Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update several attributes of an item in dynamodb using boto3

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.

like image 339
Julian Abril Avatar asked Jun 26 '18 17:06

Julian Abril


People also ask

How do you update multiple items in a DynamoDB table?

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.

How do you update items in DynamoDB table?

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.

How many attributes can a DynamoDB item have?

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 you update sort key value DynamoDB?

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.


1 Answers

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"

        )
like image 153
Julian Abril Avatar answered Oct 26 '22 22:10

Julian Abril