DEV Community

Honeybadger Staff for Honeybadger

Posted on • Originally published at honeybadger.io

Using DynamoDB With Python

This article was originally written by Edidiong Etuk on the Honeybadger Developer Blog.

NoSQL databases are non-tabular databases that store and retrieve data differently from SQL databases. While SQL is table-based, NoSQL databases are either key-value pairs. NoSQL databases are for large, distributed systems due to their fast and highly scalable systems.
DynamoDB is an example of a NoSQL database. DynamoDB is fast, capable of handling multiple requests, and highly scalable. Dynamo is a NoSQL database provided by Amazon Web Service (AWS). Python is one of the most widely used programming languages and has good support for DynamoDB using the AWS SDK for Python.

In this tutorial, we will be using the Boto3 library to create and query tables, load data, and perform CRUD operations in DynamoDB and Python.

The source code for this article can be found on GitHub.

Prerequisites

Getting Started With DynamoDB Using Python

DynamoDB is an AWS service that allows you to create database tables for storing and retrieving data and handles request traffic. AWS offers a set of SDKs for interacting with DynamoDB. These SDKs are available for various programming languages; the AWS SDK for Python is known as Boto3.

We will be using Boto3 to interact with DynamnoDB. AWS Boto3 allows you to create, configure, and manage different AWS services.

Setting up DynamoDB Locally

To get DynamoDB running locally, there are a few steps required.
Let’s get started! The first step is to download the DynamoDB zip file. This file should be downloaded based on your region. Click here to download the zip file.

Once the file is downloaded, extract all the contents of the file and move your file to your preferred directory on your device.

Next, open up the command prompt, navigate to the directory where DynamoDBLocal.jar is located, and run this configuration script:

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb 
Enter fullscreen mode Exit fullscreen mode

If you encounter any issues with this process, it is most likely because you don’t have Java installed on your local machine. Run this command to confirm:

java --version
Enter fullscreen mode Exit fullscreen mode

After confirmation, if you do not have Java on your device, you can download it using this link.

The second phase of this setup is accessing DynamoDB through the AWS CLI or your command prompt configuration. This step requires your AWS credentials. Ensure you have these credentials available in a separate environment. Run this command on your terminal to begin:

aws configure 
Enter fullscreen mode Exit fullscreen mode

You likely have your AWS credentials already configured on your machine. If this is the case, press enter. However, if you don’t, provide these details:

AWS Access Key ID: "yourAccessKeyId"
AWS Secret Access Key: "yourAccessKey"
Default region name : "yourRegionName"
Enter fullscreen mode Exit fullscreen mode

Nicely done!

Connecting to the DynamoDB using Python (Boto3)

First, install Boto3 by running the following command on your terminal.

pip install boto3
Enter fullscreen mode Exit fullscreen mode

Next, in your code editor, create a dynamo-python.py file and import the Boto3 library at the top of the file.

import boto3
Enter fullscreen mode Exit fullscreen mode

Finally, we will create the Boto3 DynamoDB resource. This will connect to the local instance of our DynamoDB server. Do this by adding the following line of code:

dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000")
Enter fullscreen mode Exit fullscreen mode

Creating a Table in DynamoDB

We will be creating a table using the Dynamo create_table function. Here, we call the table "Books."

This table will contain attributes for the partition key and sort key. The “title” of the book will be our sort key, and the “book_id” will be our partition key.

A sort key is a field in a database that indicates the order in which data is stored (in sorted order by the sort key value). In DynamoDB, the sort key for each field is unique.

The partition key is the attribute that identifies an item in a database. Data with the same partition key are stored together to enable you to query the data. The data of a partition key is sorted using the sort key.

Now, add the code snippet below to create a table:

import boto3

def create_books_table(dynamodb=None):
    dynamodb = boto3.resource(
        'dynamodb')
    table = dynamodb.create_table(
        TableName='Books',
        KeySchema=[
            {
                'AttributeName': 'book_id',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'title',
                'KeyType': 'RANGE'  # Sort key
            }
        ],
        AttributeDefinitions=[
            {
                'AttributeName': 'book_id',
                # AttributeType refers to the data type 'N' for number type and 'S' stands for string type.
                'AttributeType': 'N'
            },
            {
                'AttributeName': 'title',
                'AttributeType': 'S'
            },
        ],
        ProvisionedThroughput={
            # ReadCapacityUnits set to 10 strongly consistent reads per second
            'ReadCapacityUnits': 10,
            'WriteCapacityUnits': 10  # WriteCapacityUnits set to 10 writes per second
        }
    )
    return table

