I am creating an AppSync api with the following schema:
schema {
query: Query
}
type Query {
getUser(id: String): User!
}
type User {
DDBpk: String!
DDBsk: String!
DDBproperty1: String!
DDBproperty2: String!
emailAddress: String!
emailAddressVerified: Boolean!
CreateDate: String
}
Now the first 4 fields all come from a dynamo db table that is called from a resolver attached to the getUser
Query but the last three fields come from aws-cognito. Now I have a lambda data source that gets all three of these fields but if I attach it to each field It calls the cognate api three times, which is very wasteful, is there a way to resolve all three fields with one resolver to prevent this?
4
Answers
In AppSync, resolvers and fields in a GraphQL schema have 1:1 relationships.
If you have data sources on each field, they will be triggered independently.
Looking at the
User
type, we can attach data sources in a few ways:1) Attach data source in each field of
User
This approach is what you are doing at the moment. You need 7 data sources to resolve the
User
entity.2) Group fields in a different type and add a resolver to it
You can attach a data source to a type with the fields you want:
With the schema above, you attach a data source to
User.UserDetails
that returns all the fields fromUserDetails
. You are reducing the number of data sources to 5.Notes: if you resolve everything in
User.UserDetails
, no other query can useUserDetails
, because there’s no data source attached to the fields of the type.You may need to pay attention to which queries x fields use the
UserDetails
type.3) Resolve everything in the main
getUser
The resolver attached to
getUser
can return the complete response. You don’t need to attach a resolution for each field.The
$ctx
includes all information you need to query multiple databases/services from within the resolver.Pseudo-code:
The same Notes from item 2) apply to this approach.
yes instead of binding schema to dynamo and lambda you can simply combine them and get data from lambda directly i.e
you can use a resolver to fetch all three fields from AWS Cognito and return them in a single response to the client :
Define a new type that includes all three fields from AWS Cognito:
Note: Ignore the syntax there might be some change required.
The issue you have is that each resolver is called once per field. If you want to reduce the number of calls you basically have two options :
Batch Lambda resolvers won’t help in that case because only batches with the same field name.
One way to resolve multiple fields from multiple datasources with AppSync is by using Pipeline Resolvers.
It will call the two resolvers sequentially, allowing you to use multiple datasources.
It basically work like this :
Basically you can’t, you should use a pipeline resolver attached to the query:
https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html
In this way you can fetch dynamo data in the first function, store the result received in the response in the context stash, and then retrieve the cognito data in the second function.
At the end you can return the complete User in the response mapping template.