How to create and populate lists in DynamoDB - amazon-dynamodb

I wish to create an Item in DynamoDB that is a list. This is my code:
var list_update_params = {
TableName: "table01",
Key: {
"MachineID": {
"S": MachineID
},
"Hour": {
"S": Hour
}
},
UpdateExpression: "set var01_list = list_append(var01_list, :ot)",
ExpressionAttributeValues: {
":ot": {"L": [{"N": var01}]}
},
ReturnValues: "NONE"
};
dynamodb.updateItem(list_update_params, function(err, data) {
if (err) console.log(err, err.stack);
else console.log("Updated List to DynamoDB");
});
The problem is list_append expects the attribute var01_list to already be present, but I wouldn't know at the first insert. Is there a technique where it'll let me create an insert a List attribute if one doesn't exist and append to it in later calls?

Got the answer from a similar post here.
UpdateExpression: "set var01_list= list_append(if_not_exists(var01_list, :empty_list), :h)",
ExpressionAttributeValues: {
":h": {"L": [{"N":var01}]},
":empty_list": {"L": []}
},
The key was using if_not_exists with list_append. Didn't know that could be done in this matter

Related

Why does Dynamo DB throw an error when updating a map key with the same value?

I am trying to run a simple update query, but got an error when I tried to update the key of a map to the same value. Is there a technical reason this would be disallowed? or some kind of best-practice that I am violating by trying to do this?
Error:
ValidationException: Invalid UpdateExpression: Two document paths overlap with each other;
must remove or rewrite one of these paths; path one: [questions, What is xx?], path two: [questions, What is xx?]
Query object:
{
TableName: 'notesTable',
Key: { topic: 'My tooic' },
ExpressionAttributeNames: { '#qq': 'What is xx?', '#updq': 'What is xx?' },
ExpressionAttributeValues: { ':updans': 'new answer' },
UpdateExpression: 'REMOVE questions.#qq SET questions.#updq = :updans'
}
Multiple ways to deal with scenario when same key needs to be updated. Instead of removing and updating the same key, we can simply SET the key , which replaced the value anyhow.
So, simple way is to send different updateExpression each time.
const qq = "What is xx2?";
const updq = "What is xx?";
let expressionAttributeNames;
let UpdateExpression;
if (qq === updq) {
expressionAttributeNames = { "#updq": "What is xx?" };
UpdateExpression = "SET questions.#updq = :updans";
} else {
expressionAttributeNames = { "#qq": "What is xx1?", "#updq": "What is xx?" };
UpdateExpression = "REMOVE questions.#qq SET questions.#updq = :updans";
}
docClient.update(
{
TableName: "test",
Key: {
id: "My tooic",
},
ExpressionAttributeNames: expressionAttributeNames,
ExpressionAttributeValues: { ":updans": "new answer1" },
UpdateExpression: UpdateExpression,
},
function (error, result) {
console.log("error", error, "result", result);
}
);

ConditionalExpression DynamoDb Insert

I have the below data schema for my DynamoDb table. I am trying to append list subscribers on the condition if input = name (ex: input = my-topic2). There can be many maps in the “topics” list and I need to search for the map where the name = input and from there add the subscriber to that topic.
{
“server-id”: “123345678”,
“server-name”: “my-server”
“topics”: [
{
“name”: “my-topic”,
“subscribers”: []
},
{
“name”: “my-topic2”,
“subscribers”: [] //This is what I need to append on a condition that the input = “my-topic2”
}
]
}
I have the current following paeans I am using which appends “my-topic” subscribers.
params = {
ExpressionAttributeNames: {
"#T": "topics",
"#S": "subscribers"
},
ExpressionAttributeValues: {
":vals": [
message.author.id
]
},
Key: {
'server-id': serverID
},
ReturnValues: "ALL_NEW",
TableName: tableName,
UpdateExpression: "SET #T[0].#S = list_append(#T[0].#S, :vals)"
};

DynamoDb Nested Map Update

