DynamoDB update list of list items - amazon-web-services

I need your help to update/add item in a list of list of DynamoDB.
I want to add and update a list that is composed by a list.
How can i do that? Thanks for your help
Here my example:
DATABASE
Item{1}
idProject:"15azeze-55ze"
dateCreationProjectString: 08/01/2018 14:6:32
environnements: List[1]
0 MAP {3}
idEnvironnement: "11-aa",
name:"Exemple Environnement"
tasks[0]
NodeJS code :
let newTask = {
authorTask : "Toto",
dateCreationTask: "01/01/1960",
idTask: "154-141-aa41",
nameTask: "Task name ..."
};
dynamodbdc.update({
TableName: "projects",
Key: { idProject: "15azeze-55ze", idEnvironnement:"11-aa" },
ReturnValues: 'ALL_NEW',
UpdateExpression: 'set #environnements.#tasks = list_append(if_not_exists(#environnements.#tasks, :empty_list), :newTask)',
ExpressionAttributeNames: {
'#environnements' : 'environnements',
'#tasks' : 'tasks',
},
ExpressionAttributeValues: {
':newTask': [newTask],
':empty_list': []
}
}, function(error, stdout) {
if(error){
console.log("error==", error)
else {
console.log("Nice thank you !!")
}
});

I would suggest to keep the tasks attribute as SET ('SS') which will simplify to NOT add the duplicate values. Otherwise, it would be difficult to fulfil the scenario.
Also, you may the index of the environments attribute list to form the update expression correctly. There is no options in the dynamodb api to workout the index automatically.
The below code should work if you define the tasks attribute as SET.
Insert item code:-
var params = {
TableName : table,
Item : {
"idProject" : "15azeze-55ze",
"dateCreationProjectString" : Date(),
"environnements" : [{
"idEnvironnement" : "11-aa",
"name" : "Example Environments",
"tasks" : docClient.createSet(["1"])
}]
}
};
console.log("Adding a new item...");
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));
}
});
Sample update item working code:-
The ADD operation will ensure that it doesn't add duplicates to the SET
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "projects",
Key: {
"idProject" : "15azeze-55ze"
},
UpdateExpression: 'ADD environnements['+0+'].tasks :tasksVal',
ExpressionAttributeValues: {
":tasksVal": docClient.createSet(["2"])
},
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

How to use where in condition in dynamodb filterexpression

I am learning dynamodb and I am trying how to fetch items with status 0 and 1 but when i write the below query, it is throwing error "Error ValidationException: Invalid FilterExpression: Syntax error; token: ":user_status_val", near: "IN :user_status_val". Could any one please help in fixing this issue.
const checkUserExists = (req) => {
return new Promise((resolve,reject) =>{
var searchParams = {};
if(req.body.email != ""){
searchParams = {
FilterExpression : "#email = :e AND #user_status IN :user_status_val",
ExpressionAttributeNames: {
"#user_status": "status",
"#email" : "email",
},
ExpressionAttributeValues: {
':user_status_val' : req.body.status,
':e' : req.body.email,
},
}
}
var params = {
Select: "COUNT",
TableName: 'register'
};
var finalParams = {...searchParams, ...params}
DynamoDB.scan(finalParams, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log(data);
//res.send(data);
return resolve(data);
}
});
});
}

Getting AWS Dynamodb query result as internel server error code : 502

This is my table "odo":
I want to retrive data where deviceId == 'A233' Between two timestamps. I run query inside Lamda Function and testing with API Gateway.
This is query I ran to get the result:
var params = {
TableName: "odo",
KeyConditionExpression: "#deviceId = :deviceIdVal AND #timestamp BETWEEN :sdate AND :edate",
ExpressionAttributeNames: {
"#deviceId": "deviceId",
"#timestamp": "timestamp"
},
ExpressionAttributeValues: {
":deviceIdVal": 'A233',
":sdate": 1110601808,
":edate": 1522902606
}
};
But I get a error as "Internal Server Error" and Error Code : 502
Why this query won't work? What am I missing?
When I ran another query using id field,it work.
module.exports.handler = function (event, context, callback) {
console.log(event);
let _response = "";
let invalid_path_err = {
"Error": "Invalid path request " + event.resource + ', ' +
event.httpMethod
};
if(event.resource === '/odos' && event.httpMethod === "GET"){
var params = {
TableName: "odo",
KeyConditionExpression: "#id = :id",
ExpressionAttributeNames: {
"#id": "id"
},
ExpressionAttributeValues: {
":id": 7
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.",data);
_response = buildOutput(200, data);
return callback(null, _response);
}
});
}
else {
_response = buildOutput(500, {"error 500" : "invalid_path_err"});
return callback(_response, null);
}
};
/* Utility function to build HTTP response for the microservices output */
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};
This is the success result in test method execution in API Gateway:
The problem is that your query is trying to use a table partition key of deviceid and a range key of timestamp. In fact you have a parition key called id and no range key.
You can only use KeyConditionExpression on attributes that are a key, which in your case is the attribute id.
To do your 'query' you need to change KeyConditionExpression to FilterExpression and change query to scan
EDIT:
module.exports.handler = function (event, context, callback) {
console.log(event);
let _response = "";
let invalid_path_err = {
"Error": "Invalid path request " + event.resource + ', ' +
event.httpMethod
};
if(event.resource === '/odos' && event.httpMethod === "GET"){
var params = {
TableName: "odo",
FilterExpression: "#deviceId = :deviceIdVal AND #timestamp BETWEEN :sdate AND :edate",
ExpressionAttributeNames: {
"#deviceId": "deviceId",
"#timestamp": "timestamp"
},
ExpressionAttributeValues: {
":deviceIdVal": 'A233',
":sdate": 1110601808,
":edate": 1522902606
}
};
docClient.scan(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.",data);
_response = buildOutput(200, data);
return callback(null, _response);
}
});
}
else {
_response = buildOutput(500, {"error 500" : "invalid_path_err"});
return callback(_response, null);
}
};
/* Utility function to build HTTP response for the microservices output */
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};

