How to scan in dynamoDB based on the values in an array? - node.js

here is my code where i have a list of values in an array. I need to fetch all the projects from project table which matches the id's in the array.
var arr=[];
for(var index in data.Items){
if(data.Items[index].hasOwnProperty('projectId'))
arr.push(data.Items[index].projectId);
};
var params = {
TableName: 'projects',
FilterExpression: 'id IN (:id)',
ExpressionAttributeValues: {
':id': arr
}
};
dynamodbclient.scan(params, function (err, docs) {
if (err) {
console.log("Error", err);
} else {
console.log("Success");
callback(err, docs.Items);
}
});
However i am not getting the proper results.

Option 1 - Static :-
If you know all the values its count upfront, please construct the FilterExpression as mentioned below:-
var params = {
TableName : "projects",
FilterExpression : "id IN (:id1, :id2)",
ExpressionAttributeValues : {
":id1" : "id val 1",
":id2" : "id val 2"
}
};
Option 2 - Dynamic:-
var titleValues = ["The Big New Movie 2012", "The Big New Movie"];
var titleObject = {};
var index = 0;
titleValues.forEach(function(value) {
index++;
var titleKey = ":titlevalue"+index;
titleObject[titleKey.toString()] = value;
});
var params = {
TableName : "Movies",
FilterExpression : "title IN ("+Object.keys(titleObject).toString()+ ")",
ExpressionAttributeValues : titleObject
};
docClient.scan(params, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(
err, null, 2));
} else {
// print all the movies
console.log("Scan succeeded.");
data.Items.forEach(function(movie) {
console.log("Item :", JSON.stringify(movie));
});
// continue scanning if we have more movies
if (typeof data.LastEvaluatedKey != "undefined") {
console.log("Scanning for more...");
params.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(params, onScan);
}
}
}

Related

unable to get all items using query DynamoDB

How to scan all items from AWS dynamodb using node.js. I am posting my code here.
//Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
var unmarshalItem = require('dynamodb-marshaler').unmarshalItem;
// Set the region
AWS.config.update({region: 'us-east-1'});
// Create DynamoDB service object
var b = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = (event, context, callback) => {
var params = {
TableName: 'IoTdata2',
FilterExpression: "#deviceid = :unitID and #devicetimestamp BETWEEN :ftimestamp and :ttimestamp",
ExpressionAttributeNames: {
"#deviceid": "id",
"#devicetimestamp": "timestamp"
},
ExpressionAttributeValues: {
':unitID': {S: 'arena-MXHGMYzBBP5F6jztnLUdCL' },
':ftimestamp' : {S: '1584022680000' },
':ttimestamp' : {S: '1584023280000' }
},
};
b.scan(params, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Scan succeeded.");
var items = data.Items.map(function(val){
return unmarshalItem(val);
})
// continue scanning if we have more items
if (typeof data.LastEvaluatedKey != "undefined") {
console.log("Scanning for more...");
params.ExclusiveStartKey = data.LastEvaluatedKey;
b.scan(params, onScan);
}
}
callback(null, items);
}
};
I have followed the link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.04.html
I am getting time out here after a while. I have checked this link too
How to fetch/scan all items from `AWS dynamodb` using node.js
I am unable to return data properly i guess, Any suggestions ? Thanks
This worked for me by following Hank solution from here: How to fetch/scan all items from `AWS dynamodb` using node.js
exports.handler = async (event, context, callback) => {
let params = {
ExpressionAttributeNames: {
"#deviceid": "id",
"#devicetimestamp": "timestamp"
},
ExpressionAttributeValues: {
':unitID': {S: event.deviceid },
':ftimestamp' : {S: event.fromtime },
':ttimestamp' : {S: event.totime }
},
KeyConditionExpression: '#deviceid = :unitID and #devicetimestamp BETWEEN :ftimestamp and :ttimestamp',
TableName: 'IoTdata2'
};
let scanResults = [];
let items;
do {
items = await b.query(params).promise();
items.Items.map((item) => scanResults.push(unmarshalItem(item)));
params.ExclusiveStartKey = items.LastEvaluatedKey;
} while (typeof items.LastEvaluatedKey != "undefined");
var len = scanResults.length;
console.log(len);
callback(null, scanResults);
};

Scanning DynamoDB table not showing results from the column specified in ProjectionExpression

