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.
The only way to update multiple items at the same time is use TransactionWrite operation provided by DynamoDB. But it comes with a limitation (25 at most for example). So keep in mind with that, you probable should do some limitation in your application as well.
To update an existing item in an Amazon DynamoDB table, you use the UpdateItem operation. You must provide the key of the item that you want to update. You must also provide an update expression, indicating the attributes that you want to modify and the values that you want to assign to them.
There is no limit to the number of attributes but the total item size is limited to 400kb. The maximum item size in DynamoDB is 400 KB, which includes both attribute name binary length (UTF-8 length) and attribute value lengths (again binary length). The attribute name counts towards the size limit.
Can we update the sort key in DynamoDB? No, you can not update the sort key after the table is provisioned. However, you can create a new table and put the existing data in the newly created table, and delete the old table.
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"
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With