# DynamoDB, Demistyfied
(Chapter 2)

In [Chapter 1](https://phatrabbitapps.com/dynamodbdemistyfied-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. </br>
Let's Begin.  </br>
<h2> Create Products table </h2>
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.</br>

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.</br>


```
python CreateProductsTable.py
``` 

This should be your output in the terminal

```
Table status: ACTIVE
``` 
<h3> Create a new item</h3>
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.</br>

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}}

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


```
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')}
``` 
<h3> Update a Product</h3>
Let's update the description and ratings of the product we just added to our table. We would be using the **update_item** method.</br>

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.</br>
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).</br>
To run the program, enter the following command.</br>


```
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}}
``` 
<h3> Delete A Product </h3>
Let's delete one item from the table by using the delete_item method and specifying the item's primary key.</br>
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}}
``` 

<h2> Conclusion </h2>
That's all folks. Thanks for reading. </br>
Up your knowledge by going through this tutorial on how to create REST API's with Lambda and dynamo DB.</br>
 [Serverless Api design with AWS lambda, dynamoDb and API Gateway](https://phatrabbitapps.com/serverless-api-design-with-aws-lambda-dynamodb-and-api-gateway) 
</br>
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 </br>
Would love your thoughts on this. Please leave a comment or/and a reaction.
Wear your masks and Stay tuned. </br>
Happy Coding ✌️









