Boto3 DynamoDB

Introduction

In this Boto3 DynamoDB tutorial, we’ll walk through the process of creating tables, loading data, and executing fundamental CRUD operations in AWS DynamoDB using Python and the Boto3 library.

Boto3, the Python SDK for AWS, is primarily known for its two widely used features: Clients and Resources.

  • boto3 dynamodb client provides a low-level interface to the AWS service. It maps 1:1 with the actual AWS service API.
  • In another way, boto3 dynamodb resource are a higher-level abstraction compared to clients. It provides an object-oriented interface for interacting with various AWS services. Resources aren’t available for all AWS services.

In this tutorial, we use Boto3 DynamoDB resource methods.

Boto3 DynamoDB Prerequisites

Before starting, you should have the following prerequisites configured

  • An AWS account
  • AWS CLI on your computer
  • Download and unzip the sample source code from GitHub

Boto3 DynamoDB CRUD Operations example

  • Create table
  • Batch Write Items
  • Read Item
  • Add new item
  • Full scan table
  • Update item
  • Delete item
  • List all table
  • Delete table

Create table

The CreateTable operation adds a new table to your account. In an Amazon Web Services account, table names must be unique within each Region. That is, you can have two tables with the same name if you create the tables in different Regions.

CreateTable is an asynchronous operation. We can wait to create a process with wait_until_exists() method Upon receiving a CreateTable request, DynamoDB immediately returns a response with a TableStatus of CREATING. After the table is created, DynamoDB sets the TableStatus to ACTIVE. You can perform read-and-write operations only on an ACTIVE table.

The following code example shows how to create a DynamoDB table.

Python (Boto3)

