27
votes

I need to append a string to a string set in a dynamodb table using the corresponding key. This is the Update expression I use to do updateItem :

  var params = {
    "TableName" : tableName,
    "Key": {
      "ID": {
        S: "20000"
      }
    },
    "UpdateExpression" : "SET #attrName = list_append(#attrName, :attrValue)",
    "ExpressionAttributeNames" : {
      "#attrName" : "entries"
    },
    "ExpressionAttributeValues" : {
      ":attrValue" : {"SS":["000989"]}
    }   };

This works when I do updateItem() using the aws cli. But when using aws-sdk in nodejs, I am getting the error:

Invalid UpdateExpression: Incorrect operand type for operator or function; operator or function: list_append, operand type: M\n

Any help? Thanks

4
have you tried changing the value for :attrValue to {"L":[{"S":"000989"}]}Eli Albért
Alternatively, what is the type of entries in your table?Eli Albért

4 Answers

48
votes

list_append can be read as a "concatenate" operation. You just give it two lists.

"UpdateExpression" : "SET #attrName = list_append(#attrName, :attrValue)",
"ExpressionAttributeNames" : {
  "#attrName" : "entries"
},
"ExpressionAttributeValues" : {
  ":attrValue" : ["000989"]
}

It's worth remembering that lists (and maps) in DynamoDB are not typed and can store arbitrary data.

Side note: Armed with this knowledge, the documentation on appending to the beginning of the list now makes sense:

list_append (operand, operand)

This function evaluates to a list with a new element added to it. You can append the new element to the start or the end of the list by reversing the order of the operands.

7
votes

There's an accepted answer on this question which helped me with part of this issue. However, we'll typically want to update lists with additional objects, not strings. For this, I found it useful to avoid using ExpressionAttributeNames if possible.

1) Make sure the value in your item in your DynamoDB table is a list. 2) Make sure you pass in a list of objects (even if you only have one), not a simple object

           UpdateExpression: "set pObj.cObj= list_append(pObj.cObj, :obj)",
           ExpressionAttributeValues: {
               ":obj": [
                   {myObject: {
                       property1: '',
                       property2: '',
                       property3: '',

                   }}
                ]
           },
4
votes

I thought I'd just throw this out there as another option for adding or appending an "object" to a list. It's a map being added an item to the list, and worked well for me:

var upsertExpr = (obj.comments == undefined) ? " :attrValue" : "list_append(#attrName, :attrValue)";

var params = {
    TableName: 'tableName',
    Key: {
        'id': {'S': id},
    },
    UpdateExpression : "SET #attrName = " + upsertExpr,
    ExpressionAttributeNames : {
      "#attrName" : "comments"
    },
    ExpressionAttributeValues : {
      ":attrValue" : {
            "L": [
                { "M" : 
                    {
                        "comment": {"S": comment},
                        "vote": {"N": vote.toString()}
                    }
                }
            ]
        }
    }
};
1
votes

maybe this will help someone. i was struggling with updating a list and was getting the same error message as the original poster. i managed to solve my problem when i finally understood the documentation (see the Adding Elements To a List example here http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.ADD)

points to note are: 1) that the "list_append takes two lists as input, and appends the second list to the first." and 2) that ExpressionAttributeValues is a list! like this:

{
":vals": {
    "L": [
        { "S": "Screwdriver" },
        {"S": "Hacksaw" }
    ]
}

}

good luck!