How to scan AWS DynamoDB with wild card in Nodejs - node.js

I use aws-sdk in nodejs, And I should scan database with wildcard.
I tried this with aws developer guide:
var params = {
TableName: RecipeTable,
FilterExpression: "#recipe = :recipe",
ExpressionAttributeNames:{
"#recipe": "recipe",
},
ExpressionAttributeValues: {
":recipe": request.params.recipe,
}
};
I can't reach the answer.
Can someone help me?
Thanks.

I found the answer: Using contains keyword.
app.get('/recipe/:recipe', (request, response) => {
var params = {
TableName: RecipeTable,
FilterExpression: "contains(#recipe, :recipe)", // Here!
ExpressionAttributeNames:{
"#recipe": "ingredients"
},
ExpressionAttributeValues: {
":recipe": request.params.recipe
}
};
result = [];
docClient.scan(params, onScan);
function onScan(err, data) {
if (!err) {
data.Items.forEach((itemdata) => {
result.push(itemdata);
});
if(typeof data.LastEvaluatedKey != "undefined") {
params.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(params, onScan);
} else {
response.send(JSON.stringify({"result" : result}));
}
}
}
})
I have referenced this document.
Thanks.

Related

Aws Lambda to read the user input dynamically and return the data from Dynamo table

Lambda provides the expected result only when I pass the value manually (Id = '011010').
In the step function the value "ID" value will be random based on the logic from previous step, since the Id value is not static how to handle this scenario "ExpressionAttributeValues"
I tried all the below syntax but no luck..
ExpressionAttributeValues: { ':value': $.External.Id}
ExpressionAttributeValues: { ':value': External.Id.$}
ExpressionAttributeValues: { ':value': $.Id}
ExpressionAttributeValues: { ':value': Id.$}
ExpressionAttributeValues: { ':value': event.Id}
Lambda-Code
'use strict'
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: 'temptable',
IndexName: 'Id-CurrentStatus-index',
KeyConditionExpression: '#Id= :value',
ExpressionAttributeNames: { '#Id': 'Id'},
ExpressionAttributeValues: { ':value': 'M1' }
};
async function queryItems(){
try {
const data = await docClient.query(params).promise()
return data
} catch (err) {
return err
}
}
exports.handler = async (event, context) => {
try {
const data = await queryItems()
return { body: JSON.stringify(data) }
} catch (err) {
return { error: err }
}
}
I can read it from the
console.log("Memberid :" + JSON.stringify(event.Id, null, 2))
but how to pass the same value in the
ExpressionAttributeValues: { ':value': 'M1' }
I tried the below syntax. nothing works
ExpressionAttributeValues: { ':value': JSON.stringify(event.Id, null, 2) }
ExpressionAttributeValues: { ':value': event.Id}
ExpressionAttributeValues: { ':value': event.Id}
ExpressionAttributeValues: { ':value': Id}
I got the required code after checking multiple thread.
AWS Lambda function to scan/query DynamoDB table using array values as FilterExpression
'use strict'
var AWS = require('aws-sdk');
var mydocumentClient = new AWS.DynamoDB.DocumentClient();
exports.handler = function (event, context, callback) {
var params = {
TableName: 'temptable',
KeyConditionExpression : 'Id= :Id',
FilterExpression : 'Id in (:Id)',
ExpressionAttributeValues: {
":Id": event.Id
}
};
mydocumentClient.scan(params, function (err, data){
if (err) {
callback(err, null);
}else{
callback(null, data);
}
})
}

Data Item not getting inserted in DynamoDB Table from AWS Lambda Trigger

