Dinesh Sonachalam
Dinesh Sonachalam

Reputation: 1369

How to add a new key to a Dynamodb map without overwriting the existing key?

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

enter image description here

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

Answers (3)

Dinesh Sonachalam
Dinesh Sonachalam

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")

Output:

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

Dinesh Sonachalam
Dinesh Sonachalam

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

enter image description here

Upvotes: 1

Seth Geoghegan
Seth Geoghegan

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

Related Questions