Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create or update dynamodb

Currently, I'm checking if the item exists with a query and then I'm using put or updateItem, I want to change it and make a single call to DDB. I want to make a query that will update or create item.

Here is a example of my item:

{
   id: 'dsfadsf'
   fa: { "apple" : { "S" : "76-100" }, "yolo" : { "S" : "0-25" }
   pa: { "finish" : { "BOOL" : false },    "userKey" : { "S" : "3e299e12-9e66" }  }
   createdAt: 32432432423
}

item types:

createdAt - Number
fa - Map
pa - Map
id - String
finish - Boolean
key - String

If item exists I want to push a new item like {papa: 'dsfadsf'} (never modify existing item inside fa Map) and modify finish value inside pa Map

This is the item after the update:

{
   id: 'dsfadsf'
   fa: { "apple" : { "S" : "76-100" }, "yolo" : { "S" : "0-25" }, "papa": { "S" : "dsfadsf"} }
   pa: { "finish" : { "BOOL" : true },    "userKey" : { "S" : "3e299e12-9e66" }  }
   createdAt: 32432432423
}

Here is what I tried and its not working

{
    TableName: tableName,
    Key: {
      id: "dsfadsf",
    },
    UpdateExpression: `SET #id = :id, fa.${itemName} = if_not_exists(fa.${itemName}, :text), pa.finish = if_not_exists(pa.finish, :finishval), #ca = :ca`,
    ExpressionAttributeNames: {
      "#id": "id",
      "#ca": createdAt
    },
    ExpressionAttributeValues: {
      ":id": "7fd9a81b-7a7c-4cfb-9c84-25dc2798a8f7",
      ":text": itemText,
      ":finishval": true,
      ":ca": 32432432423
    },
    ConditionExpression: `attribute_not_exists(id)`,
  };
like image 995
ronara Avatar asked Jul 10 '20 22:07

ronara


People also ask

What is the difference between put and update in DynamoDB?

The main difference between the two is, PutItem will Replace an entire item while UpdateItem will Update it. Eg. This will replace Name and Gender and now new Item is UserId and Country. While if you want to update an item from Name = ABC to Name = 123 you have to use UpdateItem .

How do I update a DynamoDB item?

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.

Does DynamoDB Update create if not exists?

Edits an existing item's attributes, or adds a new item to the table if it does not already exist.


Video Answer


1 Answers

TLDR

This isn't possible with the current structure of your item. Change fa & pa to be string sets, get rid of finish: true & use the ADD update expression.


This is not possible with the current structure of your item. Here's why — To meet your requirement, UpdateExpression needs to be of the form:

if "fa" exists, add {"papa":"dsfadsf"} to it
else, create new "fa"={"papa":"dsfadsf"}

Of all the DynamoDB update expressions, only SET & ADD can be used in this scenario.

The above if else condition cannot be expressed in an UpdateExpression with SET due to the following reasons:

  • SET fa.papa = 'dsfadsf' will update fa if it exists, but if it doesn't, you get the error The document path provided in the update expression is invalid for update.

  • SET fa = {"papa":"dsfadsf"} will create new fa but overwrite it if it exists.

If you try to combine ADD & SET to achieve the above if else condition, into something like ADD fa {} SET fa.papa = dsfadsf, you get the error Two document paths overlap with each other; must remove or rewrite one of these paths

So we're only left with the ADD expression now, but ADD only works on sets. So if you can afford to turn the contents of fa & pa into sets of strings, you can achieve your goal of "create or update in 1 go". Here's how it'll work:

The original item structure has to be:

{
  "ca": 32432432423,
  "fa": [
    "apple:76-100",
    "yolo:0-25"
  ],
  "id": "dsfadsf",
  "pa": [
    "key:9e66"
  ]
}

In DynamoDB JSON, that's:

{
  "ca": {
    "N": "32432432423"
  },
  "fa": {
    "SS": [
      "apple:76-100",
      "yolo:0-25"
    ]
  },
  "id": {
    "S": "dsfadsf"
  },
  "pa": {
    "SS": [
      "key:9e66"
    ]
  }
}

Now, using the following code:

let AWS = require("aws-sdk")
let docClient = new AWS.DynamoDB.DocumentClient()
docClient.update({
    TableName: "my-table",
    Key: { id: "dsfadsf" },
    UpdateExpression: `ADD fa :fa, pa :pa SET ca = :ca`,
    ExpressionAttributeValues: {
        ":fa": docClient.createSet(["papa:dsfadsf"]),
        ":pa": docClient.createSet(["finished"]),
        ":ca": 32432432423
    }
}

If an item with the id "dsfadsf" already exists, it's updated as follows:

{
  "ca": {
    "N": "32432432423"
  },
  "fa": {
    "SS": [
      "apple:76-100",
      "papa:dsfadsf",
      "yolo:0-25"
    ]
  },
  "id": {
    "S": "dsfadsf"
  },
  "pa": {
    "SS": [
      "finished",
      "key:9e66"
    ]
  }
}

If an item with the id "dsfadsf" does NOT exist, it's created as follows:

{
  "ca": {
    "N": "32432432423"
  },
  "fa": {
    "SS": [
      "papa:dsfadsf"
    ]
  },
  "id": {
    "S": "dsfadsf"
  },
  "pa": {
    "SS": [
      "finished"
    ]
  }
}
like image 174
Harish KM Avatar answered Sep 26 '22 13:09

Harish KM