Reputation: 437
I'm trying to update several attributes of one item from a table in dynamoDB. My code is in Python 3. Every time I try it I get several errors related to the update expression and the way its written. I checked the documentation and the examples in the AWS site, but got confused at one step related to the AttributeUpdates.
This is the index of the table which was created in Node.js (I can't modify it in any way):
const Pages = dynamodb.define('Page', {
hashKey : 'idPages',
timestamps : true,//creates 2 string variables "createdAt" & "updatedAt"
schema : {
idPages : dynamodb.types.uuid(),//assigns one unique ID it is a string also
url: Joi.string(),
var1InTable: Joi.string(),//want to update this
idSite: Joi.string(),
var2InTable: Joi.array().allow(null)//want to update this
},
indexes: [
{
hashKey: 'idSite',
rangeKey: 'url',
name: 'UrlIndex',
type : 'global'
}
]
});
My variables to update are of two kinds, strings and list of strings:
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
tb_pages=dynamodb.Table('pages')
idPages="exampleID123"#hash key
url="www.example.com"#range key
var1String="example string"
var2StrList=["Example","String","List"]
var3NewString="new string variable"
So I checked the example in the Amazon and followed the structure of it:
response=tb_pages.update_item(
Key={
'idPages':item['idPages'],
'url':item['url']
},
UpdateExpression="SET var1InTable= :var1, var2InTable= :var2,var3InTable= :var3",
AttributeUpdates={
':var1': var1String,
':var2': var2StrList,
':var3': var3NewString
},
ReturnValues="UPDATED_NEW"
)
I got the following error for all the variables in AttributeUpdates:
Invalid type for parameter AttributeUpdates.:var1, value: example string, type: <class 'str'>, valid types: <class 'dict'>
So I followed the AWS boto3 documentation and replaced the variables with dictionaries where the code for the type of the variable is the key and the variable is the value.
response=tb_pages.update_item(
Key={
'idPages':item['idPages'],
'url':item['url']
},
UpdateExpression="SET var1InTable= :var1, var2InTable= :var2,var3InTable= :var3",
AttributeUpdates={
':var1': {"S":var1String},
':var2': {"L":var2StrList},
':var3': {"S":var3NewString},
},
ReturnValues="UPDATED_NEW"
)
And got the following error:
ParamValidationError: Parameter validation failed:
Unknown parameter in AttributeUpdates.:var1: "S", must be one of: Value, Action
Unknown parameter in AttributeUpdates.:var2: "L", must be one of: Value, Action
Unknown parameter in AttributeUpdates.:var3: "S", must be one of: Value, Action
Once again I checked the documentation but got confused on where to put the action and which one should use.
Note: I can change the string list to a string set, or join them in one string to simplify things as I don't really know which kind of python objects are compatible with the Joi.array().allow(null)
object defined in Node.js.
Upvotes: 14
Views: 31883
Reputation: 437
After several attempts and reading the Dynamodb API documentation i found that the PutItem method :
Creates a new item, or replaces an old item with a new item. If an item that has the same primary key as the new item already exists in the specified table, the new item completely replaces the existing item.
This might not be optimal but by using putItem with the same Keys and values the entire item can be replaced, in this case
tb_pages.put_item(
Item={
'idPages':item['idPages'],#hash key
'url':item['url'],#range key
'var1InTable':var1String,
'var2InTable':var2StrList,
'var3InTable':var3NewString,
'otherAttributeToKeep':item['otherAttributeToKeep']#see the note
}
)
note: Don't forget about passing again all the attributes from the item as this is method is going to rewrite the item, otherwise they will be overwritten and get erased.
Edit:
The problem with the code at was i was using AttributeUpdate instead of ExpressionAttributeValues , once i changed it and 'url' as a key (because url is a reserved word) in the code it worked normally
response=tb_pages.update_item(
Key={
'idPages':item['idPages'],
'urlz':item['urlz']
},
UpdateExpression="SET var1InTable= :var1, var2InTable= :var2,var3InTable= :var3",
ExpressionAttributeValues={
':var1': var1String,
':var2': var2StrList,
':var3': var3NewString
},
ReturnValues="UPDATED_NEW"
)
Upvotes: 16