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

Developer Guide: Getting Started with Flink (PyFlink) and Hudi - Setting Up Your Local Environment and Performing CRUD Operations via flink

flink-hudi-final Install Flink and Python ¶ conda info --envs # Create ENV conda ...