After working a bit with DynamoDb I’ve run into an issue that from what I’ve read so far is not really ideal for DynamoDb. So before I make the switch to RDS, I’d like to see if there’s anyway I can achieve what I need with DynamoDb. I’ve also thought about breaking this out into multiple tables for DynamoDb
Below of my Data schema. There is a list nested inside the item. I need to be able to append strings to the list.
{
“server-id”: “123345678”,
“server-name”: “my-server”
“topics”: [
{
“name”: “my-topic”,
“subscribers”: [] //This is what I need to append
}
]
}
Yes, this is possible.
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
var params = {
ExpressionAttributeNames: {
"#T": "topics",
"#S": "subscribers"
},
ExpressionAttributeValues: {
":vals": {
L: [
{ N: "123" },
{ N: "456" }
]
}
},
Key: {
'server-id': { S: '123345678' }
},
ReturnValues: "ALL_NEW",
TableName: 'dummy-table',
UpdateExpression: "SET #T[0].#S = list_append(#T[0].#S, :vals)"
};
ddb.updateItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});

How to add items to a map in DynamoDB

I'm using the AWS.DynamoDB.DocumentClient with nodejs (lambda functions on AWS)
I've to a db called Translations, primary key Term, sort key Category.
Basically I'm trying to write data in like this:
{
Term: 'hello_there',
Category: 'common_phrases',
Translations: {
en-ca: 'Hello There!'
}
}
and I want to update Translations Map to perhaps add another language, or just modify the en-ca portion of the object.
I've tried the following:
let params = {
TableName: 'Translations',
Key: {
Term: 'hello_there',
Category: 'common_phrases',
},
UpdateExpression:
'SET Translations.#lang = list_append(Translations, :term)',
ExpressionAttributeValues: {
':term': 'french version',
},
ExpressionAttributeNames: {
'#lang': 'fr-ca',
},
}
But I get an error about the wrong operand type.
I've tried:
UpdateExpression:
'SET Translations.#lang = :term',
ExpressionAttributeValues: {
':term': 'french version',
},
ExpressionAttributeNames: {
'#lang': 'fr-ca',
},
But this overwrites the entire contents of the Translations field. Meaning that if I already had en-ca in there, now I would only have fr-ca.
I tried this as well, but also get an operand error:
{
UpdateExpression: 'ADD Translations :term',
ExpressionAttributeValues: {
':term': { 'fr-ff': 'frenchterm' },
},
Any suggestions on how to add/update items to the Translations Map?
Your SET expression was close, try something like this:
UpdateExpression:
'SET #trans.#lang = :term',
ExpressionAttributeValues: {
':term': 'french version',
},
ExpressionAttributeNames: {
'#trans': 'Translations`,
'#lang': 'fr-ca',
},

DyanamoDB SCAN with nested attribute

Can I scan DynamoDB by 'order.shortCode', in the given example. The console is indicating I can't with dot notation, and I can't find any documentation on it.
{
"key2": "cj11b1ygp0000jcgubpe5mso3",
"order": {
"amount": 74.22,
"dateCreated": "2017-04-02T19:15:33-04:00",
"orderNumber": "cj11b1ygp0000jcgubpe5mso3",
"shortCode": "SJLLDE"
},
"skey2": "SJLLDE"
}
To scan by a nested attribute, you should use ExpressionAttributeNames parameter to pass each path component (i.e. order and shortCode) separately into FilterExpression like shown below:
var params = {
TableName: 'YOUR_TABLE_NAME',
FilterExpression: "#order.#shortCode = :shortCodeValue",
ExpressionAttributeNames: {
'#order': 'order',
"#shortCode": "shortCode"
},
ExpressionAttributeValues: {
':shortCodeValue': 'SJLLDE'
}
};
dynamodbDoc.scan(params, function(err, data) {
});
Here is a link to documentation explaining this:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html#Expressions.ExpressionAttributeNames.NestedAttributes

Resources