I am trying to use a Lambda script to find the index of an object in a list. As an example, I would like to pass in "userid": "041c9004" and "author": "J.K Rowling" and return index=1 from the books list. If the object does not exist within the books list, return index=-1. We can assume that there will be no duplicate entries.
The structure of the DynamoDB table looks like this. Userid is the primary key.
{
"books": [
{
"author": "J.R.R. Tolkien",
"title": "Lord of the Rings"
},
{
"author": "J.K Rowling",
"title": "Harry Potter"
},
{
"author": "George RR Martin",
"title": "A Song of Ice and Fire"
}
],
"isactive": true,
"ispublic": true,
"lastupdated": 1597690265,
"userid": "041c9004"
}
Here is what I have written of the Lambda function. It is returning index=-1.
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = function(event, context, callback){
var params = {
TableName: 'Users',
Key: {
userid: event.userid
}
};
docClient.get(params, function(err, data){
if(err) {
callback(err,null);
} else {
callback(null, data);
//trying to populate this variable with the correct index
var indexOfAuthor = data.Item.books.indexOf(event.author);
console.log('The index of the author is ' + indexOfAuthor);
}
});
};
Assuming event.author is just the author name, you could try:
data.Item.books.findIndex(i => i.author === event.author)
Related
Trying to be able to filter on embedded object that looks like:
"posts": [
{
"id": "10e85cf7-acd2-417b-a5dc-1dfb6de606bf",
"references": [
{
"type": "URL",
"title": "How to get dynamodb to only return certain columns",
},
{
"type": "HASHTAG",
"title": "#dynamodb",
},
]
},
...
]
I am trying to return all posts that have reference of type "HASHTAG" and VALUE "#dynamodb". I have tried this but it always returns null (running in node.js):
const params = {
TableName: "tableName",
ScanIndexForward: false,
FilterExpression: "#references.#type = :referenceValue",
ExpressionAttributeNames: {
"#references": "references",
"#type": "HASHTAG"
},
ExpressionAttributeValues: {
":referenceValue": "#dynamoDB"
}
}
const response = await docClient.scan(params).promise();
console.log(response);
And only returns (successfully) an empty array.
Use the contains function to filter on items in a list. In your case, return posts that have an item like :map at the path indicated by #references.
FilterExpression: 'contains(#references, :map)',
ExpressionAttributeNames: { '#references': 'references' },
ExpressionAttributeValues: {
':map': {
type: 'HASHTAG',
title: '#dynamodb',
},
},
I'm trying to write a Lambda function to remove an object from a list in DynamoDB. In this case I am passing in "author": "J.K. Rowling", "title": "Harry Potter", and "userid": "041c9004" as parameters. I want to delete the matching object from the books list. What is the correct syntax for the UpdateExpression statement? There may be some other errors within params{} as well.
The DynamoDB table looks like this. userid is the primary key:
{
"books": [
{
"author": "J.R.R. Tolkien",
"title": "Lord of the Rings"
},
{
"author": "J.K Rowling",
"title": "Harry Potter"
},
{
"author": "George RR Martin",
"title": "A Song of Ice and Fire"
}
],
"isactive": true,
"ispublic": true,
"lastupdated": 1597690265,
"userid": "041c9004"
}
Here is the Lambda function:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = function(event, context, callback){
let params = {
ExpressionAttributeValues: {
":attrValue": [{
"author": event.author,
"title": event.title
}]
},
ExpressionAttributeNames : {
"#books" : "books"
},
Key: {
userid: event.userid
},
TableName: 'Users',
UpdateExpression: "REMOVE #books[:attrValue]", //this is incorrect
ReturnValues:"ALL_NEW",
};
docClient.update(params, function(err,data){
if(err) {
callback(err, null)
}else{
callback(null, data)
}
});
}
This is a great question!
Unfortunately, the UpdateExpression will only allow you to REMOVE from the list if you specify an index (docs here).
You'll need to read the item from the DB, find the indexes you want to remove, and REMOVE that specific index.
In case anyone is wondering, here is the full solution:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = function(event, context, callback){
var params = {
TableName: 'Users',
Key: {
userid: event.userid
}
};
docClient.get(params, function(err, data){
if(err) {
callback(err,null);
} else {
var indexOfAuthor = data.Item.books.findIndex(i => i.author === event.author);
console.log('The index of the author is ' + indexOfAuthor);
var updateExpressionString = "REMOVE #books[" + indexOfAuthor + "]"
let paramsdelete = {
ExpressionAttributeNames : {
"#books" : "books"
},
Key: {
userid: event.userid
},
TableName: 'Users',
UpdateExpression: updateExpressionString,
ReturnValues:"ALL_NEW",
};
docClient.update(paramsdelete, function(err,data){
if(err) {
callback(err, null);
}else{
callback(null, data);
}
});
}
});
};
I want to make pagination of "car_types" using aws dynamo db and node js. I don't want to use js, Can we make it using dynamo db ? I want total items, total page, page size, current page and data in response.
{
"uid": "222-3333",
"car_types": [
{
"description": "fsdf",
"title": "sdfsd"
},
{
"description": "fdfdfdf",
"title": "dfdfd"
},
{
"description": "dasda",
"title": "asdas"
},
{
"description": "dasd",
"title": "asdas"
},
{
"description": "dasdasd",
"title": "asdas"
}
]
}
Aws Dynamo DB and Node js Code, Which I used to get result.
export function get_car_types_list(){
var params = {
TableName : "cms_cars",
KeyConditionExpression: "#uid = :uid",
ExpressionAttributeNames:{
"#uid": "uid"
},
ExpressionAttributeValues: {
":uid": "222-3333"
}
};
return docClient.query(params).promise()
.then(function(data) {
console.log(data);
return data;
}).catch( (err) => {
console.log('got Error', err);
});
}
I want Result using dynamo db query:
{
"totalItem":5,
"totalPage":1,
"pageSize":"1",
"currentPage":"1",
"car_types": [
{
"description": "fsdf",
"title": "sdfsd"
},
{
"description": "fdfdfdf",
"title": "dfdfd"
},
{
"description": "dasda",
"title": "asdas"
},
{
"description": "dasd",
"title": "asdas"
},
{
"description": "dasdasd",
"title": "asdas"
}
]
}
DynamoDb will return 1 mb data when scan/query is executed, also LastEvaluatedKey is added to result if there are any remaining data. If you pass ExclusiveStartKey: LastEvaluatedKey you can scan/query with pagination. I added some tweaks to your approach, it may help you.
Edit: You can limit the result by passing Limit: Number to your params. This will allow you to limit the returning item count and you can get more with LastEvaluatedKey.
export function get_car_types_list(LastEvaluatedKey){
var params = {
TableName : "cms_cars",
KeyConditionExpression: "#uid = :uid",
ExpressionAttributeNames:{
"#uid": "uid"
},
ExpressionAttributeValues: {
":uid": "222-3333"
},
Limit: 5,
};
if (LastEvaluatedKey) {
params.ExclusiveStartKey = LastEvaluatedKey;
}
return docClient.query(params).promise()
.then(function(data) {
console.log(data);
return data;
}).catch( (err) => {
console.log('got Error', err);
});
}
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);
}
});
I'm trying to set up a small api from AWS Lambda to DynamoDB and I am having trouble figuring out if and how I can write an array of objects into a key.
I have an object like
{
"teamName": "Team Awesome",
"members": [
{
"email": "person-1#example.com",
"name": "Bob"
},
{
"email": "person-2#example.com",
"name": "Alice"
}
]
}
The members array is giving me issues, in the docs it looks like it can be done considering the list types, but there is just no example how HOW to do it, and I am running out of ways to try it.
So is it possible to write something in this format at all and how do you in that case do it?
Example code - what do I put at ???
var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB();
exports.handler = function(event, context) {
var tableName = "GDCCompetition";
var datetime = new Date().getTime().toString();
DynamoDB.putItem({
"TableName": tableName,
"Item": {
"datetime": {
"N": datetime
},
"teamName": {
"S": event.teamName
},
"members": ???
}
});
}
The documentation is not really obvious, but there is a thing called DocClient, you can pass a usual JS object to it and it will do all the parsing and transformation into AWS object (with all the types). You can use it like this:
var AWS = require("aws-sdk");
var DynamoDB = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: "MyTable",
Item: {
"teamName": "Team Awesome",
"members": [
{
"email": "person-1#example.com",
"name": "Bob"
},
{
"email": "person-2#example.com",
"name": "Alice"
}
]
}
};
DynamoDB.put(params, function (err) {
if (err) {
return throw err;
}
//this is put
});
You could convert the object to DynamoDb record first
const AWS = require('aws-sdk');
var tableName = "GDCCompetition";
var datetime = new Date().getTime().toString();
const members = [
{
"email": "person-1#example.com",
"name": "Bob"
},
{
"email": "person-2#example.com",
"name": "Alice"
}
];
const marshalled = AWS.DynamoDB.Converter.marshall({ members });
const params = {
"TableName": tableName,
"Item": {
"datetime": {
"N": datetime
},
"teamName": {
"S": event.teamName
},
"members": marshalled.members,
},
}
AWS.DynamoDB.putItem(params, function (err) {
if (err) {
return throw err;
}
});