Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Putting/Updating item in DynamoDB fails for the UpdateExpression syntax

I've created a DynamoDB table, and in my Python code, I have the resource initialised as follows:

self.dynamodb = self.session.resource('dynamodb').Table('aws-ci')

The table has just one index/key, with the name environment. I am trying to PUT into it, an object as follows:

{
  "environment": "beta",
  "X": {
    "current_sha": "sha1",
    "deployed": true,
    "prev_sha": "sha2",
    "status": "inactive"
  },
  "Y-Z": {
    "current_sha": "sha1",
    "deployed": false,
    "prev_sha": "sha2",
    "status": "active"
  }
}

where, X and Y-Z are the names of micro-services. My insertion code is as follows:

def put_service_data(self, environment, service_name, service_data, status = None):
    get_previous = self.dynamodb.get_item(
        Key = {
            'environment': environment
        }
    ).get(service_name)
    service_data['prev'] = get_previous and get_previous.get('current_sha') or 'NULL'
    if status == 'rollback' and get_previous:
        service_data['current'] = get_previous.get('current_sha')
        service_data['prev'] = get_previous.get('prev_sha')
    set_query = "SET {0}.current_sha = :current, {0}.prev_sha = :prev, {0}.deployed = :is_deployed, {0}.current_status = :status".format(service_name)
    updated = self.dynamodb.update_item(
        Key = {
            'environment': environment
        },
        UpdateExpression = set_query,
        ExpressionAttributeValues = {
            ':current': service_data.get('current'),
            ':prev': service_data.get('prev'),
            ':status': service_data.get('status'),
            ':is_deployed': service_data.get('deployed')
        },
        ReturnValues = "ALL_NEW"
    )
    return updated

Previously, instead of {0}.current_status, I had {0}.status, but that raised the following error:

An error occurred (ValidationException) when calling the UpdateItem operation: Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: status

Anyway, I changed that attribute name name to current_status and tried the insertion again, only this time I am receiving:

An error occurred (ValidationException) when calling the UpdateItem operation: The document path provided in the update expression is invalid for update

when trying to set attributes for service X, and the following when trying for Y-Z:

An error occurred (ValidationException) when calling the UpdateItem operation: Invalid UpdateExpression: Syntax error; token: "-", near: "Y-Z"

I'm currently unable to understand how the update_item call should work.

like image 377
hjpotter92 Avatar asked Aug 26 '16 07:08

hjpotter92


People also ask

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.

What causes DynamoDB system errors?

The most likely cause of a failed read or a failed write is throttling. For BatchGetItem , one or more of the tables in the batch request does not have enough provisioned read capacity to support the operation. For BatchWriteItem , one or more of the tables does not have enough provisioned write capacity.

Does DynamoDB Update create if not exists?

UpdateItem behaves as an “UPSERT” operation. This means that if you try to update an item that doesn't exist, DynamoDB will automatically create it for you. Like with PutItem , you can add conditions to your UpdateItem API calls to modify this behavior, but there is no way to implement it service-side.

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.


1 Answers

Have you tried this? http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html#ExpressionAttributeNames

set_query = "SET #service_name.current_sha = :current, #service_name.prev_sha = :prev, #service_name.deployed = :is_deployed, #service_name.current_status = :current_status"
updated = self.dynamodb.update_item(
    Key = {
        'environment': environment
    },
    UpdateExpression = set_query,
    ExpressionAttributeValues = {
        ':current': service_data.get('current'),
        ':prev': service_data.get('prev'),
        ':current_status': service_data.get('status'),
        ':is_deployed': service_data.get('deployed')
    },
    ExpressionAttributeNames = {
         '#service_name': service_name,
    },
    ReturnValues = "ALL_NEW"
)
like image 54
ananth krishnan Avatar answered Sep 21 '22 05:09

ananth krishnan