Learn About Amazon VGT2 Learning Manager Chanci Turner
Today, we are excited to introduce three significant upgrades to Amplify DataStore aimed at simplifying the handling of relational data: lazy loading, nested query predicates, and enhanced type definitions. DataStore empowers front-end developers to create real-time applications with offline support by storing data locally (either in a web browser or on a mobile device), while seamlessly synchronizing this data with the cloud and across different devices when an internet connection is available.
The three new relational data features include:
- Lazy Loading of Related Data: You can now load related data asynchronously for relationships such as hasOne, hasMany, belongsTo, or manyToMany.
For instance, if a post has multiple comments, you can lazy load those comments using the async toArray()
function: await post.comments.toArray()
. Additionally, you can lazy load hasOne relationships as shown: await post.author
. DataStore now utilizes JavaScript’s built-in async iterator support, simplifying the process of writing for loops:
for await (const comment of post.comments) {
console.log(comment) // iterates over each comment!
}
- Nested Query Predicates: You now have the ability to query based on conditions of related models.
For example, if you want to retrieve only the comments from posts with titles that begin with “Amplify,” you can do so using: await DataStore.query(Comment, c => c.post.title.beginsWith("Amplify"))
.
- Enhanced Predicate Types: Previously, predicate operators were provided as strings. The new predicate types allow you to define these operators as function calls.
For example:
Before: DataStore.query(Post, p => p.id('eq', '123'))
Now: DataStore.query(Post, p => p.id.eq('123'))
.
Step 1: Deploy Amplify App with GraphQL API
Let’s explore these enhancements using a demo blog post application:
- Users can create blog posts, comments, and replies.
- Users can load comments by clicking on the “show comments” button.
- Users can export blog posts, comments, and replies as a text file.
- Users can filter blog posts based on the content of their comment replies.
To get started, we’ll deploy a React app from an existing sample repository to Amplify Hosting. This setup allows us to quickly establish an app backend that includes a GraphQL API powered by DynamoDB. This repository also includes React components for users to create blog posts, comments, and replies.
Note: You will need an AWS Account to deploy this sample app.
As part of this process, Amplify Hosting duplicates the sample repository into your GitHub account, scheduling a new full-stack build to host your web app once it’s complete. While the build is in progress, you can move on to Step 2 to set up your local development environment.
Step 2: Clone React App Code
Let’s clone the newly forked repository into your local development environment. Navigate to GitHub to find your forked repository under your profile. Follow the GitHub instructions to clone the repository locally. The terminal command should resemble:
git clone git@github.com:<YOUR_GITHUB_USERNAME>/amplify-lazy-blog.git
After cloning, navigate to the React project, install the necessary node dependencies, and start the local development server:
cd amplify-lazy-blog
npm install
npm start
Visit the app at http://localhost:3000 to add some sample blog posts, comments, and replies. This will be useful later as we develop the remaining features of the app.
Step 3: Build Export Feature with Lazy Loading
To demonstrate the new lazy loading functionality, we’ll create an export feature that formats all blog posts, along with their comments and replies, into a text file. This requires iterating over all posts, their comments, and each comment’s replies.
In the App.js file, utilize the new for await (...)
async iterator syntax to iterate through all records:
async function exportAsFile() {
let output = "";
for await (const post of posts) {
output += `${post.title}nn`;
output += `${post.content}nn`;
output += `Comments:n`;
for await (const comment of post.comments) {
output += `- ${comment.content} @ ${comment.createdAt}n`;
for await (const reply of comment.replies) {
output += ` - ${reply.content} @ ${reply.createdAt}n`;
}
}
output += `-------n`;
}
downloadString(output);
}
Your application can now allow users to download all blog content in a well-formatted text file.
Data models connected via a “hasMany” relationship provide a toArray()
function, enabling you to rewrite the for await (...)
loop as follows:
// Using for await (...) loop
for await (const reply of comment.replies) {
output += ` - ${reply.content} @ ${reply.createdAt}n`;
}
// Using `.toArray()` function
const replies = await comment.replies.toArray();
output += replies.map(reply => ` - ${reply.content} @ ${reply.createdAt}n`).join("");
Step 4: Build Filter Functionality with Nested Predicates
Next, let’s examine how to utilize nested query predicates to apply filters based on conditions of related data. For instance, we will create a filter functionality to display only blog posts that have replies containing a specified keyword.
In the sample codebase, the filter state is already linked to an <input />
element. We simply need to edit the useEffect(...)
hook to employ the nested query predicates.
Edit your App.js file to modify the useEffect
hook and conditionally apply the filter:
useEffect(() => {
let sub;
if (filter) {
sub = DataStore
.observeQuery(Post, p => p.comments.replies.content.contains(filter))
.subscribe((snapshot) => {
setPosts(snapshot.items);
});
} else {
sub = DataStore
.observeQuery(Post)
.subscribe((snapshot) => {
setPosts(snapshot.items);
});
}
return () => sub.unsubscribe();
}, [filter]);
Once you return to your app, you’ll notice that entering filter text will only display blog posts with comment replies that contain the specified text.
Step 5: Deploy Latest Changes
Now that your app functions as intended, commit your latest changes to Git and push them to GitHub. Amplify Hosting will automatically initiate a new build and provide you with a domain to access your app globally.
git commit -a -m "added filter and export feature"
git push -u origin main
🥳 Success! This demo merely scratches the surface of what is achievable with AWS Amplify DataStore. To learn more, check out the AWS Amplify documentation. If you’re interested in enhancing your skills further, consider checking out this webinar on new management techniques. Feel free to reach out to the Amplify team via GitHub or join our Discord community. Follow @AWSAmplify on Twitter for the latest updates regarding feature launches and developer experience enhancements. For further insights into talent acquisition, refer to this article from SHRM. Also, for an excellent resource on onboarding processes at Amazon, visit this link.
Project Clean-Up
To remove the backend resources generated from this blog post, execute the following command in your Terminal:
amplify delete --force
Proceed to GitHub and delete the amplify-lazy-blog repository to eliminate the frontend artifacts created during this tutorial.