Skip to content

Hands-On Examples for Working with DynamoDB, Boto3, and Python

A helpful resource for some of the most common use cases

Building exterior | Photo by Michael Jasmund on Unsplash


In this post, we’ll get hands-on with AWS DynamoDB, the Boto3 package, and Python. In my experience, I’ve found the documentation around this technology can be scattered or incomplete. I’ll do my best to explain and provide examples for some of the most common use cases.

The easiest way to run these examples is to set up an AWS Lambda function using the Python 3.7 runtime. Also, make sure to assign a role to your function that has access to interact with the DynamoDB service.


The Basics

Let's start by creating a Users table with just a hash key:

Now that we have a table we can do an insert:

Take note of the reserved words when defining your attributes https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html

Next, we can retrieve our newly created record. There are two main techniques to do this: get_item & query (we’ll cover scans later). Both of these methods will have the same throughput. However, get_item will return a single item, and query will return a list (unless we specify limit=1). For this reason, it is a good practice to use get_item when you have all the information to do so.

get_item:

query:

Next, let's update our record:

Alternatively, we could have used the same put_item method we used to create the item with. We would just need to make sure we passed in all the attributes and values in the item (not just the 1 we wanted to update).

And finally, let's delete our record:

Scans

A Scan operation in Amazon DynamoDB reads every item in a table or a secondary index. By default, a Scan operation returns all of the data attributes for every item in the table or index. You can use the ProjectionExpression parameter so that Scan only returns some of the attributes, rather than all of them.

Using the same table from the above, let's go ahead and create a bunch of users.

Basic scan example:

We can see above that all the attributes are being returned.

Here is an example of just scanning for all first & last names in the database:

Scans have a 1mb limit on the data returned. If we think we’re going to exceed that, we should continue to re-scan and pass in the LastEvaluatedKey:

Hash + Range Key

Hash and Range Primary Key — The primary key is made of two attributes. The first attribute is the hash attribute and the second attribute is the range attribute. For example, the forum Thread table can have ForumName and Subject as its primary key, where ForumName is the hash attribute and Subject is the range attribute. DynamoDB builds an unordered hash index on the hash attribute and a sorted range index on the range attribute.

To Demonstrate this next part, we’ll build a table for books. The title will be our hash key and author will be our range key.

And here is an example using range key with some of the techniques we learned above:

Global Secondary Index (GSI)

Some applications might need to perform many kinds of queries, using a variety of different attributes as query criteria. To support these requirements, you can create one or more global secondary indexes and issue Query requests against these indexes in Amazon DynamoDB.

To illustrate this we’re going to create an Employee table with employee_id as our hash kay and email address as our GSI.

And here is an example of a query with an GSI:

At the time of writing this get_item on GSI is not supported.

Local Secondary Index (LSI)

Some applications only need to query data using the base table’s primary key. However, there might be situations where an alternative sort key would be helpful. To give your application a choice of sort keys, you can create one or more local secondary indexes on an Amazon DynamoDB table and issue Query or Scan requests against these indexes.

To demonstrate this we’re going to create a Posts table with user_name as our hash key, title as our range key and we’ll have a LSI on user_name & subject.

And here is an example of a query with an LSI:

At the time of writing this get_item on LSI is not supported

As stated in the intro, I just wanted to bring all these examples into one place. I hope that this can be a helpful resource for some of the most common use cases.