Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

updating a JSON array in AWS dynamoDB

My document looks like this:

{
  "data": {
      "eventId": "20161029125458-df-d",
      "name": "first",
      "purpose": "test",
      "location": "yokohama",
      "dateArray": [],
      "attendees": [
        {
          "attendeeId": "2016102973634-df",
          "attendeeName": "lakshman",
          "personalizedDateSelection": {}
        },
        {
          "attendeeId": "2016102973634-tyyu",
          "attendeeName": "diwaakar",
          "personalizedDateSelection": {}
        }
      ]
    }
}

Say, I need to update the attendee JSON array with attendeeId: 2016102973634-df. I tried many ways ways using update and condition expression, but no success.

Here is my try:

const params = {
  TableName: "event",
  Key: {
    "eventId": eventId 
  },
  UpdateExpression: "SET attendees[???] = ",
  ConditionExpression: attendees.attendeeId = "2016102973634-df", 
  ExpressionAttributeValues: {
    ":attendee" : attendeeList
  },
  ReturnValues: "ALL_NEW"
};


dynamo.update(params, (err, data) => {
  if (err) {
    return reject(err);
  }
  console.log(data.Attributes);
});

Could not find any resources for updating an Json in a array.

After @notionquest's comment: - Have not used any JsonMarshaller. Initially I added the empty array to attendees field like this:

{
  "eventId": "20161029125458-df-d",
  "name": "first",
  "purpose": "test",
  "location": "yokohama",
  "dateArray": [],
  "attendees": []
}

and then When a new attendee comes I add it to the attendees property like this:

const attendee = {
  "attendeeName": "user1",
  "personalizedDateSelection": {"today": "free"}
}
const attendeeList = [attendee];
const eventId = "20161029125458-df-d";


const params = {
  TableName: "event",
  Key: {
    "eventId": eventId
  },
  UpdateExpression: "SET attendees = list_append(attendees, :attendee)",
  ExpressionAttributeValues: {
    ":attendee" : attendeeList
  },
  ReturnValues: "ALL_NEW"
};


dynamo.update(params, (err, data) => {
  if (err) {
    return reject(err);
  }
  console.log("in update dynamo");
  console.log(data.Attributes);
});

As you have seen in the above snippets, initially I add empty [] array and add a new attendee using the above code. Now, How do I update a specific JSON in an array. If you say that is not possible, what else can I try?

Should I try this :

  1. Get the Full JSON.
  2. Manipulate the JSOn and change the things I want in my nodeJS.
  3. And then update the new JSON to dynamoDB.
  4. But this consumes two calls to dynamoDB which seems to be inefficient.

Would like to know If there is any round way ?

like image 752
Lakshman Diwaakar Avatar asked Oct 29 '16 08:10

Lakshman Diwaakar


People also ask

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.

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.

Can you store JSON in DynamoDB?

You can store a JSON document as an attribute in a DynamoDB table. To do this, use the withJSON method of Item . This method parses the JSON document and maps each element to a native DynamoDB data type.


3 Answers

you can store the index of list. while updating the list we can use them. For example ,

{


"data": {
      "eventId": "20161029125458-df-d",
      "name": "first",
      "purpose": "test",
      "location": "yokohama",
      "dateArray": [],
      "attendees": [
        {  
          "index":0,  
          "attendeeId": "2016102973634-df",
          "attendeeName": "lakshman",
          "personalizedDateSelection": {}
        },
        {
           "index":1,
          "attendeeId": "2016102973634-tyyu",
          "attendeeName": "diwaakar",
          "personalizedDateSelection": {}
        }
      ]
    }
}
const params = {
  TableName: "event",
  Key: {
    "eventId": eventId 
  },
  UpdateExpression: "SET attendees[attendee.index].attendeeName = :value",
  ExpressionAttributeValues: {
    ":value" : {"S":"karthik"}
  },
  ReturnValues: "ALL_NEW"
};


dynamo.update(params, (err, data) => {
  if (err) {
    return reject(err);
  }
  console.log(data.Attributes);
});
like image 126
Karthik Avatar answered Sep 26 '22 03:09

Karthik


An example of an update query:

Data structure (saved in DynamoDB)

{
  tenant_id: 'tenant_1',
  users: {
    user1: {
      _id: 'user1',
      email_address: '[email protected]'
    },
    user2: {
      _id: 'user2',
      email_address: '[email protected]'
    }
  }
}

Data for update (used in the params)

var user = {
 email_address: '[email protected]'
}

Params

var params = {
    TableName: 'tenant-Master',
    Key: {
       "tenant_id": 'tenant_1'
    },
    UpdateExpression: "set #users.user1 = :value",
    ExpressionAttributeNames: {
    "#users": "users"
    },
    ExpressionAttributeValues: {
    ":value": user,
    },
 };

Explanation

By switching to a map of maps from an array of maps we can now use UpdateExpression: "set #users.user1 = :value" to update our nested object at the map of users with the id of user1.

NOTE: This method as is will REPLACE the entire map object at users.user1. Some changes will need to be made if you want to keep pre-existing data.

like image 45
Kenpachi Avatar answered Sep 26 '22 03:09

Kenpachi


I could not find any answer to query and update the JSON-array. I think this may be AWS profitable motive to not allow those features. If you need to query on a particular ID other than primary key, you need to make a secondary index which is cost effective. This secondary index cost is additional to the dyn amoDB table cost.

Since, I did not want to pay extra bucks on secondary index, I changed my dynamoDB schema to the following:

{
  "data": {
      "eventId": "20161029125458-df-d",
      "name": "first",
      "purpose": "test",
      "location": "yokohama",
      "dateArray": [],
      "attendees": {
        "2016102973634-df": {
          "attendeeId": "2016102973634-df",
          "attendeeName": "lakshman",
          "personalizedDateSelection": {}
        },
        "2016102973777-df": {
          "attendeeId": "2016102973777-df",
          "attendeeName": "ffff",
          "personalizedDateSelection": {}
        }
      }
    }
}

Changing attendees from [] to {}. This allows me the flexibility to query particular attendeeId and change the entire JSON associated with that. Even though, this is a redundant step, I do not want to spend extra bucks on my hobby project.

like image 26
Lakshman Diwaakar Avatar answered Sep 23 '22 03:09

Lakshman Diwaakar