1

我了解如何AppSync通过附加链接到的解析器来执行地理空间查询,以查找距 gps 坐标的距离范围内的事件ElasticSesarch,如此处所述

但是,如果我希望我的客户也订阅在此距离范围内创建的新事件怎么办?

  1. 用户订阅了一个位置
  2. 如果在该位置附近创建了事件,则通知用户

我知道我可以将解析器附加到订阅类型,但是当我只想通过检查 gps 坐标之间的距离来过滤订阅时,它似乎迫使您提供数据源。

4

1 回答 1

1

这是一个很好的问题,我认为有几种方法可以解决这个问题。这里最困难的部分是,您将找到一种方法来提出“哪些订阅对此位置的事件感兴趣”这个问题。这是一种可能的前进道路。

以下假设这些架构部分:

// Whatever custom object has a location 
type Post {
  id: ID!
  title: String
  location: Location
}
input PublishPostInput {
  id: ID!
  title: String
  location: Location
  subscriptionID: ID
}
type PublishPostOutput {
  id: ID!
  title: String
  location: Location
  subscriptionID: ID
}

type Location {
  lat: Float,
  lon: Float
}
input LocationInput {
  lat: Float,
  lon: Float
}

# A custom type to hold custom tracked subscription information
# for location discover
type OpenSubscription {
  subscriptionID: ID!
  location: Location
  timestamp: String!
}
type OpenSubscriptionConnection {
  items: [OpenSubscription]
  nextToken: String
}

type Query {
  # Query elasticsearch index for relevant subscriptions
  openSubscriptionsNear(location: LocationInput, distance: String): OpenSubscriptionConnection
}
type Mutation {
  # This mutation uses a local resolver (e.g. a resolver with a None data source) and simply returns the input as is.
  publishPostToSubscription(input: PublishPostInput): PublishPostOutput
}
type Subscription {
  # Anytime someone passes an object with the same subscriptionID to the "publishPostToSubscription" mutation field, get updated.
  listenToSubscription(subscriptionID: ID!): PublishPostOutput
    @aws_subscribe(mutations:["publishPostToSubscription"])
}

假设您使用 DynamoDB 作为主要事实来源,请设置一个调用“PublishIfInRange”lambda 函数的 DynamoDB 流。“PublishIfInRange”函数看起来像这样

// event - { location: { lat, lon }, id, title, ... }
function lambdaHandler(event) {

  const relevantSubscriptions = await callGraphql(`
    query GetSubscriptions($location: LocationInput) {
      openSubscriptionsNear(location:$location, distance: "10 miles") {
        subscriptionID
      }
    }
  `, { variables: { location: event.location }})

  for (const subscription of relevantSubscriptions) {
    callGraphql(`
      mutation PublishToSubscription($subID: ID!, $obj: PublishPostInput) {
        publishPostToSubscription(input: $obj) {
          id
          title
          location { lat lon }
          subscriptionID
        }
      }
    `, { variables: { input: { ...subscription, ...event }}})
  }
}

您将需要维护按位置索引的订阅注册表。一种方法是让您的客户端应用程序调用一个突变,该突变创建一个带有位置和订阅 ID 的订阅对象(例如mutation { makeSubscription(loc: $loc) { ... } },假设您使用 $util.autoId() 在解析器中生成订阅 ID)。获得订阅 ID 后,您可以通过 graphql 进行订阅调用,并将订阅 ID 作为参数传入(例如subscription { listenToSubscription(subscriptionID: "my-id") { id title location { lat lon } } })。当您进行上述订阅调用时,AppSync 会创建一个主题并授权当前用户订阅该主题。主题对于被调用的订阅字段和传递给订阅字段的参数集是唯一的。换句话说,主题只接收对象

现在,无论何时创建对象,记录都会通过 DynamoDB 流转到 lambda 函数。lambda 函数在 elasticsearch 中查询该对象附近的所有开放订阅,然后将记录发布到每个开放订阅。

我相信这应该能让你走得更远,但如果你有数百万用户处于紧张状态,你可能会遇到扩展问题。希望这可以帮助

于 2018-07-13T00:35:50.047 回答