DynamoDB : SET list_append not working using aws sdk

23,793

Solution 1

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.

Solution 2

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: '',

                   }}
                ]
           },

Solution 3

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()}
                    }
                }
            ]
        }
    }
};

Solution 4

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!

Share:
23,793
void
Author by

void

Dat aeng in eer

Updated on October 24, 2020

Comments

  • void
    void over 3 years

    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

  • samcorcos
    samcorcos over 7 years
    That did it for me, thanks. The important thing to note is that list_append takes in two lists: list_append([list1], [list2]). Anything else will error. So if you pass an object/map (as I was attempting to do), you need to wrap that object in a list: [{ object }]
  • CuriousCoder
    CuriousCoder over 7 years
    Thanks a lot for this answer. Been searching how to update lists with objects for so long
  • djf
    djf over 5 years
    Thank you so much! I've been trying to figure this out for two days. Unfortunately, the AWS documentation only covers the most trivial use cases..
  • Steven Musumeche
    Steven Musumeche over 2 years
    The key is that the object you are adding has to be wrapped in a list itself. Thank you.
  • Rafael Bertelli
    Rafael Bertelli about 2 years
    Thanks! that did it