[英]How do you handle lists that require joined data from multiple data sources in AppSync/GraphQL?
type Employee {
id: String!
name: String
lastObservedStatus: String
}
type Query {
employees: [Employee]
}
This is a fictional schema to illustrate my question.这是一个虚构的模式来说明我的问题。 I have two separate data sources that return lists that need to be joined in order to populate the response.
我有两个单独的数据源,它们返回需要加入以填充响应的列表。 The first data source 'employee list api' is an http API I can query to get an authoritative list of employees that I can use to populate the
id
and name
columns.第一个数据源“员工列表 api”是 http API 我可以查询以获得可用于填充
id
和name
列的权威员工列表。 For example, I get a response like this:例如,我收到这样的回复:
[
{"id": "001", "name": "Harry"},
{"id": "002", "name": "Jerry"},
{"id": "003", "name": "Larry"}
]
I have a second http API 'employee observation log' I can query to get a list of statuses together with the associated ids.我有第二个 http API '员工观察日志' 我可以查询以获取状态列表以及相关的 ID。 The id allows me to associate the number to an entry in the employee record, and I have a record date.
id 允许我将号码与员工记录中的条目相关联,并且我有一个记录日期。 There may be more than one status record, but in GraphQL I want to pick only the most recent one.
可能有不止一条状态记录,但在 GraphQL 中我只想选择最近的一条。 Example response:
示例响应:
[
{"id":"002", "TimeStamp":"2021-07-01T12:30:00Z", "status": "eating"},
{"id":"002", "TimeStamp":"2021-07-01T13:10:00Z", "status": "staring out the window"},
{"id":"001", "TimeStamp":"2021-07-01T16:00:00Z", "status": "sleeping in lobby"}
]
Now, I want the graphQL response to return something like this:现在,我希望 graphQL 响应返回如下内容:
{
"data": {
"employees": [
{
"id": "001",
"name": "Harry",
"lastObservedStatus": "sleeping in lobby"
},
{
"id": "002",
"name": "Jerry",
"lastObservedStatus": "staring out the window"
},
{
"id": "003",
"name": "Larry",
"lastObservedStatus": null
}
]
}
}
Since 'employee list api' is the authoritative source about which employees exist, all queries to the 'employee' field should always trigger a query to that api, but the 'employee observation log' api should only be triggered if the 'lastObservedStatus' field is selected in the query.由于'employee list api'是关于哪些员工存在的权威来源,所有对'employee'字段的查询都应始终触发对该api的查询,但'employee observation log'api仅应在'lastObservedStatus'字段时触发在查询中被选中。
For a schema like this, where should the resolvers be registered?对于这样的模式,应该在哪里注册解析器? I've read that the best practice is to always attach resolvers at the leaf nodes, but I'm not sure how that can be done in this situation.
我读过,最佳做法是始终在叶节点处附加解析器,但我不确定在这种情况下如何做到这一点。 I'm not even sure what happens if you attach a resolver on subfields of a list.
我什至不确定如果您在列表的子字段上附加解析器会发生什么。
I feel like the correct way to handle this is to attach a lambda resolver to the employees
field, and in the lambda resolver check the query's selectionSetList to check whether or not the 'lastObservedStatus' field has been selected.我觉得处理此问题的正确方法是将 lambda 解析器附加到
employees
字段,并在 lambda 解析器中检查查询的 selectionSetList 以检查是否已选择“lastObservedStatus”字段。 If not, then the lambda only queries 'employee list api', but otherwise the lambda also queries 'employee observation log' and does something similar to a SQL join before returning the result.如果不是,则 lambda 仅查询“员工列表 api”,否则 lambda 还会查询“员工观察日志”,并在返回结果之前执行类似于 SQL 连接的操作。 But is that the correct way to handle this?
但这是处理这个问题的正确方法吗?
It sounds like what you need is a resolver on the lastObservedStatus
field that uses your second API ('employee observation log') as the data source, where the Query field employees
is using the first API as its data source.听起来您需要的是
lastObservedStatus
字段上的解析器,它使用您的第二个 API(“员工观察日志”)作为数据源,其中查询字段employees
使用第一个 API 作为其数据源。
This resolver should do a query using the context source field (the 'parent' values, in this case id
and name
of the Employee
which you can reference).此解析器应使用上下文源字段(“父”值,在本例中为您可以引用的
Employee
的id
和name
)进行查询。 You can reference this in the VTL code using $ctx.source.id
for example, or $ctx.source.name
if you needed the name.您可以在 VTL 代码中引用它,例如使用
$ctx.source.id
或$ctx.source.name
如果您需要名称)。
This resolver should only query the status for a single Employee, since it'll be invoked once per every result in your Query field employees
.这个解析器应该只查询单个Employee 的状态,因为它会在您的查询字段
employees
中的每个结果中调用一次。
There is another option as well, which would be to have a 2 function pipeline resolver where each function points at a different data source:还有另一种选择,即有一个 2 function 管道解析器,其中每个 function 指向不同的数据源:
lastObservedStatus
lastObservedStatus
之外的所有字段lastObservedStatus
and stitches the results with the $ctx.prev.result
.lastObservedStatus
并将结果与$ctx.prev.result
。 This will be messier to implement, but will require fewer API calls if designed properly.这实现起来会比较麻烦,但如果设计得当,将需要更少的 API 调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.