Remove nested attribute in dynamodb - node.js

Let's say I have this item in DynamoDB:
{
"customerId": "customer_001",
"customerName": "itsme",
"address": {
"city": "Frankfurt",
"country": "Germany",
"street1": "c/o Company xxx",
"street2": "Europe",
"street3": "PO Box 406",
"zip": "12345"
}
}
I need to remove the nested attribute address.street3 from the item. How I can accomplish this?
Here is my code below; it works perfectly to remove non-nested attributes (for example, customerName), but if I try to use this in nested attributes (like address.street3), it silently fails.
const params = {
TableName: customerTable,
Key: {
customerId: customerId,
},
AttributeUpdates: {
'address.street3':
{
Action: 'DELETE'
}
}
};
dynamoDb.update(params, function (err, data) {
if (err) {
console.error("Unable to update customer. Error JSON:", JSON.stringify(err, null, 2));
}
else {
console.log("UpdateCustomer succeeded:", JSON.stringify(data.Attributes));
responseHelper.ResponseHelper.success(JSON.stringify(data.Attributes), 200, callback);
}
});
What can I remove the nested attribute address.street3?

Here is the code to remove "address.street3" attribute.
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName : "customer",
Key : {
"customerId": "customer_001"
},
UpdateExpression : "REMOVE address.street3",
ReturnValues : "UPDATED_NEW"
};
console.log("Updating the item...");
docClient.update(params, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data));
}
});

Related

Problem with query on nested attribute DynamoDB

In my code I'm using the AWS.DynamoDB.DocumentClient() for interact with the DB.
My item structure is:
{
"docName": "drinkDoc",
"sortKey": "RISTRETTO",
"i18n": {
"de": "",
"en": "ristretto",
"fr": "",
"it": "ristretto"
},
"params": {
"size": [
"S",
"M",
"L",
"XL"
]
}
}
What I want to do is to retrieve the item filtering by i18n subproperties.
In my code I build a params object like this:
{
"TableName": "MyTable",
"KeyConditionExpression": "#docName = :docName",
"ExpressionAttributeNames": {
"#docName": "docName",
"#i18n": "i18n.it"
},
"ExpressionAttributeValues": {
":docName": "drinkDoc",
":drinkName": "ristretto"
},
"FilterExpression": "#i18n = :drinkName"
}
Then I execute the query in this way:
var docClient = new AWS.DynamoDB.DocumentClient();
docClient.query(params, (err, data) => {
if (err) {
console.error("Unable to retrieve data. Error JSON:", JSON.stringify(err, null, 2));
return reject(JSON.stringify(err, null, 2));
}
console.log("Read data succeeded:", JSON.stringify(data, null, 2));
resolve(data.Items);
});
So far so good.
The problem is that the query returns no item, but item exists in my database, as you can see:
What is wrong in this snippet?
I solved from my self.
As indicated in this link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html
the code
{
"TableName": "MyTable",
"KeyConditionExpression": "#docName = :docName",
"ExpressionAttributeNames": {
"#docName": "docName",
"#i18n": "i18n.it"
},
"ExpressionAttributeValues": {
":docName": "drinkDoc",
":drinkName": "ristretto"
},
"FilterExpression": "#i18n = :drinkName"
}
must be replaced with
{
"TableName": "SmartCoffeeSkillTable",
"KeyConditionExpression": "#docName = :docName",
"ExpressionAttributeNames": {
"#docName": "docName",
"#i18n": "i18n",
"#locale": "it"
},
"ExpressionAttributeValues": {
":docName": "drinks",
":drinkName": "caffè"
},
"FilterExpression": "#i18n.#locale = :drinkName"
}
that is to replace
"FilterExpression": "#i18n = :drinkName" with "FilterExpression": "#i18n.#locale = :drinkName"

Update DynamoDB table with Node.JS returns reserved key word error

I am trying to update a DynamoDB table by following this AWS Tutorial, but I getting the following error:
Unable to update item. Error JSON: {
"message": "Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: hash",
"code": "ValidationException",
"time": "2021-11-10T07:54:18.832Z",
"requestId": "1e657754-c33d-4a55-8245-a107765e4261",
"statusCode": 400,
"retryable": false,
"retryDelay": 43.13890004813747
}
My code looks like this:
import AWS from 'aws-sdk';
var table = "Users";
export async function updateData(email, hash, callback){
AWS.config.update({
region: 'us-west-2',
endpoint: 'http://localhost:8000'
});
var docClient = new AWS.DynamoDB.DocumentClient()
var params = {
TableName: table,
Key:{
"email": email
},
UpdateExpression: "set hash = :var",
ExpressionAttributeValues:{
":var": hash
},
ReturnValues:"UPDATED_NEW"
};
docClient.update(params, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
callback(err, null);
} else {
callback(data, null);
}
});
}
updateData('joejava#icloud.com', 'hash', function(data, err){
console.log(err, data);
})
Any table has the following fields:
email (Key)
first_name
last_name
hash
As far as I can see, my code is very similar to the example.
What am I missing there?
hash is a dynamodb reserved keyword, so we must substitute it in as a ExpressionAttributeName.
var params = {
TableName: table,
Key:{
"email": email
},
UpdateExpression: "set #k = :var",
ExpressionAttributeNames:{
"#k": "hash"
},
ExpressionAttributeValues:{
":var": hash
},
ReturnValues:"UPDATED_NEW"
};

