DynamoDB更新含保留字嵌套属性报错:#buyer未定义
解决DynamoDB更新嵌套对象(含保留关键字)时的自动创建问题
问题背景
现有DynamoDB条目:
{ "id":1, "poc_name": "ABC" }
需要更新为:
{ "id": 1, "poc_name": "ABC", "buyer": { "value": "id1", "label": "Test" } }
因使用保留关键字value,且buyer对象不存在时,更新触发报错:
An expression attribute name used in the document path is not defined; attribute name: #buyer
现有代码生成的更新参数:
updateValues: {':poc_name': 'ABC', ':buyer_value': 'id1', ':buyer_label': 'Test'} updateExpression: ['set ','poc_name = :poc_name,','#buyer.#value = :buyer_value,', 'buyer.label = :buyer_label,'] expression_attributes_names: {'#demand_poc_action': 'demand_poc_action', '#value': 'value', '#buyer': 'buyer'}
核心代码片段:
for key, value in dictData.items(): if key in RESERVER_DDB_KEYWORDS or ( "." in key and key.split(".")[1] in RESERVER_DDB_KEYWORDS ): key1 = key.replace(".", ".#") updateExpression.append(f"#{key1} = :{key.replace('.', '_')},") updateValues[f":{key.replace('.', '_')}"] = value if "." in key: expression_attributes_names[f"#{key.split('.')[0]}"] = key.split(".")[0] expression_attributes_names[f"#{key.split('.')[1]}"] = key.split(".")[1] else: expression_attributes_names[f"#{key}"] = key else: updateExpression.append(f"{key} = :{key.replace('.', '_')},") updateValues[f":{key.replace('.', '_')}"] = value UpdateExpression="".join(updateExpression)[:-1], ExpressionAttributeValues=updateValues, ReturnValues="UPDATED_NEW", ExpressionAttributeNames=expression_attributes_names,
当前问题:buyer对象已存在时更新正常,不存在时触发报错,需求是自动创建buyer但无法修改现有代码。
解决方案
方案1:调整输入数据结构(推荐)
不传入buyer.value、buyer.label这类嵌套键,直接传入完整的buyer对象作为顶层键:
将原来的输入数据:
dictData = { "poc_name": "ABC", "buyer.value": "id1", "buyer.label": "Test" }
修改为:
dictData = { "poc_name": "ABC", "buyer": { "value": "id1", "label": "Test" } }
这样现有代码会直接生成buyer = :buyer的更新语句,DynamoDB会自动创建不存在的buyer对象,且内部的value作为对象属性,无需单独处理保留关键字路径问题。
方案2:前置创建空对象
在原有更新操作前,先执行一次条件更新,确保buyer存在:
- 执行前置
UpdateItem操作:dynamodb.update_item( TableName="your-table-name", Key={"id": {"N": "1"}}, UpdateExpression="set #buyer = :empty_obj", ConditionExpression="attribute_not_exists(#buyer)", ExpressionAttributeNames={"#buyer": "buyer"}, ExpressionAttributeValues={":empty_obj": {"M": {}}} ) - 再执行原有更新逻辑,此时
buyer已存在,不会触发路径不存在的报错。
内容的提问来源于stack exchange,提问作者Neelabh Singh
相关产品推荐
相关产品推荐

