This post explains how to create a DynamoDB table using both DynamoDB.Client and DynamoDB.ServiceResource and explains difference between these two approaches.
Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability. With DynamoDB, you can create database tables that can store and retrieve any amount of data and serve any level of request traffic. You can scale up or scale down your tables' throughput capacity without downtime or performance degradation.
In this section we will use Python Boto3 SDK to create table in DynamoDB for storing movies data.
Each movie is having its distinct attributes like "title", "year" etc. Below is the sample item from the JSON file that will be stored in DynamoDB. You can download the sample file from here.
{
"year": 2000,
"title": "28 Days",
"info": {
"directors": ["Betty Thomas"],
"release_date": "2000-02-08T00:00:00Z",
"rating": 5.8,
"genres": [
"Comedy",
"Drama"
],
"image_url": "http://ia.media-imdb.com/images/M/MV5BMTYwMDA1NjAxMF5BMl5BanBnXkFtZTYwODc3MTU3._V1_SX400_.jpg",
"plot": "A big-city newspaper columnist is forced to enter a drug and alcohol rehab center after ruining her sister's wedding and crashing a stolen limousine.",
"rank": 3350,
"running_time_secs": 6180,
"actors": [
"Sandra Bullock",
"Viggo Mortensen",
"Dominic West"
]
}
Let's select year as partition key (HASH Key) and title as a sort key (RANGE key) and create the table as shown in below code snippet.
import boto3
client = boto3.client("dynamodb")
table_name = "sample-movie-table-client"
attribute_definitions = [
{"AttributeName": "year", "AttributeType": "N"},
{"AttributeName": "title", "AttributeType": "S"},
]
key_schema = [
{"AttributeName": "year", "KeyType": "HASH"},
{"AttributeName": "title", "KeyType": "RANGE"},
]
response = client.create_table(
AttributeDefinitions=attribute_definitions,
TableName=table_name,
KeySchema=key_schema,
BillingMode='PAY_PER_REQUEST'
)
print(type(response))
print(dir(response))
Output
<class 'dict'>
['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__ior__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
Now let's create the same table using DynamoDB.ServiceResource and notice the difference in returned response.
import boto3
dynamodb_resource = boto3.resource("dynamodb")
table_name = "sample-movie-table-resource"
attribute_definitions = [
{"AttributeName": "year", "AttributeType": "N"},
{"AttributeName": "title", "AttributeType": "S"},
]
key_schema = [
{"AttributeName": "year", "KeyType": "HASH"},
{"AttributeName": "title", "KeyType": "RANGE"},
]
response = dynamodb_resource.create_table(
AttributeDefinitions=attribute_definitions,
TableName=table_name,
KeySchema=key_schema,
BillingMode='PAY_PER_REQUEST'
)
print(type(response))
print(dir(response))
Output
<class 'boto3.resources.factory.dynamodb.Table'>
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_injector', '_name', 'archival_summary', 'attribute_definitions', 'batch_writer', 'billing_mode_summary', 'creation_date_time', 'delete', 'delete_item', 'get_available_subresources', 'get_item', 'global_secondary_indexes', 'global_table_version', 'item_count', 'key_schema', 'latest_stream_arn', 'latest_stream_label', 'load', 'local_secondary_indexes', 'meta', 'name', 'provisioned_throughput', 'put_item', 'query', 'reload', 'replicas', 'restore_summary', 'scan', 'sse_description', 'stream_specification', 'table_arn', 'table_class_summary', 'table_id', 'table_name', 'table_size_bytes', 'table_status', 'update', 'update_item', 'wait_until_exists', 'wait_until_not_exists']
So if you noticed the type of response returned by
DynamoDB.Client
is
dictionary, while type of response
returned by DynamoDB.ServiceResource is
boto3.resources.factory.dynamodb.Table, which provides other useful methods like
table_status
,
wait_until_exists
etc. to
interact with the created table.
In the above snippet tables were created in On-Demand Mode, where we passed BillingMode
as PAY_PER_REQUEST. Now lets create the table for
PROVISIONED
mode. Change the ReadCapacityUnits and WriteCapacityUnits as per the requirements.
import boto3
dynamodb_resource = boto3.resource("dynamodb")
table_name = "sample-movie-table-resource"
attribute_definitions = [
{"AttributeName": "year", "AttributeType": "N"},
{"AttributeName": "title", "AttributeType": "S"},
]
key_schema = [
{"AttributeName": "year", "KeyType": "HASH"},
{"AttributeName": "title", "KeyType": "RANGE"},
]
response = dynamodb_resource.create_table(
AttributeDefinitions=attribute_definitions,
TableName=table_name,
KeySchema=key_schema,
BillingMode="PROVISIONED",
ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1},
)
print(type(response))
print(dir(response))
In the previous examples while creating the DynamoDB tables, SSESpecification
parameter was not provided. Whenever this parameter is missing or disabled than server-side encryption is set to AWS owned key. Follow below code snippet
to create table that is encrypted using AWS KMS.
import boto3
dynamodb_resource = boto3.resource("dynamodb")
table_name = "sample-movie-table-resource"
attribute_definitions = [
{"AttributeName": "year", "AttributeType": "N"},
{"AttributeName": "title", "AttributeType": "S"},
]
key_schema = [
{"AttributeName": "year", "KeyType": "HASH"},
{"AttributeName": "title", "KeyType": "RANGE"},
]
response = dynamodb_resource.create_table(
AttributeDefinitions=attribute_definitions,
TableName=table_name,
KeySchema=key_schema,
BillingMode="PROVISIONED",
ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1},
SSESpecification={
'Enabled': True,
'SSEType': 'KMS'
},
)
print(type(response))
print(dir(response))
Category: Python