Query More Items Using Scans in AWS Amplify
Is the 1000 item limit in AWS Amplify hindering you from building your application? In this tutorial, you are going to learn how to use DynamoDB's Scan operation to query all items from a given table.
Note: This article is a tutorial for intermediates. Do you want to learn how to accelerate the creation of your projects using Amplify 🚀? For beginners, I recommend checking out Nader Dabit's free course on egghead, or Amplify's 'Getting Started' to learn the basics.
When building Amplify applications, I found myself having to query for more than a thousand entities. You are going to learn how to create these large queries using custom resolvers. We are going to use a Scan operation.
If you are unfamiliar with the resources AWS Amplify generates when you run amplify add api
, let me give you a brief overview. It produces tables for DynamoDB for each @model
directive you use. It also generates resolvers that tell AppSync how given a GraphQL request it should read or write this data from/to DynamoDB. These resolvers are written in .vtl
files and utilize the "Apache Velocity Template Language". It looks like JSON with some logic.
The flaw with the resolvers that Amplify generates is that they are being filtered in the velocity templates. And .vtl
files come with the restriction that for loops needn't exceed 1000 iterations. This is where the 1000 entity limit comes from. We are going to use a Scan operation and DynamoDB's build in filter method to circumvent this limit. Keep in mind that using this Scan the limit for the items queried is 1MB before filtering the results.
I'm going to walk you through the setup using a regular todo example. Feel free to code along.
Start by creating a new React app and adding Amplify.
Consequently, add the API with authentication.
Choose Amazon Cognito User Pool
as your way of authentication and go with the simple todo schema. Push your changes using amplify push
.
Next, modify your schema to reflect the following.
We added authentication so we can filter items by owner. Furthermore, we added a new query called scanTodos
that returns a nested attribute items
, which is a list of Todo
s.
We need to modify the "Resources"
key in amplify/api/<your-api-name>/stacks/CustomResources.json
.
We declared two resolver templates as new resources, one for the GraphQL request and one for the response. Let's write their respective templates. We start with the request (amplify/api/<your-api-name>/resolvers/Query.scanTodos.req.vtl
).
This template is pretty easy to understand. We first get the user from the request. Next, we declare a new request that executes the Scan
operation. And then we filter by owner. The expression
is equals, and the value is the user we extracted earlier. Lastly, we need to give owner
the alias #owner
using expressionNames
because the word "owner" is a reserved word in DynamoDB.
The response template in amplify/api/<your-api-name>/resolvers/Query.scanTodos.res.vtl
is straight forward.
We merely return the result. Run amplify push
to deploy your changes.
Now configure Amplify in index.js
.
Remember to create a user in the Cognito console. To conclude the example, we will render the todo count and create a thousand todos, if there are less than that.
The code is pretty self-explanatory. asyncForEach
avoids race conditions. range
is a helper to fill an array with numbers between two bounds. And we have a useEffect
that logs the user in, gets all todos using our scanTodos
query and counts them. If there are less than a thousand, we create them. We also log in the console when the creation starts and when it ends so you know what's going on because creating a thousand todos can take a while.
Run the app, and after you see "Done creating. Reload your app."
reload it. Your counter should now be at 1001. If it is you just did a query for more than a thousand entities 👏🏻. Good job! If you followed this tutorial, you can clear everything up by running amplify delete
.
If you liked this article, you might also enjoy "Creating GraphQL Batch Operations for AWS Amplify" because we also use custom resolvers in it.