def create_table(self, table_name):
        """
        Creates an Amazon DynamoDB table that can be used to store forum data.
        The table partition key(S): Name 

        :param table_name: The name of the table to create.
        :return: The newly created table.
        """
        try:
            self.table = self.dyn_resource.create_table(
                TableName=table_name,
                KeySchema=[
                    {'AttributeName': 'Name', 'KeyType': 'HASH'},  # Partition key
                ],
                AttributeDefinitions=[
                    {'AttributeName': 'Name', 'AttributeType': 'S'}
                ],
                ProvisionedThroughput={'ReadCapacityUnits': 10, 'WriteCapacityUnits': 5})
            self.table.wait_until_exists()
        except ClientError as err:
            logger.error(
                "Couldn't create table %s. Here's why: %s: %s", table_name,
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise
        else:
            return self.table

Call function to create table as bellow

forums = Forum(dynamodb)
    #Check for table existence, create table if not found
    forums_exists = forums.exists(table_name)
    if not forums_exists:
        print(f"\nCreating table {table_name}...")
        forums.create_table(table_name)
        print(f"\nCreated table {forums.table.name}.")

This command returns the following result.

Boto3 DynamoDB create table

Batch Write Items

The BatchWriteItem operation puts or deletes multiple items in one or more tables. A single call  BatchWriteItem can transmit up to 16MB of data over the network, consisting of up to 25 item put or delete operations. While individual items can be up to 400 KB once stored, it’s important to note that an item’s representation might be greater than 400KB while being sent in DynamoDB’s JSON format for the API call.

BatchWriteItem cannot update items. 

If DynamoDB returns any unprocessed items, you should retry the batch operation on those items. However, AWS strongly recommends that you use an exponential backoff algorithm. If you retry the batch operation immediately, the underlying read or write requests can still fail due to throttling on the individual tables. If you delay the batch operation using exponential backoff, the individual requests in the batch are much more likely to succeed.

For more information, see Batch Operations and Error Handling in the Amazon DynamoDB Developer Guide & Exponential Backoff And Jitter

The following code example shows how to write a batch of DynamoDB items.

def write_batch(self, forums):
        """
        Fills an Amazon DynamoDB table with the specified data, using the Boto3
        Table.batch_writer() function to put the items in the table.
        Inside the context manager, Table.batch_writer builds a list of
        requests. On exiting the context manager, Table.batch_writer starts sending
        batches of write requests to Amazon DynamoDB and automatically
        handles chunking, buffering, and retrying.

        :param forums: The data to put in the table. Each item must contain at least
                       the keys required by the schema that was specified when the
                       table was created.
        """
        try:
            with self.table.batch_writer() as writer:
                for forum in forums:
                    writer.put_item(Item=forum)
        except ClientError as err:
            logger.error(
                "Couldn't load data into table %s. Here's why: %s: %s", self.table.name,
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise

Call function to write data to DynamoDB as below

    #Load data into the created table
    forum_data = forums.get_sample_forum_data(forum_file_name)
    print(f"\nReading data from '{forum_file_name}' into your table.")
    forums.write_batch(forum_data)
    print(f"\nWrote {len(forum_data)} forums into {forums.table.name}.")
    print('-'*88)

This command returns the following result.

Boto3 DynamoDB batch write into table

Read Item

The GetItem operation returns a set of attributes for the item with the given primary key. If there is no matching item, GetItem do not return any data and there will be no Item element in the response.

GetItem provides an eventually consistent read by default. If your application requires a strongly consistent read, set ConsistentRead to true

The following code example shows how to get an item from a DynamoDB table.

    def get_forum(self, name):
        """
        Gets forum data from the table for a specific forum.

        :param name: The name of the forum.
        :return: The data about the requested forum.
        """
        try:
            response = self.table.get_item(Key={'Name': name})
        except ClientError as err:
            logger.error(
                "Couldn't get forum %s from table %s. Here's why: %s: %s",
                name, self.table.name,
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise
        else:
            return response['Item']

Call function to get data items from DynamoDB as below

    #Get forum data with hash key = 'Amazon DynamoDB'  
    forum = forums.get_forum("Amazon DynamoDB")
    print("\nHere's what I found:")
    pprint(forum)
    print('-'*88)

This command returns the following result.

Boto3 DynamoDB get data from table

Add new item

Creates a new item, or replaces an old item with a new item. If an item that has the same primary key as the new item already exists in the specified table, the new item completely replaces the existing item. You can perform a conditional put operation (add a new item if one with the specified primary key doesn’t exist), or replace an existing item if it has certain attribute values. You can return the item’s attribute values in the same operation, using the ReturnValuesparameter.

The following code example shows how to put an item in a DynamoDB table.

    def add_forum(self, name, category, messages, threads, views):
        """
        Adds a forum to the table.

        :param name: The name of the forum.
        :param category: The category of the forum.
        :param messages: The messages of the forum.
        :param threads: The quality threads of the forum.
        :param views: The quality views of the forum.
        """
        try:
            self.table.put_item(
                Item={
                    'Name': name,
                    'Category': category,
                    'Messages': messages,
                    'Threads': threads,
                    'Views': views
                    })
        except ClientError as err:
            logger.error(
                "Couldn't add forum %s to table %s. Here's why: %s: %s",
                name, self.table.name,
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise

Call function to add item from DynamoDB as below

    #Add new forum data with hash key = 'SQL server'
    forums.add_forum("SQL server","Amazon Web Services",4,2,1000)
    print(f"\nAdded item to '{forums.table.name}'.")
    print('-'*88)

This command returns the following result.

Boto3 DynamoDB add item into table

Full scan table

The Scan operation returns one or more items and item attributes by accessing every item in a table or a secondary index. To have DynamoDB return fewer items, you can provide an FilterExpression operation.

If the total size of scanned items exceeds the maximum dataset size limit of 1 MB, the scan completes and results are returned to the user. The LastEvaluatedKey value is also returned and the requestor can use the LastEvaluatedKey to continue the scan in a subsequent operation. 

The following code example shows how to scan a DynamoDB table.

   def scan_forums(self):
        """
        Scans for forums.

        :param n/a
        :return: The list of forums.
        """
        forums = []
        scan_kwargs = {}
        try:
            done = False
            start_key = None
            while not done:
                if start_key:
                    scan_kwargs['ExclusiveStartKey'] = start_key
                response = self.table.scan(**scan_kwargs)
                forums.extend(response.get('Items', []))
                start_key = response.get('LastEvaluatedKey', None)
                done = start_key is None
        except ClientError as err:
            logger.error(
                "Couldn't scan for forums. Here's why: %s: %s",
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise

        return forums

Call function to scan items from DynamoDB as below

    #Full scan table
    releases = forums.scan_forums()
    if releases:
        print(f"\nHere are your {len(releases)} forums:\n")
        pprint(releases)
    else:
        print(f"I don't know about any forums released\n")
    print('-'*88)

This command boto3 dynamodb scan returns the following result.

Boto3 DynamoDB scan table

Update item

Edits an existing item’s attributes, or adds a new item to the table if it does not already exist. We can put, delete, or add attribute values. We can also perform a conditional update on an existing item (insert a new attribute name-value pair if it doesn’t exist, or replace an existing name-value pair if it has certain expected attribute values).

We can also return the item’s attribute values in the same UpdateItem operation using the ReturnValues parameter.

The following code example shows how to update an item in a DynamoDB table.

    def update_forum(self, name, category, messages, threads, views):
        """
        Updates rating and plot data for a forum in the table.

        :param name: The name of the forum.
        :param category: The category of the forum.
        :param messages: The messages of the forum.
        :param threads: The quality threads of the forum.
        :param views: The quality views of the forum.
        :return: The fields that were updated, with their new values.
        """
        try:
            response = self.table.update_item(
                Key={'Name': name},
                UpdateExpression="set Category=:c, Messages=:m, Threads=:t, #Views=:v",
                ExpressionAttributeValues={
                    ':c': category,
                    ':m': messages,
                    ':t': threads,
                    ':v': views
                    },
                ExpressionAttributeNames={"#Views" : "Views"},
                ReturnValues="UPDATED_NEW")
        except ClientError as err:
            logger.error(
                "Couldn't update forum %s in table %s. Here's why: %s: %s",
                name, self.table.name,
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise
        else:
            return response['Attributes']

Call function to update an item of DynamoDB as below

    #Update data: update forum quality views from 1000 to 2000
    updated = forums.update_forum("SQL server","Amazon Web Services",4,2,2000)
    print(f"\nUpdated :")
    pprint(updated)
    print('-'*88)

This command returns the following result.

Boto3 DynamoDB update item of table

Delete item

Deletes a single item in a table by primary key. You can perform a conditional delete operation that deletes the item if it exists, or if it has an expected attribute value.

In addition to deleting an item, you can also return the item’s attribute values in the same operation, using the ReturnValues parameter.

Unless you specify conditions, the DeleteItem is an idempotent operation; running it multiple times on the same item or attribute does not result in an error response.

The following code example shows how to delete an item from a DynamoDB table.

    def delete_forum(self, name):
        """
        Deletes a forum from the table.

        :param name: The title of the forum to delete.
        """
        try:
            self.table.delete_item(Key={'Name': name})
        except ClientError as err:
            logger.error(
                "Couldn't delete forum %s. Here's why: %s: %s", name,
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise

Call function to delete the item of DynamoDB as below

    #Delete data
    forums.delete_forum("SQL server")
    print(f"\nRemoved item from the table.")
    print('-'*88)
    ##Full scan table
    releases = forums.scan_forums()
    if releases:
        print(f"\nHere are your {len(releases)} forums:\n")
        pprint(releases)
    else:
        print(f"I don't know about any forums released\n")
    print('-'*88)

This command returns the following result.

Boto3 DynamoDB delete item of table

List all table

Returns an array of table names associated with the current account and endpoint. The output from ListTables is paginated, with each page returning a maximum of 100 table names default.

The following code example shows how to list DynamoDB tables.

    #List all table
    print('-'*88)
    print(f"Table list:\n")
    print(list(dynamodb.tables.all()))

This command returns the following result.

list DynamoDB tables

Delete table

Deletes a single item in a table by primary key. You can perform a conditional delete operation that deletes the item if it exists, or if it has an expected attribute value.

In addition to deleting an item, you can also return the item’s attribute values in the same operation, using the ReturnValues parameter.

Unless you specify conditions, the DeleteItem is an idempotent operation; running it multiple times on the same item or attribute does not result in an error response.

The following code example shows how to delete an item from a DynamoDB table.

    def delete_table(self):
        """
        Deletes the table.
        """
        try:
            self.table.delete()
            self.table = None
        except ClientError as err:
            logger.error(
                "Couldn't delete table. Here's why: %s: %s",
                err.response['Error']['Code'], err.response['Error']['Message'])
            raise

Call function to delete the item of DynamoDB as below

   #Delete table
    forums.delete_table()
    print(f"Deleted {table_name}.")

This command returns the following result.

image 78

Conclusion

These steps provide an example CRUD Operations using Boto3 DynamoDB. The specific configuration details may vary depending on your environment and setup. It’s recommended to consult the relevant documentation from AWS for detailed instructions on setting up. I hope this will your helpful. Thank you for reading the DevopsRoles page!

Boto3 DynamoDB Refer to:

About Dang Nhu Hieu

I'm Vietnamese. In the past, I'm a software developer, now working in Japan on an Infra team. Skill : AWS, VMware, HA architech,setting Database : Oracle DB, PostgresDB ,.. Programming language : Java, C#, Python, Bash linux, Batch windows, powershell ,... Hobbies: badminton, film photo, travel. https://www.linkedin.com/in/hieu-dang-15a0561a6/
View all posts by Dang Nhu Hieu →

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.