if __name__ == '__main__':
    book_table = create_books_table()
    print("Status:", book_table.table_status)
Enter fullscreen mode Exit fullscreen mode

In the code above, we created a table named Books; book_id is the partition key, and the title is the sort key. Next, we defined our table by declaring a key schema stored in the KeySchema variable.

We also declared the data types of the attributes. Where "N" represents a number and "S" represents a string, we also added the ProvisionedThroughput variable to reduce the number of "read" and "write" operations on the database per second.

Finally, in the last section of the code snippet, we created an instance of our class.

Adding Sample Data to the DynamoDB Table

In this section, we will be adding sample data to the DynamoDB table. This data will be written in JSON format. To begin, create a JSON file, data.json, and add the following data:

[
    {
        "book_id": 1000,
        "title": "Atomic habits",
        "author": "James Clear",
        "isbn": "34526767",
        "year_of_publication": "2019"
    },
    {
        "book_id": 1001,
        "title": "Americanah",
        "author": "Chimamanda Adichie",
        "isbn": "10202223",
        "year_of_publication": "2013"
    },
    {
        "book_id": 1002,
        "title": "Teller of secrets",
        "author": "Bisi Adjapon",
        "isbn": "10201120",
        "year_of_publication": "2013"
    },
    {
        "book_id": 1003,
        "title": "Joys of motherhood",
        "author": "Buchi Emecheta",
        "isbn": "10110120",
        "year_of_publication": "1979" 
    },

    {
        "book_id": 1004,
        "title": "Purple Hibiscus",
        "author": "Chimamanda Adichie",
        "isbn": "10001241",
        "year_of_publication": "2012" 
    }
]

Enter fullscreen mode Exit fullscreen mode

Now, we need to load this data to add it to our database. Create a Python file, store_data.py, and add these lines of code:

import json 
from decimal import Decimal
import boto3 

def load_data(books, dynamodb=None):
    dynamodb = boto3.resource(
        'dynamodb')

    books_table = dynamodb.Table('Books')
    for book in books:
        book_id = (book['book_id'])
        title= book['title']

        print("Displaying book data:", book_id, title)
        books_table.put_item(Item=book)

if __name__ == '__main__':

    with open("data.json") as json_file:
        book_list = json.load(json_file, parse_float=Decimal)
    load_data(book_list)
Enter fullscreen mode Exit fullscreen mode

In the code above, we created a function that will loop through the fields and load the data contained in our JSON file.

Run the following command in your terminal to execute the script above.

python store_data.py
Enter fullscreen mode Exit fullscreen mode

Once the script is running successfully, the result of your loaded data will be displayed on your terminal.

Displaying book data: 1000 Atomic habits
Displaying book data: 1001 Americanah
Displaying book data: 1002 Teller of secrets
Displaying book data: 1003 Joys of motherhood
Displaying book data: 1004 Purple Hibiscus
Enter fullscreen mode Exit fullscreen mode

Successful! Good job so far!

CRUD Operations in DynamoDB Using Python

We have successfully created a table that contains data (items), and each of these items makes up a set of attributes. These are the core components of DynamoDB.

In this section, we will be working on performing CRUD operations using the items in our DynamnoDB table.

Let’s dive in!

Create Item

We will use the put_item() method to add new items to the Books table. To get started, create a new python file, add_book.py, and add the following code snippet:

import boto3

def add_book(books, dynamodb=None):
    dynamodb = boto3.resource('dynamodb')

    books_table = dynamodb.Table('Books')
    response = books_table.put_item(
        Item={
        "book_id": 1005,
        "title": "There Was a Country",
        "author": "Chinua Achebe",
        "isbn": "0143124030",
        "year_of_publication": "2012"

        }
    )


    return response

if __name__ == '__main__':
    book_resp = add_book(books='Books')
    print(book_resp)
Enter fullscreen mode Exit fullscreen mode

In the code snippet above, we defined a function that will add items from our Dynamo table. Next, using the put_item() method, we added sample data for the DynamoDB table.

