'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)`,
};
Solution 1:[1]
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 updatefaif it exists, but if it doesn't, you get the errorThe document path provided in the update expression is invalid for update.SET fa = {"papa":"dsfadsf"}will create newfabut 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"
]
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Harish KM |
