Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DynamoDB: How to append to list values in document

I have a DynamoDB table, users, that has a document structure similar to the following:

{
  "id": "1",
  "name": "john",
  "hobbies": [
    {
      "description": "painting",
      "skill": "amateur"
    },
    {
      "description": "cooking",
      "skill": "expert"
    }
  ]
}

As can be seen, the document structure contains a list attribute, hobbies, that can contain a collection of hobby "objects".

I want to write an update statement to add a new element to the list attribute if it doesn't exist yet.

For example, I want to be able to pass a hobby with a "description" of "designing" and a "skill" of "amateur" to my update function and, since this hobby isn't yet in the list of hobbies, it should be added to the list. If the hobby is already there, it should not be added a second time.

I am working in Node.js and therefore using JavaScript and the AWS.DynamoDB.DocumentClient() with a parameter map to perform my functions. The AWS documentation has been helpful, but I am struggling to find examples of how to set up params to conditionally append items to a list attribute as I am describing. Does anyone perhaps have some advice on how to do this?

like image 695
Stanley Avatar asked Jan 24 '17 13:01

Stanley


1 Answers

You can use list_append() and if_not_exists() together in an UpdateExpression to append to a potentially non-existent list column, but there is no way to prevent appending to that list if an object with the same properties already exists inside the list.

As an alternative you could replace your "hobbies" List with a String Set and just JSON.stringify() each "hobbie" before inserting it (and JSON.parse() it when reading the values back out):

var AWS = require('aws-sdk')
var DB = new AWS.DynamoDB.DocumentClient()
var hobbieToAdd = JSON.stringify({
  description: "designing",
  skill: "amateur"
})
DB.update({
  TableName: "TableName",
  Key: { id: "1" },
  UpdateExpression: "ADD #hobbies :hobbie",
  ExpressionAttributeNames: { "#hobbies" : "hobbies" },
  ExpressionAttributeValues: { ":hobbie": DB.createSet([hobbieToAdd]) }
})

Using a String Set would ensure that duplicates could never appear, but it also requires you to (de)serialize the hobbies yourself.

like image 101
idbehold Avatar answered Sep 22 '22 15:09

idbehold