DynamoDB, Demistyfied
(Chapter 2)

DynamoDB, Demistyfied (Chapter 2)

Perform CRUD operations on dynamoDB with python

In Chapter 1, we ran through the core concepts surrounding the dynamoDb and I provided a link on how to install it locally on your computer. In this chapter, we'll be looking at how to perform basic CRUD(Create, Read, Update, Delete) operations on a table. I'll assume you've already installed and are running dynamo DB locally. What we want to do is, create a Products table and perform CRUD operations on it.
Let's Begin.

Create Products table

Let's create a Products table to store our Product Items in it. The composite key for the table is composed of the following attributes:

id – The partition key. The AttributeType is N for number.

name – The sort key. The AttributeType is S for string.

Create a file called CreateProductsTable.py and type out this code within

import boto3


def create_products_table(dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.create_table(
        TableName='Products',
        KeySchema=[
            {
                'AttributeName': 'id',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'name',
                'KeyType': 'RANGE'  # Sort key
            }
        ],
        AttributeDefinitions=[
            {
                'AttributeName': 'id',
                'AttributeType': 'N'
            },
            {
                'AttributeName': 'name',
                'AttributeType': 'S'
            },

        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': 10,
            'WriteCapacityUnits': 10
        }
    )
    return table


if __name__ == '__main__':
    product_table = create_products_table()
    print("Table status:", product_table.table_status)

boto3 is the aws sdk for python. You set the endpoint to indicate that you are creating the table in the downloadable version of DynamoDB on your computer.

The ProvisionedThroughput parameter is required. However, the downloadable version of DynamoDB ignores it. Provisioned throughput is the maximum amount of capacity that an application can consume from a table or index. If your application exceeds your provisioned throughput capacity on a table or index, it is subject to request throttling. Throttling prevents your application from consuming too many capacity units.

Make sure you have boto3 installed on your computer

pip install boto3

To run the program, enter the following command.

python CreateProductsTable.py

This should be your output in the terminal

Table status: ACTIVE

Create a new item

Let's add a new item(Product) to our Products table. We will use the put_item method to do this. Create a file called CreateProductItem.py and type out the following code in it.

from pprint import pprint
import boto3
from decimal import Decimal

def put_product(id, name,description, price,rating, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Products')
    response = table.put_item(
       Item={
            'id': id,
            'name': name,
            'description':description,
            'price': Decimal(price),
            'rating':Decimal(rating)
        }
    )
    return response


if __name__ == '__main__':
    product_response = put_product(1001,"Laptops",
                           "Any good description", "25.9", "4.5")
    print("Put product succeeded:")
    pprint(product_response, sort_dicts=False)

The DecimalEncoder class is used to print out numbers stored using the Decimal class. The Boto SDK uses the Decimal class to hold Amazon DynamoDB number values.

To run the program, enter the following command.

python CreateProductItem.py

This should be your output in the terminal.

Put product succeeded:
{'ResponseMetadata': {'RequestId': '83bb5a1f-07f9-48b6-88fa-813040d5c371',
                      'HTTPStatusCode': 200,
                      'HTTPHeaders': {'date': 'Mon, 29 Mar 2021 14:54:47 GMT',
                                      'content-type': 'application/x-amz-json-1.0',
                                      'x-amz-crc32': '2745614147',
                                      'x-amzn-requestid': '83bb5a1f-07f9-48b6-88fa-813040d5c371',
                                      'content-length': '2',
                                      'server': 'Jetty(9.4.18.v20190429)'},
                      'RetryAttempts': 0}}

Get a Product

Let's get the product we just added to our table. We will be using the get_item method
You must specify the composite key values in order to read an item from the Products table.
Create a file called ReadProductItem.py and type out the following code

from pprint import pprint
import boto3
from botocore.exceptions import ClientError


def get_product(id, name, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Products')

    try:
        response = table.get_item(Key={'id': id, 'name': name})
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        return response['Item']


if __name__ == '__main__':
    product = get_product(1001,"Laptops")
    if product:
        print("Successfully got the product:")
        pprint(product, sort_dicts=False)

To run the program, enter the following command.

python ReadProductItem.py

This should be your output in the terminal.

Successfully got the product:
{'name': 'Laptops',
 'rating': Decimal('4.5'),
 'description': 'Any good description',
 'id': Decimal('1001'),
 'price': Decimal('25.9')}

Update a Product

Let's update the description and ratings of the product we just added to our table. We would be using the update_item method.

Create a file called UpdateProductItem.py and type out the following code in it

from decimal import Decimal
from pprint import pprint
import boto3


def update_product(id,name,description, rating, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Products')

    response = table.update_item(
        Key={
            'id': id,
            'name': name
        },
        UpdateExpression="set rating=:r, description=:d",
        ExpressionAttributeValues={
            ':r': Decimal(rating),
            ':d': description

        },
        ReturnValues="UPDATED_NEW"
    )
    return response


if __name__ == '__main__':
    update_response = update_product(
        1001,"Laptops","an updated description", 6.5)
    print("Product Successfully updated:")
    pprint(update_response, sort_dicts=False)

This program uses UpdateExpression to describe all updates you want to perform on the specified item.
The ExpressionAttributeValues provides value substitution.As you can see, we substituted the :r for ratings and :d for description. The ReturnValues parameter instructs DynamoDB to return only the updated attributes (UPDATED_NEW).
To run the program, enter the following command.

python UpdateProductItem.py

This should be your output.

Product Successfully updated:
{'Attributes': {'rating': Decimal('6.5'),
                'description': 'an updated description'},
 'ResponseMetadata': {'RequestId': 'e1e0c9af-32e2-4052-9bc8-abd7e580fe21',
                      'HTTPStatusCode': 200,
                      'HTTPHeaders': {'date': 'Mon, 29 Mar 2021 15:25:21 GMT',
                                      'content-type': 'application/x-amz-json-1.0',
                                      'x-amz-crc32': '1215728936',
                                      'x-amzn-requestid': 'e1e0c9af-32e2-4052-9bc8-abd7e580fe21',
                                      'content-length': '82',
                                      'server': 'Jetty(9.4.18.v20190429)'},
                      'RetryAttempts': 0}}

Delete A Product

Let's delete one item from the table by using the delete_item method and specifying the item's primary key.
Create a file called DeleteProductItem.py and type out the following code in it.

from decimal import Decimal
from pprint import pprint
import boto3
from botocore.exceptions import ClientError


def delete_product(id,name, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Products')

    try:
        response = table.delete_item(
            Key={
                'id': id,
                'name': name
            }

        )
    except ClientError as e:


        print(e.response['Error']['Message'])

    else:
        return response


if __name__ == '__main__':

    delete_response = delete_product(1001,"Laptops")
    if delete_response:
        print("Successfully deleted product")
        pprint(delete_response, sort_dicts=False)

To run the program, enter the following command.

python DeleteProductItem.py

Your output should look like this.

Successfully deleted product
{'ResponseMetadata': {'RequestId': 'c892d40b-e044-4953-b8db-5c0ddf6eed4a',
                      'HTTPStatusCode': 200,
                      'HTTPHeaders': {'date': 'Mon, 29 Mar 2021 15:38:57 GMT',
                                      'content-type': 'application/x-amz-json-1.0',
                                      'x-amz-crc32': '2745614147',
                                      'x-amzn-requestid': 'c892d40b-e044-4953-b8db-5c0ddf6eed4a',
                                      'content-length': '2',
                                      'server': 'Jetty(9.4.18.v20190429)'},
                      'RetryAttempts': 0}}

Conclusion

That's all folks. Thanks for reading.
Up your knowledge by going through this tutorial on how to create REST API's with Lambda and dynamo DB.
Serverless Api design with AWS lambda, dynamoDb and API Gateway
There's still a ton to talk about with respect to dynamo DB and I'll be bringing the news to you on a weekly basis
Would love your thoughts on this. Please leave a comment or/and a reaction. Wear your masks and Stay tuned.
Happy Coding ✌️