如何在不覆盖现有密钥的情况下向Dynamodb映射添加新密钥?

时间:2020-09-25 16:24:51

标签: python amazon-dynamodb boto3

根据我的代码,首先,我向地图添加新字典,然后将其成功更新到我的地图。但是,当我向地图添加另一个字典时,地图中的现有键就会被覆盖。

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)

我的输出:我的Dynamodb表中可用的项目

{
    'company': {
        'Twitter': {
            'CEO': 'Jack'
        }
    },
    'id': Decimal('1'),
    'industry': 'industry'
}

enter image description here

预期输出:

{
    'company': {
        'Facebook': {
            'CEO': 'Mark'
        }
        'Twitter': {
            'CEO': 'Jack'
        }
    },
    'id': Decimal('1'),
    'industry': 'industry'
}

当我向地图添加新字典时,如何避免覆盖现有字典?我是DynamoDB的新手,任何建议都将对您有所帮助。

3 个答案:

答案 0 :(得分:2)

问题出在您的UpdateExpression上。您每次将company映射的值设置为新值:

SET  company = :company

但是听起来您想将新值追加company映射中。

this post中的答案应该有助于您指出正确的方向。

答案 1 :(得分:1)

您只需要在#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)

输出:我的Dynamodb中可用的项目

{
    'company': {
        'Facebook': {
            'CEO': 'Mark'
        },
        'Twitter': {
            'CEO': 'Jack'
        }
    },
    'id': Decimal('1'),
    'industry': 'internet'
}

enter image description here

答案 2 :(得分:1)

我是 Lucid-Dynamodb 的作者,它是 AWS DynamoDB 的极简包装器。使用我的库可以轻松解决此问题。

参考: 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'
}