Jakub Juszczak
Jakub Juszczak

Reputation: 7857

How to filter a non-scalar type in AppSync / Amplify

I am using aws-amplify to define my appsync schema.

I have following simplified schema:

type Country @model {
  id: ID!
  name: String!
  code: String!
  tracks: [Track] @connection(name: "CountryTrack")
}

type Track @model
  id: ID!
  name: String!
  country: Country! @connection(name: "CountryTrack")
  lng: Float
  lat: Float
  length: Float
  curves: Int
  website: String
  trackImage: String
  information: String
}

Amplify generates the FilterInput for the models. However it does not include the connection types.

I want to filter a Track based on the Country.

The dynamodb tables does have a trackCountryId and in the scan operation I can simply filter based on the id.

However this does not work in the graphql schema. Because the trackCountryId is not included into the FiterInput.

Does anyone know how to work around this?

Upvotes: 4

Views: 1422

Answers (1)

Shankar Raju
Shankar Raju

Reputation: 4546

Amplify CLI creates listTracks query+resolver, and tracks resolver on the Country type, out of the box. If you would like to filter all Tracks based on a countryId, you would have to add this manually in the following steps, which are essentially a mix of the above generated query+resolvers:

-> In your Schema: Add this within the type Query, and then click on "Save Schema":

listTracksByCountry(countryId: ID!, limit: Int, nextToken: String, sortDirection: ModelSortDirection): ModelTrackConnection

-> Attach a Resolver to this query field you just added, and click on "Save Resolver":

  • Pick the TrackTable as your Data source name

  • RequestMapping template:

#set( $limit = $util.defaultIfNull($context.args.limit, 10) )
{
  "version": "2017-02-28",
  "operation": "Query",
  "query": {
      "expression": "#connectionAttribute = :connectionAttribute",
      "expressionNames": {
          "#connectionAttribute": "trackCountryId"
    },
      "expressionValues": {
          ":connectionAttribute": {
              "S": "$context.args.countryId"
      }
    }
  },
  "scanIndexForward":   #if( $context.args.sortDirection )
    #if( $context.args.sortDirection == "ASC" )
true
    #else
false
    #end
  #else
true
  #end,
  "filter":   #if( $context.args.filter )
$util.transform.toDynamoDBFilterExpression($ctx.args.filter)
  #else
null
  #end,
  "limit": $limit,
  "nextToken":   #if( $context.args.nextToken )
"$context.args.nextToken"
  #else
null
  #end,
  "index": "gsi-CountryTrack"
}
  • ResponseMapping template:
#if( !$result )
  #set( $result = $ctx.result )
#end
$util.toJson($result)

-> Navigate to the Queries section on the Console, and run the following query:

query {
  listTracksByCountry(countryId: "countryId1") {
    items {
      id
      name
      length
    }
  }
}

You should be able to get a list of tracks for the countryId you specified. In my case, the GraphQL output for the above operation was:

{
  "data": {
    "listTracksByCountry": {
      "items": [
        {
          "id": "trackId1",
          "name": "track name 1",
          "length": 1.1
        },
        {
          "id": "trackId2",
          "name": "track name 2",
          "length": 1.2
        }
      ]
    }
  }
}

This seems to be a very common use case, so feel free to create an issue here, if it doesn't exist already, and we can then have Amplify CLI (amplify add api), generate these resolvers automatically.

Upvotes: 1

Related Questions