i'm trying to scan the DynamoDB tale so that i fetch only filtered items.
myTable has 3 columns:L timestamp (String, PK), colors (String), userId (String)
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
"TableName": "myTable",
"ProjectionExpression": "colors, userId",
"ExpressionAttributeValues": {":val": userId},
"FilterExpression": "userId = :val"
};
console.log("Scanning table.");
docClient.scan((params), function(err,data){
if (err) console.log(err, err.stack);
else console.log(data); //success response
});
2018-05-22T08:04:21.395Z baac6d92-5d96-11e8-ae78-bd04c275acf5 Scanning table.
2018-05-22T08:04:21.672Z baac6d92-5d96-11e8-ae78-bd04c275acf5 { Items: [ { userId: 'amzn1.ask.account.XYZ' } ], Count: 1, ScannedCount: 2 }
As a result i'm only getting value(s) from userId column. The column 'colors' is completely ignored.
What am i doing wrong?
Setting ProjectionExpression attributes in ExpressionAttributeNames. Check out the following snippet
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
ExpressionAttributeNames: {
"#colors": "colors",
"#userId": "userId"
},
ExpressionAttributeValues: {
":val": userId
},
FilterExpression: "userId = :val",
ProjectionExpression: "#colors, #userId",
TableName: "myTable"
};
console.log("Scanning table.");
docClient.scan(params, function(err, data) {
if (err) console.log(err, err.stack);
else console.log(data); //success response
});
Note the # and : must be present on ExpressionAttributeNames and ExpressionAttributeValues, respectively.

Confused on querying DynamoDB

I've the below data in my DynamoDB.
and I'm trying to achieve the below result.
scan through the table and get the rows where the management is NULL and Location is Midwest.
I initially tried the below query to match the Null.
var scanningParameters = {
TableName: 'LOB',
FilterExpression: "#mgmt contains NULL",
ExpressionAttributeNames: {
"#mgmt": "Management",
}
};
docClient.scan(scanningParameters, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
// print all the movies
console.log("Scan succeeded.");
data.Items.forEach(function (data) {
console.log(
data.lineofbusiness + " name : ",
data.name);
});
if (typeof data.LastEvaluatedKey != "undefined") {
console.log("Scanning for more...");
scanningParameters.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(scanningParameters, onScan);
}
}
}
I get the exception as
{
"message": "Invalid FilterExpression: Syntax error; token: \"contains\", near: \"#mgmtcontains NULL\"",
"code": "ValidationException",
"time": "2017-05-03T13:21:11.611Z",
"requestId": "0T0GU59HRJ24P96D42H9QNC97RVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 13.73953651636839
}
please let me know where am I going wrong and how can I fix this.
Here is the scan item for "NULL" value (i.e. String attribute having NULL as data).
I assume that Management attribute is of String data type containing the string value "NULL".
Code:-
var AWS = require("aws-sdk");
var creds = new AWS.Credentials('akid', 'secret', 'session');
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000",
credentials : creds
});
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "lob",
FilterExpression: "#mgmt = :mgmtVal",
ExpressionAttributeNames: {
"#mgmt": "Management",
},
ExpressionAttributeValues : {
":mgmtVal" : "NULL"
}
};
docClient.scan(params, onScan);
var count = 0;
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Scan succeeded.");
data.Items.forEach(function(itemData) {
console.log("Item :", ++count,JSON.stringify(itemData));
});
if (typeof data.LastEvaluatedKey != "undefined") {
params.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(params, onScan);
}
}
}

access values after authentication in node js

