aws-amplify / amplify-cli

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development.
Apache License 2.0
2.81k stars 819 forks source link

how to enable sorting on query using GraphQL from AWS Amplify #2307

Closed rafaelmarques7 closed 5 years ago

rafaelmarques7 commented 5 years ago

Note: If your question is regarding the AWS Amplify Console service, please log it in the official AWS Amplify Console forum

Which Category is your question related to?

What AWS Services are you utilizing?

AWS Amplify to create backend API and database

Provide additional details e.g. code snippets

I've recently started looking into AWS Amplify. I have managed to setup an API using GraphQl. Basically, during the API creation, Amplify ask you a few questions about the API and guides you through its creation. At some point, you are requested to create a schema. The schema I selected is as follows:

type User @model {
  id: ID!
  username: String!
  email: String
}

type Highscore @model {
  points: Int!,
  id: ID!
  ownerId: ID!,
  numRounds: Int,
  date: String, 
}

with this schema, Amplify is able to generate code that allows me to do things such as:

Does anyone know how I could achieve this?

I've looked into the @key directive (https://aws-amplify.github.io/docs/cli-toolchain/graphql#key) but updating the schema to include

type Highscore @model @key((fields: ["points"] {
...
}

did not produce the expected result.

unfortunately, the code generated by Amplify using this schema does not allow sorting of the query.

I would like to be able to query all Highscores, and sort it according to the number of points.

RossWilliams commented 5 years ago

There is an answer to a similar question here.

rafaelmarques7 commented 5 years ago

There is an answer to a similar question here.

You are right. You're answer put me in the right direction, thank you :)!

Given the above, I was able to solve my problem with the following schema.

type Highscore @model @key(name: "ByPoints", fields: ["type", "points"], queryField: "getHighscoreByPoints") {
  id: ID!
  type: String!
  points: Int!
  ownerId: ID!
  numRounds: Int
  date: String
}

This allows me to query the Highscore data, and sort it by points, with the following query:

query LH {
  getHighscoreByPoints (type: "Highscore", limit: 5) {
    items {
      points
    }
  }
}

Note: to allow sorting on the sort key (second index), the primary key should be the same. In the model above, type is the primary key, and will be set to a constant value (f.e. highscore) for all highscore data entries. points is the sort key, All queries will be automatically sorted according to the sort key.

Current limitation: @RossWilliams with the above schema, I was not able to set sortDirection on the query. The current query defaults to sorting from lowest to highest, and I would like to be able to sort it from highest to lowest. I was able to get the desired query by setting points to -points, so it should be all right, In any case, do you know if I need to update the model to allow to sort by sortDirection?

Thank you for your help on this.

chrisco512 commented 5 years ago

@rafaelmarques7 I believe you can pass in sortDirection as an argument to getHighscoreByPoints. Should look something like:

query LH {
  getHighscoreByPoints (type: "Highscore", limit: 5, sortDirection: DESC) {
    items {
      points
    }
  }
}

Is that how your query is structured? Note, ASC and DESC are not strings.

rafaelmarques7 commented 5 years ago

query LH { getHighscoreByPoints (type: "Highscore", limit: 5, sortDirection: DESC) { items { points } } }

with the above query I get the following error:

"message": "Validation error of type UnknownArgument: Unknown field argument sortDirection @ 'getHighscoreByPoints'"

The getHighscoreByPoints resolver does not seem to accept sortDirection as a input argument. The resolver looks as follows:

getHighscoreByPoints(
type: String
points: ModelIntKeyConditionInput
filter: ModelHighscoreFilterInput
limit: Int
nextToken: String): ModelHighscoreConnection

@chrisco255

attilah commented 5 years ago

@rafaelmarques7 which version of the CLI are you using?

I've tried with the latest and in the compiled schema I get the right query generated:

  getHighscoreByPoints(type: String, points: ModelIntKeyConditionInput, sortDirection: ModelSortDirection, filter: ModelHighscoreFilterInput, limit: Int, nextToken: String): ModelHighscoreConnection
rafaelmarques7 commented 5 years ago

@rafaelmarques7 which version of the CLI are you using?

I've tried with the latest and in the compiled schema I get the right query generated:

  getHighscoreByPoints(type: String, points: ModelIntKeyConditionInput, sortDirection: ModelSortDirection, filter: ModelHighscoreFilterInput, limit: Int, nextToken: String): ModelHighscoreConnection

I am on version 1.7.6. Thank you for flagging that. I Will update the version and retry. Thank you for your help!

sacrampton commented 5 years ago

The way I solve this is to use the @searchable directive to stream the data to ElasticSearch. Using ElasticSearch and some custom resolvers you can do really powerful sorting (ie, sort by name ascending, then by description descending, then by date descending, etc.) and you don't have the headache of trying to plan for global secondary indexes in DynamoDB.

rafaelmarques7 commented 5 years ago

The way I solve this is to use the @searchable directive to stream the data to ElasticSearch. Using ElasticSearch and some custom resolvers you can do really powerful sorting (ie, sort by name ascending, then by description descending, then by date descending, etc.) and you don't have the headache of trying to plan for global secondary indexes in DynamoDB.

I will have a look into that as well, thank you.

I can confirm that the above schema, together with the update of the amplify version, does produce the expected result.

Thank you all for your help, unless there are other questions, this may now be closed.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels for those types of questions.