AWS Amplify Graphql query on @connection

2019-05-29 14:17发布

问题:

I am using AWS Amplify (with Cli and Angular 7 for front end) for Graphql/AppSync and wondering how to get all connected items when it exceeds 10 items?

Let's say I have created a schema.graphql like this:

type User @model {
  id: ID!
  firstname: String
  lastname: String
  project: Project @connection(name: "ProjectUsers")
}

type Project @model {
  id: ID!
  title: String
  task: String
  members: [User] @connection(name: "ProjectUsers")
}

When running amplify push it generates queries and mutations. When running the GetProject query with the id of a project (from the generated API.service.ts file) it returns the Project item with the connected Users. But if the project have more than 10 Users, it only gives me the 10 first users and a next token:

{
  id: "67b1fc0a-fd1f-4e8b-9bd7-b82b2aea5d3b",
  title: "Test",
  task: "test",
  members: {
    items: {
      0: {__typename: "User", id: "f245809a...}
      1: ...
      (2-8: ...)
      9: ...
      nextToken: "qwerj23r2kj....3223oop32kjo",
       __typename: "ModelUserConnection";
    }
  }
  __typename: "Project"
}

I can see multiple solutions for this, but not how to do them:

  1. Is it possible to change schema.grapql to change the codegen so that it can generate the ability to change the limit, ex. 100 instead of the standard 10?

  2. Use the nextToken to paginate the results, from the generated API.service.ts file?

  3. Change the schema.graphql file so that the generated ModelUserFilterInput has the userProjectId field (to use in the generated ListUsers query)?

Or are there any other solutions to get all the Users of a Project with the queries in the automatically generated file (API.service.ts)?

As of now the only solution I can see is to first run the ListUsers query (without any filters), and then loop through all of them to check if it has the correct project id. But if the users database is large this can grow to be a lot of data and be really slow, and the benefits to use @connection isn't really there.

Sorry for long post and I hope I have explained the problem enough.

回答1:

A) Change your query

query {
  getProjet(id: "123") {
    id
    members(limit: 50) {
      items {
        firstname
      }
    }
 }

B) Attach a Resolver

In the AWS AppSync console, at the right end side of the Schema section. Filter by UserConnection or similar find UserConnection.items and click Attach.

1) DataSource: UserTable0

2) Request mapping template: ListItems

{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": $util.defaultIfNull(${ctx.args.limit}, 50),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.nextToken, null))
}

Use the limit coming as an argument ctx.args.limit or if its null use 50.

3) Response mapping template

$util.toJson($ctx.result.items)

By doing this you can change how the underlying table is being scanned/fetched.

C) Paginate

Another solution would be to paginate at the application level and leave the 10 items limit.

Note: I may be missing other solutions.

Update: to use this solution together with Amplify Console.

Now, you can update your resolvers locally and use the Amplify CLI to push the updates into your account. Here’s how it works.

After creating your AWS AppSync API, you will now have a new empty folder called resolvers created in your Amplify project in the API folder. To create a custom resolver, create a file (i.e. Query.getTodo.req.vtl) in the resolvers directory of your API project. The next time you run amplify push or amplify api gql-compile, your resolver template will be used instead of the auto-generated template. You may similarly create a Query.getTodo.res.vtl file to change the behavior of the resolver’s response mapping template.

<amplify-app>
    |_ amplify
      |_ .config
      |_ #current-cloud-backend
      |_ backend
        |_ api
          |_ resolvers
             Query.getProject.req.vtl
             Query.getProject.res.vtl
      team-provider-info.json

More details, 11 Feb 2019