I've a program that does the below.
Look into a DynamoDB table.
Get the data from the table.
Save the variables in session
After the process, print the values in console.
My code is as below.
intentHandlers['GetMYBusinessInfo'] = function (request, session, response, slots) {
console.log('entered ext bloxk');
if (!session.attributes.userName) {
console.log('eneterd the user entered the block');
var userName = 'jim';
isUserRegistered(userName.toLowerCase(), function (res, err) {
if (err) {
response.fail(err);
console.log(err);
}
else if (!res) {
response.shouldEndSession = true;
}
else {
console.log(res);
var countRes = JSON.stringify(res.Count);
var unpUserRegion = JSON.stringify(res.Items[0].Region);
var unpUserCity = JSON.stringify(res.Items[0].State);
var userRegion = JSON.parse(unpUserRegion);
var userCity = JSON.parse(unpUserCity);
session.attributes.city = userCity;
session.attributes.region = userRegion;
console.log("parsed " + countRes + "\t region is " + userRegion);
session.attributes.userName = true;
}
});
}
console.log(`session values after authentication are user city is ${session.attributes.city}`);
}
The method to check if the value is in DynamoDb or not.
function isUserRegistered(userName, callback) {
var params = {
TableName: "usersTable",
FilterExpression: "#nme = :nme",
ExpressionAttributeNames: {
"#nme": "Name",
},
ExpressionAttributeValues: {
":nme": userName
}
};
var count = 0;
docClient.scan(params, function (err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
callback(false, err);
} else {
console.log("Scan succeeded." + data.Items.length);
if (data.Items.length === 0) {
callback(false);
}
else {
data.Items.forEach(function (itemData) {
console.log("Item :", ++count, JSON.stringify(itemData));
});
callback(data);
}
}
});
}
when I run this, the output that I get is:
session values after authentication are user city is undefined
Scan succeeded.1
Item : 1
{
"ID": "3",
"State": "wisconsin",
"Region": "midwest",
"Name": "jim"
}
{ Items: [ { ID: '3', State: 'wisconsin', Region: 'midwest', Name: 'jim' } ],
Count: 1,
ScannedCount: 1 }
parsed 1 region is midwest
Here I know that Node js being Non-blockable process, the above output is correct, but I want to get the value of city printed in session values after authentication are user city is {HereTheCityComes} instead of session values after authentication are user city is undefined.
I'm sure that placing the console.log(session values after authentication are user city is ${session.attributes.city}); in the last else block(place where the data is returned).
But I need this type of functionality(Get data as shown in my current scenario), as there is some other things to be done after checking if the user is available in database.
please let me know where am I going wrong and how can I fix this.
You can't synchronously expect async result.
What you can do here is solve your problem with promises.
Here is a solution:
intentHandlers['GetMYBusinessInfo'] = function(request, session, response, slots) {
console.log('entered ext bloxk');
var userPromise = Promise.resolve();
if (!session.attributes.userName) {
console.log('eneterd the user entered the block');
var userName = 'jim';
userPromise = new Promise(function (resolve, reject) {
isUserRegistered(userName.toLowerCase(), function (res, err) {
if (err) {
response.fail(err);
reject(err);
}
var countRes = JSON.stringify(res.Count);
var unpUserRegion = JSON.stringify(res.Items[0].Region);
var unpUserCity = JSON.stringify(res.Items[0].State);
var userRegion = JSON.parse(unpUserRegion);
var userCity = JSON.parse(unpUserCity);
session.attributes.city = userCity;
session.attributes.region = userRegion;
console.log("parsed " + countRes + "\t region is " + userRegion);
resolve(res);
});
});
}
userPromise.then(function () {
console.log(`session values after authentication are user city is ${session.attributes.city}`);
});
}
If you are not using ES6, then just install bluebird and use var Promise = require('bluebird')

Node.js: How to use putitem to add integer to list w/DynamoDB

I am working on a Node.js server for a game I have created. The server acts as an api to retrieve user account info including their personal high scores. I have an individual item for each account which contains their username and a list of their scores for the game. I can't seem to find any example code for inserting values into a list in DynamoDB and I was hoping someone could help me with this. I'm not finding documentation for this specific action. I have simply been trying to use the putitem function that I know works for inserting strings and other data types, but I have had no luck with inserting into a list data type. My most recent attempt at this looks like the following:
var params = {
TableName : "userscores",
Item:{
"username" : {"S": username},
"scores" : {"L": {"S": score}}
}
}
dynamodb.putItem(params, function(err, data) {
if(err)
console.log(err);
else
console.log(JSON.stringify(data));
});
The error looks like this:
{ [InvalidParameterType: Expected params.Item['scores'].L to be an Array]
message: 'Expected params.Item[\'scores\'].L to be an Array',
code: 'InvalidParameterType'
I understand why this block doesn't work, but I don't understand how to do this.
Any help would be greatly appreciated!
let data = {
"username" : "name",
"scores" : ["val1", "val2"]
};
let attrs=toAttributes(data);
dynamodb.putItem({
TableName: "underscored",
Item: attrs,
// not needed for you example, just some extra info
ConditionExpression: 'attribute_not_exists(#id)',
ExpressionAttributeNames: {'#id': '<aUniqueColumnNameIfYouUse>'}
});
toAttributes = obj => {
return Object.keys(obj).reduce((prevResult, sKey)=> {
prevResult[sKey] = getAttributeFromValue(obj[sKey]);
return prevResult
}, {});
};
getAttributeFromValue = value => {
var type = typeof value;
if (type === "string") {
return { S: value };
} else if (type === "number") {
return { N: value.toString() };
} else if (type === "boolean") {
return { BOOL: value };
} else if (value.constructor === Array) {
var array = value.map(function(element) {
return getAttributeFromValue(element);
});
return { L: array }
} else if (type === "object" && value !== null) {
var map = {};
for (var key in value) {
map[key] = getAttributeFromValue(value[key]);
}
return { M: map }
} else {
return null
}
}
You can change the scores value like this:-
If scores is defined as String variable:-
var scores = "s1";
var params = {
TableName : "userscores",
Item:{
"username" : {"S": username},
"scores" : [scores]
}
}
If scores is defined as array:-
var scores = ["s1"];
var params = {
TableName : "userscores",
Item:{
"username" : {"S": username},
"scores" : scores
}
}

Resources