How To Model 1-Many Relationships & Reverse Lookups In DynamoDB
Modeling common relationships in your database design.
Modeling relationships in your data is the core of any database design.
This isn’t only true with SQL but with DynamoDB as well, especially when you group multiple entities in the same table (using the single table design).
A classical database design pattern is to enable queries for one to many relationships as well as reverse lookup queries.
A reverse lookup query are simply querying the inverse of the one-to-many relationship query.
For example, i can query all courses a given student is enrolled in and then i can do a reverse lookup to find out all students enrolled in a given course.
This is a typical reverse lookup query.
In DynamoDB, we can model both one-to-many relationship queries and their reverse lookup queries by using a global secondary index (GSI).
Let’s take a look at how that works.
Modeling one-to-many relationships
Imagine a university database that stores records on courses and students.
The two most typical queries performed against the system are:
Getting all of the students enrolled in a given course
Getting all of the courses that a particular student is taking
For the first query, we can provide a courseID and retrieve the list of student records.
For the second query we can provide a studentID and retreive the list of course records.
Let’s attempt to model the first pattern in our DynamoDB base table and the second pattern in a GSI.
Base Table
Each item will be identified by a composite key: the studentID as the partition key and the courseID as the sort key.
Querying a one-to-many relationship
Now i can query all courses a student is taking by providing the studentID.
Here’s an example query:
TableName: "courses",
KeyConditionExpression: "#studentID = 'stu#101' AND begins_with(#courseID, 'cs#')
I specify that i want to retrieve all items in the stu#101 item collection (partition), whose courseID (sort key) begins with the sequence “cs#”.
Essentially that gives me all courses that student “stu#101” is enrolled in.
Modeling a Reverse Lookup
Now let’s model the reverse lookup query.
We need to model the data so that we can get all students enrolled in a given course.
With DynamoDB, this is super simple. We’ll just create a GSI and swap the partition and sort keys:
In this GSI, the base table’s partition key is now the GSI’s sort key and the base table’s sort key is now the GSI’s partition key; a simple key swap.
Performing the reverse lookup
We can now query this reverse lookup index simply.
We’ll provide a courseID and retrieve a list of enrolled students.
Here’s an example query:
TableName: "courses",
KeyConditionExpression: "#courseID = 'cs#201' AND begins_with(#studentID, 'stu#')
With virtually no effort we can satisfy both of the most common access patterns for this course system.
Conclusion
In this article, I explain how to model one-to-many relationships and reverse lookups in DynamoDB, particularly for a university database with students and courses.
By using a base table for one-to-many queries (e.g. courses a student is enrolled in) and a global secondary index (GSI) with swapped keys for reverse lookups (e.g. students enrolled in a course), both access patterns can be efficiently satisfied.
👋 My name is Uriel Bitton and I’m committed to helping you master Serverless, Cloud Computing, and AWS.
🚀 If you want to learn how to build serverless, scalable, and resilient applications, you can also follow me on Linkedin for valuable daily posts.
Thanks for reading and see you in the next one!