I am trying to update the record in dynamodb using following dictData, I have RESERVER_KEYWORDS array which has reserved keyword in dynamoDB. Please check code segment which I am trying to replace with the reserve keyword. Main issue that customer.value
and action.value
type of keyword used in given record. I am not sure how to replace with #.
However I am getting error
CRITICAL Couldn't update record in table table. Here's why: ValidationException: Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: value
dictData = {
':line_items': [{
'search_product': 'dd',
'quantity': '10'
}]
'email': 'xyz@email',
'poc_name': 'XYZ',
'contact': '90912',
'action': {
'value': 'id1',
'label': 'In Progress'
},
'terms': 'Cash',
'customer': {
'value': 'id1',
'label': 'Customer'
},
}
In side the function definition:
updateExpression = ["set "]
updateValues = dict()
expression_attributes_names = {}
for key, value in dictData.items():
updateExpression.append(f" #{key}_alias = :{key.replace('.', '_')},")
updateValues[f":{key.replace('.', '_')}"] = value
expression_attributes_names[f"#{key}_alias"] = key
response = table.update_item(
Key={"_id": id},
UpdateExpression="".join(updateExpression)[:-1],
ExpressionAttributeValues=updateValues,
ReturnValues="UPDATED_NEW",
ExpressionAttributeNames=expression_attributes_names,
)
Above function will give following values of expression_attributes_names, updateExpression, updateValues.
expression_attributes_names: {}
updateExpression: ['set ', ' line_items = :line_items,', ' email = :email', ' poc_name = :poc_name,', ' contact = :contact,', ' action.value = :action_value,',
' action.label = :action_label,', ' terms = :terms,',
' customer.value = :customer_value,', ' customer.label = :customer_label,'
]
updateValues: {
':line_items': [{
'search_product': 'dd',
'quantity': '10'
}],
':email': 'xyz@email',
':poc_name': 'Test',
':contact': '90912',
':action_value': 'id1',
':action_label': 'In Progress',
':terms': 'Cash',
':customer_value': 'id1',
':customer_label': 'Customer'
}
CodePudding user response:
You should always use ExpressionAttributeNames to ensure you do not conflict with DynamoDB reserved keywords.
Furthermore, I believe you should look into the parameters expected of UpdateItem to ensure you are passing correct values:
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html
For nested values you just follow the same concept:
#customer.#value
ExpressionAttributeNames={
"#customer":"customer",
"#value":"value"
},
UpdateExpression="SET #customer.#value = :val"