Updating dynamoDB from Lambda function failed

I've got a problem updating DynamoDB entry.
The DB looks like this
{
"userId":"amzn1.ask.account.XYZ",
"mapAttr":{
"name":"John",
"colors":[
"yellow",
"white"
]
}
}
I want to update the List of colors utilizing follwoing code:
var docClient = new AWS.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" });
var params = {
TableName: "myTable",
Key: {
userId: userId
},
UpdateExpression: "SET #mapAttr = list_append(#mapAttr, :entry)",
ExpressionAttributeNames: { "#mapAttr": "mapAttr.colors" },
ExpressionAttributeValues: {
":entry": ["blue"]
},
ReturnValues: "UPDATED_NEW"
};
docClient.update(params, function(err, data) {
if (err) {
console.error(
"Unable to update item. Error JSON:",
JSON.stringify(err, null, 2)
);
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
});
and i get the following message:
Unable to update item. Error JSON: { "message": "The provided key
element does not match the schema", "code": "ValidationException",
Any ideas why... ?
Per AWS documentation, you need to split your ExpressionAttributeNames up.
UpdateExpression: "SET #mapAttr.#colors = list_append(#mapAttr.#colors, :entry)",
ExpressionAttributeNames: {
"#mapAttr": "mapAttr",
"#colors": "colors"
}

How do I update nested list data in dynamodb using document client

I have a dynamoDB table that has an Item that includes a UserId and a List of lists. It looks like this:
Item:
{
UserId: 'abc123',
Lists: [
{
id: 1,
title: 'My favorite movies',
topMovies: [
{
id: 1,
title: 'Caddyshack'
},
{
id: 2,
title: 'Star Wars'
}
]
}
]
}
Now, lets the user has created a new list titled, "My favorite TV Shows", and wants to insert it into the Lists array with id: 2.
How would I update this object using document client. I've looked through several examples and I've found nothing that explains what I'm trying to do. It's making me think that perhaps I'm not using DynamoDB correctly and I should have a different object schema.
I've attempted using this, but it is overwriting my previous object.
exports.handler = (event, context, callback) => {
console.log(event);
const params = {
TableName: "top-ten",
Key: {
"UserId": 'abc123',
},
UpdateExpression: "set Lists =:newItem",
ExpressionAttributeValues: {
":newItem": {
"id": 2,
"title": "Favorite TV Shows",
"topMovies": [{"id": 1, "title" : "The Simpsons"}]
},
},
ReturnValues: "UPDATED_NEW"
};
dynamodb.update(params, function(err, data) {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
EDIT: Ok, I've figured out that if I put
UpdateExpression: "set Lists[1] =:newItem"
it updates the item correctly. But now, how do I know how many items I have in my list array?
You should use list_append. The function adds two lists together, so you need to make your item to add a list.
exports.handler = (event, context, callback) => {
console.log(event);
const params = {
TableName: "top-ten",
Key: {
"UserId": 'abc123',
},
UpdateExpression : "SET #attrName = list_append(#attrName, :attrValue)",
ExpressionAttributeNames : {
"#attrName" : "Lists"
},
ExpressionAttributeValues : {
":attrValue" : [{
"id": 2,
"title": "Favorite TV Shows",
"topMovies": [{"id": 1, "title" : "The Simpsons"}]
}]
},
ReturnValues: "UPDATED_NEW"
};
dynamodb.update(params, function(err, data) {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});

node.js: DynamoDB DocumentClient returning empty object

I am using DynamoDB local and can create and delete table. I created a table with only one key like below
const tablePromise = dynamodb.listTables({})
.promise()
.then((data) => {
const exists = data.TableNames
.filter(name => {
return name === tableNameLogin;
})
.length > 0;
if (exists) {
return Promise.resolve();
}
else {
const params = {
TableName: tableNameLogin,
KeySchema: [
{ AttributeName: "email", KeyType: "HASH"}, //Partition key
],
AttributeDefinitions: [
{ AttributeName: "email", AttributeType: "S" },
],
ProvisionedThroughput: {
ReadCapacityUnits: 10,
WriteCapacityUnits: 10
}
};
dynamodb.createTable(params, function(err, data){
if (err) {
console.error("Unable to create table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Created table. Table description JSON:", JSON.stringify(data, null, 2));
}
});
}
});
Now I want to insert an item in the table following example doc at AWS.
var docClient = new AWS.DynamoDB.DocumentClient();
var tableNameLogin = "Login"
var emailLogin = "abc#gmail.com";
var params = {
TableName:tableNameLogin,
Item:{
"email": emailLogin,
"info":{
"password": "08083928"
}
}
};
docClient.put(params, function(err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});
When I run the insert item code, I get Added item: {} Why does it output an empty object? Is it actually inserting anything? I looked into this callback example but this time it doesn't output anything.
You need to add ReturnValues: 'ALL_OLD' to your put params. It will look like as mentioned below.
var params = {
TableName:tableNameLogin,
Item:{
"email": emailLogin,
"info":{
"password": "08083928"
}
},
ReturnValues: 'ALL_OLD'
};
For more details, you can follow this https://github.com/aws/aws-sdk-js/issues/803

Resources