Tuesday, April 26, 2022

Hands on Lab Learning DynamoDB with Python Library PynamoDB

DynamoDB Tutorials

Hands on Lab Learning DynamoDB with Python Library PynamoDB

Tutorials

PynamoDB

  • PynamoDB is a Pythonic interface to Amazon’s DynamoDB. By using simple, yet powerful abstractions over the DynamoDB API, PynamoDB allows you to start developing immediately.

  • Python 3 support

  • Support for Unicode, Binary, JSON, Number, Set, and UTC Datetime attributes
  • Support for DynamoDB Local
  • Support for all of the DynamoDB API
  • Support for Global and Local Secondary Indexes
  • Batch operations with automatic pagination
  • Iterators for working with Query and Scan operations
  • Fully tested
In [106]:
import os
import boto3
import json
from faker import Faker
import random
import pynamodb.attributes as at
import datetime
from datetime import datetime
from pynamodb.models import Model
from pynamodb.attributes import *
In [137]:
AWS_ACCESS_KEY = "XXX"
AWS_SECRET_KEY = "XXXXX"
AWS_REGION_NAME = "us-east-1"
Why PynamoDB?

It all started when author needed to use Global Secondary Indexes, a new and powerful feature of DynamoDB. I quickly realized that my go to library, dynamodb-mapper, didn’t support them. In fact, it won’t be supporting them anytime soon because dynamodb-mapper relies on another library, boto.dynamodb, which itself won’t support them. In fact, boto doesn’t support Python 3 either. If you want to know more, I blogged about it.

Installation

pip install pynamodb

In [108]:
!pip install pynamodb
WARNING: You are using pip version 20.2.2; however, version 22.0.4 is available.
You should consider upgrading via the 'c:\python38\python.exe -m pip install --upgrade pip' command.
Requirement already satisfied: pynamodb in c:\python38\lib\site-packages (5.2.1)
Requirement already satisfied: botocore>=1.12.54 in c:\python38\lib\site-packages (from pynamodb) (1.21.65)
Requirement already satisfied: urllib3<1.27,>=1.25.4 in c:\python38\lib\site-packages (from botocore>=1.12.54->pynamodb) (1.25.11)
Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in c:\python38\lib\site-packages (from botocore>=1.12.54->pynamodb) (2.8.1)
Requirement already satisfied: jmespath<1.0.0,>=0.7.1 in c:\python38\lib\site-packages (from botocore>=1.12.54->pynamodb) (0.10.0)
Requirement already satisfied: six>=1.5 in c:\python38\lib\site-packages (from python-dateutil<3.0.0,>=2.1->botocore>=1.12.54->pynamodb) (1.15.0)
In [109]:
 faker = Faker()
Creating Model
In [124]:
class UserModel(Model):
    class Meta:
        table_name = 'youtube_tut'
        aws_access_key_id = AWS_ACCESS_KEY
        aws_secret_access_key = AWS_SECRET_KEY

    email = UnicodeAttribute(null=True)
    first_name = UnicodeAttribute(range_key=True)
    last_name = UnicodeAttribute(hash_key=True)
Creating DynamoDB tables with pynamodb
  • PROVISIONED
In [125]:
UserModel.create_table(
    read_capacity_units=4,
    write_capacity_units=4, 
    billing_mode='PROVISIONED')
  • PAY_PER_REQUEST
In [ ]:
UserModel.create_table(billing_mode='PAY_PER_REQUEST')

Insert Item

In [126]:
UserModel(
    email='test@gmail.com',
    first_name='test',
    last_name='test name'
).save()
Out[126]:
{'ConsumedCapacity': {'CapacityUnits': 1.0, 'TableName': 'youtube_tut'}}
In [127]:
average = []

for i in range(1, 20):
    
    starttime = datetime.now()
    UserModel(email=faker.email(), first_name=faker.first_name(), last_name=faker.last_name()).save()
    endtime = datetime.now()
    
    delta = endtime-starttime
    
    elapsed_time = int((delta.seconds * 1000) + (delta.microseconds / 1000))
    
    average.append(elapsed_time)
    print("Exection Time: {} MS ".format(elapsed_time))   
    
averagetime = sum(average)/ len(average)
print("\nAverage Time in MS: {} ".format(averagetime))
Exection Time: 34 MS 
Exection Time: 24 MS 
Exection Time: 31 MS 
Exection Time: 30 MS 
Exection Time: 31 MS 
Exection Time: 35 MS 
Exection Time: 31 MS 
Exection Time: 32 MS 
Exection Time: 32 MS 
Exection Time: 32 MS 
Exection Time: 36 MS 
Exection Time: 30 MS 
Exection Time: 32 MS 
Exection Time: 31 MS 
Exection Time: 32 MS 
Exection Time: 33 MS 
Exection Time: 31 MS 
Exection Time: 32 MS 
Exection Time: 32 MS 

Average Time in MS: 31.63157894736842 

Batch Inserts

In [46]:
bulk_items = [UserModel(
                    email=faker.email(),
                    first_name=faker.first_name(),
                    last_name=faker.last_name()
                    ) 
           for i in range(1, 20)]
In [48]:
with UserModel.batch_write() as batch:
    for item in bulk_items:
        batch.save(item)

Query Partition Key

In [128]:
for user in UserModel.query("Cooper"):
    print(user.email)
briansimpson@glover.com

Querying Partition key and then by Sort Key

In [129]:
for user in UserModel.query("Cooper", UserModel.first_name.startswith("C")):
    print(user.email)
briansimpson@glover.com

Scan query

In [130]:
for item in UserModel.scan(UserModel.email.startswith('j'), limit=2):
        print(item.email)
jacqueline57@yahoo.com
jsmith@moreno-bond.net

Update based on partition key

In [131]:
for user in UserModel.query("Cooper"):
    user.email = "change email address"
    user.save()
In [133]:
for user in UserModel.query("Cooper"):
    print(user.email)
change email address

Deleting based on Partition key

In [134]:
for user in UserModel.query("Cooper"):
    user.delete()
In [135]:
for user in UserModel.query("Cooper"):
    print(user.email)

Delete table

In [136]:
UserModel.delete_table()
Out[136]:
{'TableDescription': {'ItemCount': 0,
  'ProvisionedThroughput': {'NumberOfDecreasesToday': 0,
   'ReadCapacityUnits': 4,
   'WriteCapacityUnits': 4},
  'TableArn': 'arn:aws:dynamodb:us-east-1:867098943567:table/youtube_tut',
  'TableId': '0dc9caea-05ae-421a-a895-ab0d152780fd',
  'TableName': 'youtube_tut',
  'TableSizeBytes': 0,
  'TableStatus': 'DELETING'}}

No comments:

Post a Comment

Learn How to Connect to the Glue Data Catalog using AWS Glue Iceberg REST endpoint

gluecat Learn How to Connect to the Glue Data Catalog using AWS Glue Iceberg REST e...