In this step, you perform read and write operations on an item in the Movies table.
To learn more about reading and writing data, see Working with Items and Attributes.
In this step, you add a new item to the Movies table.
Movies
MoviesItemOps01.py
import boto3 import json import decimal # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if abs(o) % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('Movies') title = "The Big New Movie" year = 2015 response = table.put_item( Item={ 'year': year, 'title': title, 'info': { 'plot':"Nothing happens at all.", 'rating': decimal.Decimal(0) } } ) print("PutItem succeeded:") print(json.dumps(response, indent=4, cls=DecimalEncoder))
The primary key is required. This code adds an item that has primary key (year, title) and info attributes. The info attribute stores sample JSON that provides more information about the movie. 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.
year
title
info
DecimalEncoder
Decimal
python MoviesItemOps01.py
In the previous program, you added the following item to the table.
{ year: 2015, title: "The Big New Movie", info: { plot: "Nothing happens at all.", rating: 0 } }
You can use the get_itemmethod to read the item from the Movies table. You must specify the primary key values so that you can read any item from Movies if you know its year and title.
get_item
MoviesItemOps02.py
import boto3 import json import decimal from boto3.dynamodb.conditions import Key, Attr from botocore.exceptions import ClientError # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource("dynamodb", region_name='us-west-2') table = dynamodb.Table('Movies') title = "The Big New Movie" year = 2015 try: response = table.get_item( Key={ 'year': year, 'title': title } ) except ClientError as e: print(e.response['Error']['Message']) else: item = response['Item'] print("GetItem succeeded:") print(json.dumps(item, indent=4, cls=DecimalEncoder))
python MoviesItemOps02.py
You can use the update_item method to modify an existing item. You can update values of existing attributes, add new attributes, or remove attributes.
update_item
In this example, you perform the following updates:
Change the value of the existing attributes (rating, plot).
rating
plot
Add a new list attribute (actors) to the existing info map.
actors
The following shows the existing item.
The item is updated as follows.
{ year: 2015, title: "The Big New Movie", info: { plot: "Everything happens all at once.", rating: 5.5, actors: ["Larry", "Moe", "Curly"] } }
MoviesItemOps03.py
import boto3 import json import decimal # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('Movies') title = "The Big New Movie" year = 2015 response = table.update_item( Key={ 'year': year, 'title': title }, UpdateExpression="set info.rating=:r, info.plot=:p, info.actors=:a", ExpressionAttributeValues={ ':r': decimal.Decimal(5.5), ':p': "Everything happens all at once.", ':a': ["Larry", "Moe", "Curly"] }, ReturnValues="UPDATED_NEW" ) print("UpdateItem succeeded:") print(json.dumps(response, indent=4, cls=DecimalEncoder))
This program uses UpdateExpression to describe all updates you want to perform on the specified item. The ReturnValues parameter instructs DynamoDB to return only the updated attributes (UPDATED_NEW).
UpdateExpression
ReturnValues
UPDATED_NEW
python MoviesItemOps03.py
DynamoDB supports atomic counters, which use the update_item method to increment or decrement the value of an existing attribute without interfering with other write requests. (All write requests are applied in the order in which they are received.)
The following program shows how to increment the rating for a movie. Each time you run the program, it increments this attribute by one.
MoviesItemOps04.py
import boto3 import json import decimal # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('Movies') title = "The Big New Movie" year = 2015 response = table.update_item( Key={ 'year': year, 'title': title }, UpdateExpression="set info.rating = info.rating + :val", ExpressionAttributeValues={ ':val': decimal.Decimal(1) }, ReturnValues="UPDATED_NEW" ) print("UpdateItem succeeded:") print(json.dumps(response, indent=4, cls=DecimalEncoder))
python MoviesItemOps04.py
The following program shows how to use UpdateItem with a condition. If the condition evaluates to true, the update succeeds; otherwise, the update is not performed.
UpdateItem
In this case, the item is updated only if there are more than three actors.
Copy the following program and paste it into a file named MoviesItemOps05.py.
MoviesItemOps05.py
import boto3 from botocore.exceptions import ClientError import json import decimal # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('Movies') title = "The Big New Movie" year = 2015 # Conditional update (will fail) print("Attempting conditional update...") try: response = table.update_item( Key={ 'year': year, 'title': title }, UpdateExpression="remove info.actors[0]", ConditionExpression="size(info.actors) > :num", ExpressionAttributeValues={ ':num': 3 }, ReturnValues="UPDATED_NEW" ) except ClientError as e: if e.response['Error']['Code'] == "ConditionalCheckFailedException": print(e.response['Error']['Message']) else: raise else: print("UpdateItem succeeded:") print(json.dumps(response, indent=4, cls=DecimalEncoder))
python MoviesItemOps05.py
The program should fail with the following message.
The conditional request failed
The program fails because the movie has three actors in it, but the condition is checking for greater than three actors.
ConditionExpression
ConditionExpression="size(info.actors) >= :num",
The condition is now greater than or equal to 3 instead of greater than 3.
You can use the delete_item method to delete one item by specifying its primary key. Optionally, you can provide a ConditionExpression to prevent the item from being deleted if the condition is not met.
delete_item
In the following example, you try to delete a specific movie item if its rating is 5 or less.
MoviesItemOps06.py
import boto3 from botocore.exceptions import ClientError import json import decimal # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('Movies') title = "The Big New Movie" year = 2015 print("Attempting a conditional delete...") try: response = table.delete_item( Key={ 'year': year, 'title': title }, ConditionExpression="info.rating <= :val", ExpressionAttributeValues= { ":val": decimal.Decimal(5) } ) except ClientError as e: if e.response['Error']['Code'] == "ConditionalCheckFailedException": print(e.response['Error']['Message']) else: raise else: print("DeleteItem succeeded:") print(json.dumps(response, indent=4, cls=DecimalEncoder))
python MoviesItemOps06.py
The program fails because the rating for this particular move is greater than 5.
table.delete_item
response = table.delete_item( Key={ 'year': year, 'title': title } )