I have this Lambda code setup in JS for inserting a row in DynamoDB but the code seems to have some issue and doesn't trigger.Unable to figure out the issue as cloud watch also does captures anything. The API Gateway triggers the Lambda will inserts a row in DynamoDB. Tried debugging with console and logs also but unable to figure out the actual issue that is causing the code to break.
exports.handler = async (event) => {
console.log(event);
var eventBody = JSON.parse(event.body);
var eventType = eventBody.event_type;
var content = eventBody.content;
if (content.subscription) {
var subscription = content.subscription;
switch (eventType) {
case "subscription_created":
// Add new entry to License table
console.log('subscription created event');
var customer = content.customer;
var findUserScan = {
ExpressionAttributeValues: {
':email': { S: customer.email },
},
FilterExpression: 'email = :email',
TableName: _dynamodb_userprofile_table
};
try {
await dynamodb.scan(findUserScan, function (err, data) {
if (err) {
console.log("Error", err);
} else {
var userProfileAWS;
data.Items.forEach(function (userProfile, index, array) {
userProfileAWS = AWS.DynamoDB.Converter.unmarshall(userProfile);
});
var companyName;
if (userProfileAWS) {
companyName = userProfileAWS.organization;
}
try {
var licenseEntry = {
"subscriptionID": {
S: subscription.id
},
"companyName": {
S: companyName || ""
},
"customerEmail": {
S: customer.email
},
};
await dynamodb.putItem({
"TableName": _dynamodb_license_table,
"Item": licenseEntry
}).promise()
} catch (error) {
console.log(error)
throw new Error(`Error in dynamoDB: ${JSON.stringify(error)}`);
}
}
}).promise();
} catch (error) {
throw new Error(`Error in dynamoDB: ${JSON.stringify(error)}`);
}
break;

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

DynamoDB Scan FilterExpression returning empty result

I am trying to filter the data returned by a dynamodb scan operation using nodejs aws sdk but the data returned has 0 items.
Response : {"Items":[],"Count":0,"ScannedCount":15}
I have tried with both FilterExpression and ScanFilter but getting the same result.
FilterExpression:
var params = {
TableName: tableName,
FilterExpression: 'active = :active',
ExpressionAttributeValues: {
':active': {
S: '1'
}
}
};
ScanFilter:
var params = {
TableName: tableName,
ScanFilter: {
'active': {
"AttributeValueList": [{ "S": "1" }],
"ComparisonOperator": "EQ"
}
}
};
Here is the nodejs code:
dynamodb.scan(params, onScan);
function onScan(err, data) {
if (err) {
console.error('Unable to scan the table. Error JSON:', JSON.stringify(err, null, 2));
} else {
if (typeof data.LastEvaluatedKey != 'undefined') {
params.ExclusiveStartKey = data.LastEvaluatedKey;
dynamodb.scan(params, onScan);
}
if (data && data.Items)
callback(data.Items);
else
callback(null);
}
}
I checked the same filter condition in the dynamodb console and getting the expected result.
dynamodb console screenshot
#bharathp answer did the trick for me,
in aws command line had to specify the parameter as {"S":"s1"}
aws dynamodb scan \
--table-name aws-nodejs-typescript-dev \
--filter-expression "id = :search" \
--expression-attribute-values '{":search":{"S":"s1"}}'
in node code just ":search": "s1"
const params = {
TableName: process.env.DYNAMODB_TABLE,
ExpressionAttributeValues: {
":search": "s1"
},
FilterExpression: "id = :search",
ProjectionExpression: "id",
};
dynamoDb.scan(params, (error, result) => {
This was working just fine for me on AWS CLI,
aws dynamodb scan \
--table-name myTableName \
--filter-expression "email = :a" \
--expression-attribute-values '{":a":{"S":"xxxxx#xxxxx.com"}}'
However when trying to write the same query on NodeJs/Angular5/typescript it fails:
private getDynamoEmail(email: string): Promise<ScanOutput> {
const params: any = {
TableName: this.config.database.myTableHere,
KeyConditionExpression "email = :e"
ExpressionAttributeValues: {
":email": {
S: email, // Had to remove this part to work and use
// ExpressionAttributeNames instead
},
},
FilterExpression: ":e = :email",
};
return this.docClient.scan(params).promise();
}
In order to work I had to omit the attribute type so here is the code working:
private getDynamoEmail(email: string): Promise<ScanOutput> {
// tslint:disable-next-line:no-any
const params: any = {
ExpressionAttributeNames: {"#email": "email"},
ExpressionAttributeValues: {":email": email},
FilterExpression: "#email = :email",
TableName: this.config.database.registeredLiveAccounts,
};
return this.docClient.scan(params).promise();
}
Hope helps
Daniel
It indicates that 15 items are scanned and no items found. You might find the item in your loop of:
if (typeof data.LastEvaluatedKey != 'undefined') {
params.ExclusiveStartKey = data.LastEvaluatedKey;
dynamodb.scan(params, onScan);
}
As scan operation scans all the items and filters the match.

How to update() DynamoDB

I'm working with DynamoDB for the first time and so far, not too bad. Having some understanding of Node is making this easier, but having none of noSQL, well that hurts!. My application relies on quickly searching a GROUPS list and returning members from that group.
When I add the data using the console, I am able to create a JSON document like this:
"GROUP_ID":"GroupA", "MEMBER": ["MemberA", "MemberB", "MemberC"], "STATUS": ["OWNER", "MEMBER", "INVITED"], "ADD_DATE":[1234567, 2345671, 3456712]
I am using this to create the GROUP_ID as the primary key:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region:'us-east-1'});
exports.handler = (event, context, callback) => {
var tableName = "USER_GROUPS";
var checkParams = {
TableName: tableName,
Key:{"GROUP_NAME": event.group_id}
};
var createParams = {
TableName: tableName,
Key:{"GROUP_NAME": event.group_id},
Item:{"GROUP_NAME": event.group_id, "MEMBER_NAME":[event.device_id], "MEMBER_SATUS":["OWNER"], "MEMBER_DATE" : [event.date]}
};
var checkGroupExists = new Promise((resolve, reject) => {
docClient.get(checkParams, (err, data) => {
if(err){
reject(err);
}
if(data.Item){ // exists...
console.log("found Group ID");
reject();
}
else{
console.log("Group ID not found...");
resolve();
}
});
});
checkGroupExists.then((err, data) => {
console.log("adding Group: ");
console.log(data);
docClient.put(createParams, (err, data) =>{
if(err){
console.log(err);
callback(err, null);
}else{
console.log("added device: " + createParams.Key);
callback(null, {"created":createParams.Key.GROUP_NAME});
}
});
}).catch((err) => {
if(err){
callback(err, null);
}
else{
callback(err, {"used":createParams.Key.GROUP_NAME});
}
});
};
but when I use update() I am adding to the array and end up with a type name for the arrays
["S":"MemberA", "S":"MemberB", "S":"MemberC"]
kind of thing....
This is where I have left off, quite frustrated here!
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region:'us-east-1'});
exports.handler = (event, context, callback) => {
var tableName = "USER_GROUPS";
var checkParams = {
TableName: tableName,
Key:{"GROUP_NAME": event.group_id},
Item:{"MEMBER_NAME": event.member_name}
};
var updateParams = {
TableName: tableName,
Key:{"GROUP_NAME": event.group_id},
//Item:{"MEMBER_NAME":[event.device_id], "MEMBER_STATUS":["OWNER"], "MEMBER_DATE" : [event.date]},
AttributeUpdates: {
"MEMBER_NAME": {
Action: 'ADD',
Value: event.device_id
},
"MEMBER_STATUS":{
Action : 'ADD',
Value: "ENVITED"
},
"MEMBER_DATE":{
Action: 'ADD',
Value: event.date
}
},
};
var checkGroupExists = new Promise((resolve, reject) => {
docClient.get(checkParams, (err, data) => {
console.log(data);
if(err){
reject(err);
}
if(data.Item.GROUP_NAME){ // exists...
console.log("found the group...");
resolve();
}
else{
reject();
}
});
});
checkGroupExists.then((err, data) => {
docClient.update(updateParams, (err, data) =>{
if(err){
console.log(err);
callback(err, null);
}else{
callback(null, {"updated" : updateParams.Key.GROUP_NAME});
}
});
}).catch((err) => {
if(err){
callback(err, null);
}
else{
callback(err, {"noGroup":createParams.Key.GROUP_NAME});
}
});
};
It seems I am lacking the understanding of how to process updates to include NEW item in the member array. Any assistance would be appreciated!
Use list_append() together in an UpdateExpression to append to a list column along with a ConditionExpression to prevent updates to a non-existent group:
const AWS = require('aws-sdk');
const DB = new AWS.DynamoDB.DocumentClient({region:'us-east-1'});
const UpdateExpression = 'SET ' + [
'#members = list_append(#members, :member)',
'#statuses = list_append(#statuses, :status)',
'#dates = list_append(#dates, :date)',
].join(', ')
const ConditionExpression = [
'attribute_type(#members, :L)',
'attribute_type(#statuses, :L)',
'attribute_type(#dates, :L)'
].join(' AND ')
const ExpressionAttributeNames = {
'#members': 'MEMBER_NAME',
'#statuses': 'MEMBER_STATUS',
'#dates': 'MEMBER_DATE'
}
exports.handler = (event, context, callback) => {
DB.update({
TableName: 'USER_GROUPS',
Key: { GROUP_NAME: e.group_id },
ReturnValues: 'ALL_NEW',
UpdateExpression: UpdateExpression,
ConditionExpression: ConditionExpression,
ExpressionAttributeNames: ExpressionAttributeNames,
ExpressionAttributeValues: {
':member': [e.member_name],
':status': ['ENVITED'],
':date': [e.date],
':L': 'L'
}
}, callback)
}

Resources