Is there a simple way to get a list of items by a set of ids?
** Which Category is your question related to? ** API
** What AWS Services are you utilizing? ** AppSync, Amplify
** Provide additional details e.g. code snippets ** Is there a simple way to write a resolver to get a list of items from a table by passing in a set of ids?
I'm currently solving this problem by building a filter expression string rather manually (this is a function for a pipeline resolver):
#set( $expValues = {} )
#set( $expression = "#id IN (" )
#set( $ids = $ctx.stash.get("ids"))
#set( $index = 0 )
#foreach( $id in $ids )
#set( $index = $index + 1 )
#if( $ids.size() == $index )
#set( $expression = "${expression} :id${index})" )
#else
#set( $expression = "${expression} :id${index}, " )
#end
$util.qr( $expValues.put(":id${index}", { "S" : "${id}" }) )
#end
{
"operation" : "Scan",
"filter" : {
"expression" : "${expression}",
"expressionNames": {
"#id" : "id"
},
"expressionValues" : $util.toJson($expValues)
}
}
Is this the best way? For example, I noticed there was a utility, $util.transform.toDynamoDBFilterExpression and tried implementing it as suggested from @mikeparisstuff 's answer on StackOverflow: https://stackoverflow.com/questions/52046495/util-transform-todynamodbfilterexpression
But I kept getting errors in the response about $util and expecting 'null', 'true', or 'false'. So I had to resort to the above approach.
It would be nice to have a better way to build complex queries as DynamoDB-JSON is a bit painful to write. I was hoping to be able to use similar filters (with OR: [{ id: "123" }, {id: "124"}] -type constructs that AppSync/Amplify already provides at the API level, but at the resolver level.
To get a set of values based on id, you should use the BatchGetItem resolver operation as outlined here https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-dynamodb-batch.html. This is currently a bit tough to use when using multiple environments because you need to know the table name in the resolver and ideally would be encapsulated as a transformer such as @batchGet. We have plans to open up the CLI such that you can run custom transformers and that would be the best way to get this working in a reproducible manner.
@mikeparisstuff, have there been any recent developments into making this work with multiple environments?
+1, is there any way to do this more easily now?
The batchGet is actually the best shot at doing this, although you will be limited to 100 items (https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html). The sole problem at the moment, however, is that as far as I know, we are not able to inject any environment variables such as the table name - which is required for the BatchGetItem - into the custom resolver.
This is supposedly tracked in aws-amplify/amplify-category-api#408. Maybe somebody in the near future will find some time to dig deep into it and find a way to make this work.
Other than that, I think, you can pretty much only run the expensive scan with the filter expression.
Or instead, in case you are using GraphQL, you can run the list query with a filter. This should already be a scan with the filter, depending on where you want to have your logic for building the filter.
Oh, aws-amplify/amplify-category-api#415 ist also talking about this. I don't know, what the pricing implications are, but if you really need a batchGet you can of course always lean back to a lambda for the resolver. Lambdas can be added with amplify add function and detailed configuration which other resources access is required to.
any updates on this?
any updates on this?
It’s 2023 already, any updates on this?
the future called and is asking for updates?
Yeah this is still needed
Hello from the future of 2025!