Run the scripts in your terminal to add the data:

python add_book.py
Enter fullscreen mode Exit fullscreen mode

You should get this output:

{'ResponseMetadata': {'RequestId': '', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Thu, 05 May 2022 15:00:40 GMT', 'content-type': 'application/x-amz-json-1.0', 'content-length': '2', 'connection': 'keep-alive', 'x-amzn-requestid': '', 'x-amz-crc32': '2745614147'}, 'RetryAttempts': 0}}
Enter fullscreen mode Exit fullscreen mode

Read Item

We can also access the item(s) in the DynamoDB table using the get_item() method. We need the primary to be able to access the database. The primary of this project is a combination of the sort key (’title’) and the partition key (’book_id’).

Create a python file, get_book.py, and add the following lines of code:

import boto3
from botocore.exceptions import ClientError

def get_book(book_id, title, dynamodb=None):
    dynamodb = boto3.resource('dynamodb')

    books_table = dynamodb.Table('Books')

    try:
        response = books_table.get_item(
            Key={'book_id': book_id, 'title': title})
    except ClientError as e:
            print(e.response['No item found'])
    else:
            return response['Item']

if __name__ == '__main__':
    book = get_book(1000, "Atomic habits")
    if book:
        print(book)
Enter fullscreen mode Exit fullscreen mode

From the code above, we imported ClientError from the botocore.exceptions package, which is set to help us navigate and handle errors and exceptions that may be encountered while interacting with the AWS Boto3 SDK.

Run this script on your terminal using this command:

python get_book.py
Enter fullscreen mode Exit fullscreen mode

You should get this output:

{'year_of_publication': '2019', 'isbn': '34526767', 'book_id': Decimal('1000'), 'author': 'James Clear', 'title': 'Atomic habits'}
Enter fullscreen mode Exit fullscreen mode

Condition Expressions

When working with DynamoDB, you are likely to use ConditionExpressions when altering items in a database table.

Condition expressions are optional parameters used to manipulate specified items in a DynamoDB table. Conditions expressions are applied using the PutItem, UpdateItem, and DeleteItem operations.

These operations are implemented when updating or deleting items. The operation only succeeds if the condition expression value is set to true; otherwise, the operation fails.

In the next section, we will be working with condition expressions for updating and deleting items on our table.

Update Item

We can also update the existing data in our table. This is done by either updating the values of an existing attribute, adding new attributes, or deleting attributes.

In this section, we will update the value of an existing attribute using the update_item() method. Let’s get started with an existing attribute in our table:

{
    "book_id": 1000,
    "title": "Atomic habits",
    "author": "James Clear",
    "isbn": "34526767",
    "year_of_publication": "2019"
}
Enter fullscreen mode Exit fullscreen mode

Create a python file, update_book.py, and insert these lines of code:

import boto3

def update_book(book_id, title, dynamodb=None):
    dynamodb = boto3.resource('dynamodb')

    books_table = dynamodb.Table('Books')

    response = books_table.update_item(
        Key={
            'book_id' : 1001,
            'title': "Americanah"
        },
        UpdateExpression="set ISBN=:ISBN",
        ExpressionAttributeValues={':ISBN': "9780307455925"},
        ReturnValues="UPDATED_NEW"
    )
    return response

if __name__ == '__main__':
    update_response = update_book(1001, 'Americanah')
    print(update_response)
Enter fullscreen mode Exit fullscreen mode

From the code above, we defined a function that will add items from our Dynamo table. Next, using the update_item() method, we intend to update an attribute in the DynamoDB table. Other parameters used include:

UpdateExpression: Defines attribute(s) which are to be updated and their new values.

ExpressionAttributeValues: This expression holds the substitutes for the attribute to be updated or the new value.

ReturnValues: Use this parameter to get the item attributes before or after they are updated. For UpdateItem(), the valid values are NONE | ALL_OLD | UPDATED_OLD | ALL_NEW | UPDATED_NEW.

Run this script on your terminal using this command:

python update_book.py
Enter fullscreen mode Exit fullscreen mode

Output:

{'Attributes': {'ISBN': '9780307455925'}, 'ResponseMetadata': {'RequestId': '3TJHT8856E3GRKFCPN8S5HMRQ3VV4KQNSO5AEMVJF66Q9ASUAAJG', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Mon, 09 May 2022 10:26:53 GMT', 'content-type': 'application/x-amz-json-1.0', 'content-length': '45', 'connection': 'keep-alive', 'x-amzn-requestid': '3TJHT8856E3GRKFCPN8S5HMRQ3VV4KQNSO5AEMVJF66Q9ASUAAJG', 'x-amz-crc32': '2958762950'}, 'RetryAttempts': 0}}
Enter fullscreen mode Exit fullscreen mode

Delete item

For the last CRUD operation, we will be deleting an item from our table using the delete_item() method. You can either use the primary key of the item or a ConditionExpression to delete the item. If you wish to use a ConditionExpression the condition expression value must be set to true.
However, in this tutorial, we will be using both the primary key and the condition expression.

Create a python file, delete_book.py, and these lines of code:

import boto3

def delete_book(book_id, title, dynamodb=None):
    dynamodb = boto3.resource('dynamodb')

    books_table = dynamodb.Table('Books')

    response = books_table.delete_item(
        Key={
            'book_id' : 1001,
            'title': "Americanah"
        },
        ConditionExpression="ISBN=:ISBN",
        ExpressionAttributeValues={':ISBN': "9780307455925"},

    )
    return response

if __name__ == '__main__':
    delete_response = delete_book(1001, 'Americanah')
    print(delete_response)
Enter fullscreen mode Exit fullscreen mode

Run this script on your terminal using this command:

python delete_book.py
Enter fullscreen mode Exit fullscreen mode

Output:

{'ResponseMetadata': {'RequestId': 'LQ2M5SKSNKAASF041VPKE6FQCFVV4KQNSO5AEMVJF66Q9ASUAAJG', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Mon, 09 May 2022 11:56:08 GMT', 'content-type': 'application/x-amz-json-1.0', 'content-length': '2', 'connection': 'keep-alive', 'x-amzn-requestid': 'LQ2M5SKSNKAASF041VPKE6FQCFVV4KQNSO5AEMVJF66Q9ASUAAJG', 'x-amz-crc32': '2745614147'}, 'RetryAttempts': 0}}
Enter fullscreen mode Exit fullscreen mode

Query Tables in DynamoDB

Querying our database table returns every item in the table with the same partition key. We will query the table using the value of our partition key using the query() method. The partition key in this project is ‘book_id’.

Let’s dive in!

Create a python file, query_table.py, and insert these lines of code:

import boto3 
from boto3.dynamodb.conditions import Key 

def query_book(book_id, dynamodb=None):
    dynamodb = boto3.resource('dynamodb')

    books_table = dynamodb.Table('Books')

    response = books_table.query(
        KeyConditionExpression=Key('book_id').eq(1001)
    )
    return response['Items']

if __name__ == '__main__':
    query_id = 10001
    print(f"Book ID: {query_id}")
    books_data = query_book(query_id)
    for book_data in books_data:
       print(book_data['book_id'], ":", book_data['title'])
Enter fullscreen mode Exit fullscreen mode

Run this script on your terminal using this command:

python query_table.py 
Enter fullscreen mode Exit fullscreen mode

Output:

Book ID: 10001
1001: Americanah
Enter fullscreen mode Exit fullscreen mode

Delete Table

In addition to CRUD operations, you can also delete an entire DynamoDB table using the table.delete() method. All you need to do is specify the name of the table you wish to delete.

Create a python file, delete_table.py, and insert these lines of code:

import boto3

def delete_table(dynamodb=None):
    dynamodb = boto3.resource('dynamodb')

    books_table = dynamodb.Table('Books')
    books_table.delete()

if __name__ == '__main__':
    delete_table()
    print("DynamoDB table deleted!")
Enter fullscreen mode Exit fullscreen mode

Run this script on your terminal using this command:

python delete_table.py
Enter fullscreen mode Exit fullscreen mode

Output:

DynamoDB table deleted
Enter fullscreen mode Exit fullscreen mode

Conclusion

Several DynamoDB operations can be performed by creating a Python script using AWS Boto3. In this tutorial, we created a DynamoDB table using Boto3 to interact with our database and perform CRUD operations, query, and delete a table.

I hope you had fun working on this!

Happy Coding!🙂

Top comments (0)