Updating dynamoDB from Lambda function failed - node.js

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"
}

Related

Dynamodb sdk update entry at specific index in list in a map using node js

I am trying to update a specific list entry using a counter.
const taskParams = {
TableName: CONST.NAMES.SUJET_TABLE_NAME,
Key: {
id: defectId
},
UpdateExpression: "SET #list.#epicType.#tasks[#taskIndex].#tracking =:attrValue ",
ExpressionAttributeNames: {
'#list': 'epicsList',
'#tasks': 'tasks',
'#epicType': epicType,
'#taskIndex': taskCounter,
'#tracking': 'tracking',
},
ExpressionAttributeValues: {
':attrValue': epicData["tasks"][0]["tracking"],
},
};
try {
await documentClient.update(taskParams).promise();
console.log("Task successfully created.")
} catch (err) {
console.log("Unable to create Task ", err);
}
When executing I get the following error :
ValidationException: Invalid UpdateExpression: Syntax error; token: "#taskIndex", near: "[#taskIndex]"
Is the syntax wrong or is there something else I am not aware of?
I finally found the answer, for those who are having trouble with this :
const taskParams = {
TableName: CONST.NAMES.SUJET_TABLE_NAME,
Key: {
id: defectId
},
UpdateExpression: "SET #list.#epicType.#tasks[" + taskIndex+ "].#tracking =:attrValue ",
ExpressionAttributeNames: {
'#list': 'epicsList',
'#tasks': 'tasks',
'#epicType': epicType,
'#tracking': 'tracking',
},
ExpressionAttributeValues: {
':attrValue': epicData["tasks"][0]["tracking"],
},
};

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"
};

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

Remove nested attribute in dynamodb

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));
}
});

node.js passing a parameter to DynamoDB updateItem method

I want to write a function that updates given parameter in dynamodb.
For example in a dynamodb table where each userId is the key I have values like
{
"categoryname": "a",
"skillState": "a",
"skipcount": 1,
"userId": "amzn1.ask.account.xxx”
}
I wanna set the "categoryname": "b" although there might be 10-15 fields like this so I dont wanna hard code the field name.
function (userId,itemToUpdate,itemValue,callback) {
var updateExpressionString = "SET #"+itemToUpdate+" =:val1";
var expressionAtt = '#'+itemToUpdate + '';
console.log(updateExpressionString)
console.log(expressionAtt)
this.dynamodb.updateItem({
TableName: constants.dynamoDBDetailTableName,
Key: {
userId: {
S: userId
}
},
UpdateExpression: updateExpressionString,
ExpressionAttributeNames : {
expressionAtt : itemToUpdate
},
ExpressionAttributeValues : {
':val1': {'S':itemValue}
}
}, function (err, data) {
if (err) {
console.log(err)
console.log('Error ')
} else if (data.Item === undefined) {
}else {
console.log(data)
}
});
}
In ExpressionAttributeNames:
{ ValidationException: ExpressionAttributeNames contains invalid key: Syntax error; key: "expressionAtt"
This throws error obviously thinking that expressionAtt is the key while it is a local variable.
I am new to node.js , how can pass the local variable in to ExpressionAttributeNames and ExpressionAttributeValues
One way of dealing with this could be to pull the object out of updateItem, put it into its own variable like so:
var item = {
TableName: constants.dynamoDBDetailTableName,
Key: {
userId: {
S: userId
}
},
UpdateExpression: updateExpressionString,
ExpressionAttributeNames: {},
ExpressionAttributeValue: {
':val1': {'S': itemValue}
}
};
item.ExpressionAttributeNames[expressionAtt] = itemToUpdate;
this.dynamodb.updateItem(item);
I believe that will fix your problem

Resources