Add form data to DynamoDB

I am new to AWS DynamoDB, I would like add form data which randomly entered by a user to DynamoDB without using JSON format.
Here is my sample code which is used to add data from a json file,
var AWS = require("aws-sdk");
var fs = require('fs');
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000",
});
allMovies.forEach(function(movie) {
var params = {
TableName: "Movies1",
Item: {enter code here
"year": movie.year,
"title": movie.title,
"info": movie.info
}
};
docClient.put(params, function(err, data) {
if (err) {
console.error("Unable to add movie", movie.title, ". Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("PutItem succeeded:", movie.title);
}
});
});
But I want add data which is from a form. Any kind of help will be more useful.

Append to or create StringSet if it doesn't exist

So this should be simple...
I want to append a string to a StringSet in a DynamoDB if it exists, or create the StringSet property if it doesn't and set the value. If we could initialize the StringSet on creation with an empty array, it would be fine, but alas we can not.
Here's what I have so far:
const companiesTable = 'companies';
dynamodb.updateItem({
TableName: companiesTable,
Key: {
id: {
S: company.id
}
},
UpdateExpression: 'ADD socialAccounts = list_append(socialAccount, :socialAccountId)',
ExpressionAttributeValues: {
':socialAccountId': {
'S': [socialAccountId]
}
},
ReturnValues: "ALL_NEW"
}, function(err, companyData) {
if (err) return cb({ error: true, message: err });
const response = {
error: false,
message: 'Social account created',
socialAccountData
};
cb(response);
});
I've also tried...
UpdateExpression: 'SET socialAccounts = list_append(socialAccounts, :socialAccountId)',
ExpressionAttributeValues: {
':socialAccountId': {
S: socialAccountId
}
},
and...
UpdateExpression: 'ADD socialAccounts = :socialAccountId',
ExpressionAttributeValues: {
':socialAccountId': {
S: socialAccountId
}
},
and...
UpdateExpression: 'SET socialAccounts = [:socialAccountId]',
ExpressionAttributeValues: {
':socialAccountId': socialAccountId
},
and...
UpdateExpression: 'ADD socialAccounts = :socialAccountId',
ExpressionAttributeValues: {
':socialAccountId': socialAccountId
},
Among about every other variation of the above. Am I dumb? Is DynamoDB not capable of simple write/updates to an array type field? Do I REALLY have to lookup the item first to see if it has that field before I try to either add or set that field, because I can't instantiate that field with an empty array?
The ADD action handles the create/update logic, but only supports numbers and sets. You are trying to add a string type 'S'. You need to wrap this string in an array and pass it as a string set 'SS'. You also don't need the equals sign.
Your UpdateExpression and ExpressionAttributeValues should look like this:
UpdateExpression: 'ADD socialAccounts :socialAccountId',
ExpressionAttributeValues: {
':socialAccountId': {
'SS': [socialAccountId]
}
},
More information about updating items can be found here

AWS DynamoDB Attempting to ADD to a Set - Incorrect Operand

I am creating an API using Nodejs and DynamoDB as a back end. I am attempting to update an item to add to a set of "friends". When I update the user, I get the error, "Invalid UpdateExpression: Incorrect operand type for operator or function; operator: ADD, operand type: MAP". My understanding is that when adding to a set that does not exist, the set will be created. If it already exists, the new value should be added to the set. I do not understand why the set I attempt to ADD is being read as a map.
How users are created:
var params = {
TableName: "users",
Item:{
"id": Number(id),
"name": name,
"password": password
}
};
documentClient.put(params, function(err, data) {
if(err)
res.json(500, err);
else
res.json(200, data);
});
How friends are added:
var params = {
TableName: "users",
Key: {
"id": id
},
UpdateExpression: "ADD friends :friendId",
ExpressionAttributeValues: {
":friendId": { "NS": [friendId] }
},
ReturnValues: "UPDATED_NEW"
};
documentClient.update(params, function(err, data) {
if(err)
res.json(500, err);
else
res.json(200, data);
});
This question has an answer here
https://stackoverflow.com/a/38960676/4975772
Here's the relevant code formatted to fit your question
let AWS = require('aws-sdk');
let docClient = new AWS.DynamoDB.DocumentClient();
...
var params = {
TableName : 'users',
Key: {'id': id},
UpdateExpression : 'ADD #friends :friendId',
ExpressionAttributeNames : {
'#friends' : 'friends'
},
ExpressionAttributeValues : {
':friendId' : docClient.createSet([friendId])
},
ReturnValues: 'UPDATED_NEW'
};
docClient.update(params, callback);
If the set doesn't exist, then that code will create it for you. You can also run that code with a different set to update the set's elements. Super convenient.
Here is the working code. You don't need ADD here. Just use "set friends = :friendId" as friends attribute is not already present in the table (i.e. before the update you have only id, name and password in the table). The friend attribute is being added newly as part of the update.
var docClient = new AWS.DynamoDB.DocumentClient();
var table = "users";
var userid = 1;
var friendId = [123];
var params = {
TableName : table,
Key: {
"id" : userid
},
"UpdateExpression": "set friends = :friendId",
"ExpressionAttributeValues": {
":friendId": {"NS": friendId}
},
"ReturnValues" : "UPDATED_NEW"
};