AppSync/GraphQL filter nested objects

616 Views Asked by At

I have a DynamoDB table with the following structure

site           (String)
addresses      (List)
 |-> address   (String)
 |-> isCurrent (Boolean)

I want to filter a specific site for either current or all address(s).

query MyQuery {
  getSite(site: "site1", isCurrent: true) {
    site
    addresses{
       adress
       isCurrent
    }

the schema looks like

type Sites{
site: String!
addresses: [Address]
}

type Address {
address: String
isCurrent: Boolean
}

type Query{
getSite(site: String!, isCurrent:Boolean)
}

The Resolver I have

#if($ctx.args.isCurrent)
{
    "version": "2017-02-28",
    "operation": "Query",
    "query": {. // Filter for specific Site
        "expression": "#siteName = :siteNameByUser",
        "expressionNames": {
            "#siteName": "site"
        },
        "expressionValues": {
            ":siteNameByUser": {"S": $util.toJson($ctx.args.site)}
        }
    }, // Filter Current Address(s)
        "filter": {
        "expression": "addresses.isCurrent = :isActiveByUser",
        "expressionValues": {
            ":isActiveByUser": $util.dynamodb.toDynamoDBJson($ctx.args.isCurrent)      
    }
  }
}
#else
{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "site": $util.dynamodb.toDynamoDBJson($ctx.args.site)
    }
}
#end

I'm not getting any results when I add filter ( it works without the filter or with isCurrent=False ). I am trying to filter the inner objects in Addresses list based on a value user sends for isCurrent. Any help is much appreciated!

I tried writing a resolver with a filter condition on an inner value (addresses.isCurrent).

{
    "version": "2017-02-28",
    "operation": "Query",
    "query": {. // Filter for specific Site
        "expression": "#siteName = :siteNameByUser",
        "expressionNames": {
            "#siteName": "site"
        },
        "expressionValues": {
            ":siteNameByUser": {"S": $util.toJson($ctx.args.site)}
        }
    }, // Filter Current Address(s)
        "filter": {
        "expression": "addresses.isCurrent = :isActiveByUser",
        "expressionValues": {
            ":isActiveByUser": $util.dynamodb.toDynamoDBJson($ctx.args.isCurrent)      
    }
  }
}
1

There are 1 best solutions below

0
On BEST ANSWER

Apparently, DynamoDB does not let you filter on Complex object types like List of Maps (your case), see a related question: DynamoDB: How to store a list of items

I'd suggest changing your DynamoDB table data model if possible to site, address, isCurrentAddress to achieve what you are trying to do. Or you can write logic in VTL response mapping template to filter your result set based on isCurrentAddress value. Btw AppSync recently launched JavaScript resolvers, go through that and see if that helps in writing your resolver logic simpler.