Reputation: 1369
As per my code, At first, I add a new dict to the map and it gets updated to my map successfully. But when I add another dict to my map, the existing key in my map gets overwritten.
def update_item(table_name, id, new_company):
table = dynamodb.Table(table_name)
result = table.update_item(
Key={
'id': id
},
UpdateExpression="SET company = :company",
ExpressionAttributeValues={
':company': new_company
},
ReturnValues="ALL_NEW"
)
print(result)
if __name__ == '__main__':
company_1 = {
"Facebook" : {
"CEO" : "Mark"
}
}
update_item('companies', 1, company_1)
company_2 = {
"Twitter": {
"CEO": "Jack"
}
}
update_item('companies', 1, company_2)
My Output: Items available in my Dynamodb table
{
'company': {
'Twitter': {
'CEO': 'Jack'
}
},
'id': Decimal('1'),
'industry': 'industry'
}
Expected Output:
{
'company': {
'Facebook': {
'CEO': 'Mark'
}
'Twitter': {
'CEO': 'Jack'
}
},
'id': Decimal('1'),
'industry': 'industry'
}
How to avoid overwriting of the existing dict, when I add a new dict to the map? I'm new to DynamoDB, any suggestions would be helpful.
Upvotes: 2
Views: 2160
Reputation: 1369
I'm the author of Lucid-Dynamodb, a minimalist wrapper to AWS DynamoDB. This problem can be easily solved using my library.
Reference: https://github.com/dineshsonachalam/Lucid-Dynamodb
from LucidDynamodb.Operations import DynamoDb
import os
import logging
logging.basicConfig(level=logging.INFO)
AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
table_schema = {
"TableName": "company",
"KeySchema": [
{
"AttributeName": "id",
"KeyType": "HASH"
}
],
"AttributeDefinitions": [
{
"AttributeName": "id",
"AttributeType": "N"
}
],
"GlobalSecondaryIndexes": [],
"ProvisionedThroughput": {
"ReadCapacityUnits": 1,
"WriteCapacityUnits": 1
}
}
if __name__ == "__main__":
# 1. create a new table
db = DynamoDb(region_name="us-east-1",
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
table_creation_status = db.create_table(
TableName=table_schema.get("TableName"),
KeySchema=table_schema.get("KeySchema"),
AttributeDefinitions=table_schema.get("AttributeDefinitions"),
GlobalSecondaryIndexes=table_schema.get("GlobalSecondaryIndexes"),
ProvisionedThroughput=table_schema.get("ProvisionedThroughput")
)
if(table_creation_status == True):
logging.info("{} table created successfully".format(table_schema.get("TableName")))
else:
logging.error("{} table creation failed".format(table_schema.get("TableName")))
# 2. Create a new item
item_creation_status = db.create_item(
TableName=table_schema.get("TableName"),
Item= {
'company': {
'Facebook': {
'CEO': 'Mark'
}
},
'id': 1,
'industry': 'internet'
}
)
if(item_creation_status == True):
logging.info("Item created successfully")
else:
logging.warning("Item creation failed")
# 3. Add a new attribute in a item
item_update_status = db.update_item(
TableName=table_schema.get("TableName"),
Key={
'id': 1
},
AttributesToUpdate={
'company.Twitter': {
'CEO': 'Jack'
}
}
)
if(item_update_status == True):
logging.info("Update is successful")
else:
logging.warning("Update failed")
item = db.read_item(
TableName=table_schema.get("TableName"),
Key={
'id': 1
})
if(item != None):
logging.info("Item: {}".format(item))
else:
logging.warning("Item doesn't exist")
dineshsonachalam@macbook Dynamodb-experiment % python test.py
INFO:root:company table created successfully
INFO:root:Item created successfully
INFO:root:Update is successful
INFO:root:Item:
{
'company': {
'Facebook': {
'CEO': 'Mark'
},
'Twitter': {
'CEO': 'Jack'
}
},
'id': Decimal('1'),
'industry': 'internet'
}
Upvotes: 1
Reputation: 1369
You just need to add a map entry at #name.
def update_item(table_name, id, new_company):
table = dynamodb.Table(table_name)
name = list(new_company)[0]
result = table.update_item(
Key={
'id': id
},
UpdateExpression="SET company.#name = :company",
ExpressionAttributeNames={"#name": name},
ExpressionAttributeValues={
':company': new_company[name]
},
ReturnValues="ALL_NEW"
)
print(result)
Output: Items available in my Dynamodb
{
'company': {
'Facebook': {
'CEO': 'Mark'
},
'Twitter': {
'CEO': 'Jack'
}
},
'id': Decimal('1'),
'industry': 'internet'
}
Upvotes: 1
Reputation: 5747
The issue is with your UpdateExpression
. You are setting the value of company
map to a new value each time:
SET company = :company
but it sounds like you want to append a new value to the company
map.
The answer in this post should help point you in the right direction.
Upvotes: 2