amazon-dynamodbboto3

How can I update table item value of a dict inside a list?


I'm trying to simply update the instance type in the following dynamodb table item. But I can't seem to figure out how to do that since it's within an attribute called instanceParameters which is a list of key,value pairs.

{
"PK":"pk_value",
"SK":"sk_value",
"instanceParameters": [
  {
   "key": "AZ",
   "value": "us-east-1a"
  },
  {
   "key": "SubnetId",
   "value": "subnet-0a123455623235f1"
  },
  {
   "key": "VpcId",
   "value": "vpc-0a1234567890a1"
  },
  {
   "key": "InstanceType",
   "value": "t2.12xlarge"
  }
 ]
}

This is the python code I have to update the InstanceType value:

import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Instances')

def update_database(pk, sk):
    try:
        res = table.update_item(
            Key={
                'PK': pk,
                'SK': sk
            },
            ConditionExpression= 'attribute_exists(instanceParameters)',
            UpdateExpression='SET #key = :val',
            ExpressionAttributeNames={
                '#key': 'InstanceType'
            },
            ExpressionAttributeValues={
                ':val':'t2.4xlarge'
            },
            ReturnValues='UPDATED_NEW'
        )
    except Exception as e:
        print(e)
    print(res)

There are no errors but nothing gets updated in the table. I'm thinking the syntax for the UpdateExpression field is incorrect and it's not finding the correct field to update. Any thoughts? Thanks!


Solution

  • instead of directly updating the InstanceType in the UpdateExpression (which doesn't work for nested lists), you can retrieve the entire instanceParameters list, modify the desired entry (InstanceType) in the code, and write the updated list back to the DynamoDB table using UpdateExpression.

        import boto3
        
        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table('Instances')
        
        def update_instance_type(pk, sk, new_instance_type):
            try:
                # Fetch the current item
                response = table.get_item(Key={'PK': pk, 'SK': sk})
                item = response.get('Item', {})
                
                if not item or 'instanceParameters' not in item:
                    print("Item or instanceParameters not found")
                    return
                
                # Modify the InstanceType in instanceParameters
                for param in item['instanceParameters']:
                    if param['key'] == 'InstanceType':
                        param['value'] = new_instance_type
                        break
                
                # Update the item in DynamoDB
                table.update_item(
                    Key={'PK': pk, 'SK': sk},
                    UpdateExpression="SET instanceParameters = :params",
                    ExpressionAttributeValues={':params': item['instanceParameters']},
                    ReturnValues="UPDATED_NEW"
                )
                print("InstanceType updated successfully!")
            
            except Exception as e:
                print(f"Error updating InstanceType: {e}")
        
        # Call the function
        update_instance_type("pk_value", "sk_value", "t2.4xlarge")