2

I am new to dynamodb but worked with MongoDB relationship. I am very confused while reading aws docs for dynamodb one to many relationship.

So my scenario is:

For example, I have tables user and addresses:

Table: User
----
username
fname
lname
address: ref to addresses

Table: Addresses
----------
address line 1
address line 2
city
Zip
state
country

Can you please help me how to achieve this in dynamodb.

  1. How to Store relational data?
  2. Retrieve data including relational in a single query?
navjotdhanawat
  • 333
  • 1
  • 3
  • 13

2 Answers2

3

DynamoDB is not a relational database. You cannot perform the type of relational requests that you are thinking about (particularly in a single query as described in your question #2). It requires a different way of thinking about how you will store and access your data, and accordingly it may not be the appropriate technology for your application.

Dynamo does not offer foreign keys or table joins. Each table has either a Partition Key (PK), or a combination of a Partition Key and Sort Key (SK). When a table has just a PK, it can only be queried for individual items. When it has both a PK and an SK, it can be queried for a single item by PK/SK, or it can be queried for all items that share the same PK.

One way of implementing 1-to-N data as you describe would look something like this:

Table: Users
------------
[PK] userId
username
fname
lname

Table: Addresses
----------------
[PK] userId
[SK] addressId
address line 1
address line 2
city
zip
state
country

In this layout, you would still require two calls to Dynamo to get all information for a user, including addresses. You would make a single getItem call to the Users table by that userId, and you would make a query call to the Addresses by that same userId. The first call would return the single user record, and the second call would return a list of address records, sorted by addressId.

You must manually manage your data. As there are no foreign keys, there are also no constraints or cascades. It's very easy to end up with orphaned data if you are not careful. Again, Dynamo may not be the most appropriate tool for your application.

What I've described here only scratches the surface. For anyone hoping to build enterprise software using DynamoDB for data storage, it is paramount that you have a good understanding of its architectural approach and best practices. Coming from a SQL or even MongoDB background, your intuition may lead you astray, causing you to build something that will not perform well and will be hard to debug. It is an extremely powerful tool for the right types of jobs, but you must perform due diligence to understand it first.

--

Edited to add: the approach I described above is not even a good one! AWS has shared documentation and talks about this sort of thing, including their Best Practices for DynamoDB which goes well beyond the scope of this answer.

Joe Lafiosca
  • 1,646
  • 11
  • 15
0

Using DynamoDB, it requires you to have different mindset of how you structure and access the data. It requires you to think ahead of how you query your data. It's certainly not as flexible as relational database, but what it gives you is scalability, provided you structure your data right.

  1. How to store relational data?

This is one way how you can achieve this (single table design).

pk sk data
user111 address|mumbai|1 mumbai 1, india
user111 address|mumbai|2 mumbai 2, india
user111 address|delhi|1 delhi 1, india
user222 address|chennai|1 chennai 1, india
  • Use user ID as the partition key ("pk").
  • Use user addresses as sort key ("sk").
  • User address is at the "data" field. Feel free to have as many fields as you want.
  1. Retrieve data including relational in a single query?

This is an example using AWS SDK for javascript.

const docClient = new AWS.DynamoDB.DocumentClient()

const params = {
  TableName: 'users',
  KeyConditionExpression: '#pk = :userId and begins_with(#sk, :data)',
  ExpressionAttributeNames: {
    "#pk": "pk",
    "#sk": "sk"
  },
  ExpressionAttributeValues: {
    ":userId": "user111",
    ":data": "address|"
  }
}

// get addresses
const res = await docClient.query(params).promise()

The idea here is using "begins_with" to retrieve the user addresses. This is how you model one to many relationships in DynamoDB.

For more information: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-sort-keys.html