aws dynamodb
- Follow this to run dynamo locally
Management
list-tables
aws dynamodb list-tables \
--endpoint-url "http://localhost:8000"
create-table
- Key schema
- HASH (partition key)
- Capacity
- Table read capacity units (RCUs) = 5
- Table write capacity units (WCUs) = 5
- Global secondary index (GSI):
- GSI_1 (5 RCUs, 5 WCUs) - Allows for querying by host IP address.
aws dynamodb create-table \
--table-name MyLogFile \
--attribute-definitions "AttributeName=PK,AttributeType=S" \
"AttributeName=GSI_1_PK,AttributeType=S" \
--key-schema "AttributeName=PK,KeyType=HASH" \
--provisioned-throughput "ReadCapacityUnits=5,WriteCapacityUnits=5" \
--tags "Key=workshop-design-patterns,Value=targeted-for-cleanup" \
--global-secondary-indexes "IndexName=GSI_1,\
KeySchema=[{AttributeName=GSI_1_PK,KeyType=HASH}],\
Projection={ProjectionType=INCLUDE,NonKeyAttributes=['bytessent']},\
ProvisionedThroughput={ReadCapacityUnits=5,WriteCapacityUnits=5}"
update-table
aws dynamodb update-table \
--table-name "MyLogFile" \
--provisioned-throughput "ReadCapacityUnits=100,WriteCapacityUnits=100"
aws dynamodb update-table \
--table-name "Employees" \
--attribute-definitions "AttributeName=GSI_2_PK,AttributeType=S" \
"AttributeName=GSI_2_SK,AttributeType=S" \
--global-secondary-index-updates file://gsi_manager.json # this file defines what will be created and the GSI name
# Enable streams API (let you implement event-driven systems by reacting to changes in the table - event sourcing)
aws dynamodb update-table \
--table-name Users \
--stream-specification StreamEnabled=true,StreamViewType=NEW_IMAGE
delete-table
aws dynamodb delete-table \
--endpoint-url "http://localhost:8000" \
--table-name "local-insurance-social-policies-docstore"
describe-table
# Returns "ACTIVE" if so
aws dynamodb describe-table \
--table-name "logfile" \
--query "Table.TableStatus"
# Returns a list of GSIs and its configuration
aws dynamodb describe-table \
--table-name "logfile" \
--query "Table.GlobalSecondaryIndexes"
# Status of all GSIs
aws dynamodb describe-table \
--table-name employees \
--query "Table.GlobalSecondaryIndexes[].IndexStatus"
wait
- Waits for a table to become active
- Useful after updates to table
aws dynamodb wait table-exists \
--table-name "logfile"
Read
scan
- Scan the whole table to find an item
- Consumes lots of RCU
- filter expressions are applicable only for
scanandqueryoperations
aws dynamodb scan \
--endpoint-url "http://localhost:8000" \
--table-name "local-insurance-social-policies-docstore"
import boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
client = boto3.resource('dynamodb')
table = client.Table('MyTable')
# filter expression can be any attribute (not only hash or sort key)
response = table.scan(
FilterExpression = Attr('MyKey').eq('USA')
)
response = table.scan(
FilterExpression =
Attr('MyKey').eq('USA') &
Attr('MyKey').begins_with('2019')
)
query
- Query operations require at least a
hash key -
It's much more efficient than a scan, because it searches only in that partition (scan reads the entire table)
-
Additionally you can use
filter expressionsto query based on other fields that are not hash/range keys
aws dynamodb query \
--table-name "Users" \
--key-condition-expression "UserId = :id" \
--expression-attribute-values '{":id":{"S":"123"}}'
import boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
client = boto3.resource('dynamodb')
table = client.Table('MyTable')
response = table.query(
KeyConditionExpression =
Key('MyPartitionKey').eq('Lala') &
Key('MySortKey ').gt('2019-01-01')
)
# Query in a different index (GSI), not the main table
# querying by non-primary key, alternate access patterns
aws dynamodb query \
--table-name Users \
--index-name EmailIndex \
--key-condition-expression "Email = :e" \
--expression-attribute-values '{":e":{"S":"[email protected]"}}'
get-item
- Returns ONE specific item
- Requires the
hash keyand therange key(if any)
aws dynamodb get-item \
--table-name Users \
--key '{"UserId":{"S":"123"}}'
import boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
client = boto3.resource('dynamodb')
table = client.Table('MyTable')
response = table.get_item(
Key = {
'MyPartitionKey': 'Lala',
'MySortKey': '2019-11-17'
}
)
Write
put-item
- Insert or replace an item
- Accepts condition-expression
aws dynamodb put-item \
--table-name "Users" \
--item '{
"UserId": {"S":"123"},
"Name": {"S":"Alice"},
"Age": {"N":"30"}
}'
aws dynamodb put-item \
--table-name Users \
--item '{"UserId":{"S":"123"}}' \
--condition-expression "attribute_not_exists(UserId)"
update-item
- Updates only selected attributes
- Avoids rewriting the entire item
- Accepts update-expression and condition-expression
SET
aws dynamodb update-item \
--table-name "Users" \
--key '{
"UserId":{"S":"123"},
"JoinedAt":{"S":"<date>"}
}' \
--update-expression "SET Name = :n, Age = :a, Profile.City = :c, Tags = list_append(Tags, :t)" \
--expression-attribute-values '{
":n": {"S":"John"},
":a": {"N":"31"},
":c": {"S":"Berlin"},
":t": {"L":[{"S":"VIP"}]}
}'
# Update only if value matches. This is optimistic locking
aws dynamodb update-item \
--table-name Users \
--key '{"UserId":{"S":"123"}}' \
--update-expression "SET Age = :new" \
--expression-attribute-values '{
":new":{"N":"31"},
":old":{"N":"30"}
}' \
--condition-expression "Age = :old"
# --condition-expression "attribute_exists(UserId)"
REMOVE
aws dynamodb update-item \
--table-name "Users" \
--key '{"UserId":{"S":"123"}}' \
--update-expression "REMOVE Age, Profile.City"
ADD
- If field doesn't exist it starts at 0 automatically
aws dynamodb update-item \
--table-name "Users" \
--key '{"UserId":{"S":"123"}}' \
--update-expression "ADD LoginCount :n, Tags :t" \
--expression-attribute-values '{
":n": {"N":"1"},
":t": {"SS":["VIP"]}
}'
DELETE
- Remove a specific value from a set
aws dynamodb update-item \
--table-name "Users" \
--key '{"UserId":{"S":"123"}}' \
--update-expression "DELETE Tags :t"
--expression-attribute-values '{
":t": {"SS":["VIP"]}
}'
delete-item
aws dynamodb delete-item \
--table-name Users \
--key '{"UserId":{"S":"123"}}'
Batch
- Used for multiple operations in the
same table
batch-get-item
aws dynamodb batch-get-item \
--request-items '{
"Users": {
"Keys": [
{"UserId":{"S":"1"}},
{"UserId":{"S":"2"}}
]
}
}'
batch-write-item
- Great for imports or migrations
- Limit: 25 items per request
aws dynamodb batch-write-item \
--request-items '{
"Users":[
{"PutRequest":{"Item":{"UserId":{"S":"1"}}}},
{"PutRequest":{"Item":{"UserId":{"S":"2"}}}},
{"DeleteRequest":{"Key":{"UserId":{"S":"3"}}}}
]
}'
Transactions
- Used for multiple operations in
different tables
transact-get-items
aws dynamodb transact-get-items \
--transact-items '[
{"Get":{"TableName":"Users","Key":{"UserId":{"S":"1"}}}},
{"Get":{"TableName":"Accounts","Key":{"AccountId":{"S":"A1"}}}}
]'
transact-write-items
- Multiple writes succeed or fail together (in different tables)
aws dynamodb transact-write-items \
--transact-items '[
{
"Put":{
"TableName":"Users",
"Item":{"UserId":{"S":"1"}}
}
},
{
"Update":{
"TableName":"Accounts",
"Key":{"AccountId":{"S":"A1"}},
"UpdateExpression":"SET Balance = Balance - :x",
"ExpressionAttributeValues":{":x":{"N":"10"}}
}
}
]'