How to retrieve query data output from Dynamodb using Node.js - node.js

I am having difficulty to understand where is my query stored in which array variable. I know the "var params" contains all the query conditions and "db.query" will perform the actual query action. But how do I get my query result which match my search condition?
At the end, I want to pass my query output parameters (title, postedby) to html or jade for display so I need to understand where all the query data are stored at first place and how to retrieve them. Some sample code to demo this part would be greatly appreciated. Thanks
var params = {
TableName: tablename,
AttributesToGet: [
'title',
'postedBy'
],
Limit: 20,
ScanIndexForward: true,
KeyConditions: { /* required */
key : {
ComparisonOperator: 'EQ', /* required */
AttributeValueList: [
{
'N' : 'some value'
}
/* more items */
},
},
};
db.query(params, function(err, data) {
if (err) {
console.log('show error here');
} else {
console.log('Success');
}
});
I found out that all my query data is stored inside "data" from function(err, data). But i am having problem passing "data" to the following export function which later can be used as a local variable inside my webpage. Then I realized the "data" part is always empty {} inside export function even i am sure the above db.query can return the right result. So i believe somehow the export.list function is executed before the db.query happen so I am not getting any data assigned. How can I overcome this part? Thanks.
exports.list = function(req, res){
res.render('post', {title:'Title', posts : data });
console.log("Result: %j", data);
};
Note: Console.log("Result: ", data) is showing {}

I figured it out. Use the callback function due to the nature of javascript. Thanks.

Related

How to update a specific value in object of MongoDb via Post?

I have a schema with sub objects, i want to be able to update a specific key inside of it. If i update only a specific key - like in the Post example - it's empty all the other keys..
for example :
{
"_id": "32323323",
"names":{
"firstname":"John",
"lastname":"foo",
"workers":{
"position":"manager",
"address":"1 st"
}
}
}
I want to update Only "position" key via Post request , for example :
$.post({
url: 'workers/information/',
data: {
user_id: user_id,
names: {
workers: {
position: some data,
}
}
},
success: function (result) {
alert('Your information updated successfully')
}
});
Here is the update method in NodeJs server :
UserDataController.updateWorkersInformation = function (userID, workersInformation, cb) {
if (userID) {
user.findOneAndUpdate({_id: userID}, workersInformation, function (err, result) {
if (err) return cb(err);
return cb(null, result);
});
}
};
You may want to look into mongoose. It provides a more simple interface than the native client does.
https://www.npmjs.com/package/mongoose
However, as the comment mentioned, you are missing the $set operator. {$set:workersInformation}
If update is called without the $set operator, the entire document will be replaced with your update object.
http://mongodb.github.io/node-mongodb-native/2.2/tutorials/crud/

Sequelize query multiple times

I'm trying to improve the search on my website, this is how it currently looks (I use NodeJS, Sequelize and PostgreSQL):
db.food.findAll({
where: {
nameFood: {
$iLike: '%' + queryName + '%'
}
}
}).then(function (foods) {
foods.sort(compareFood);
res.json(foods);
}, function (e) {
res.status(500).send();
});
I think it is pretty self explanatory, but if something isn't clear just ask me on the comments.
Now, this search algorithm takes into consideration the WHOLE parameter, so searching for "chicken eggs" would return nothing since on my database they're saved as "eggs".
My idea for a quick improvement would be to split the query looking for spaces and then query each keyword, something like:
var keywords = queryName.split(' ');
With that I have the keywords, now how can I query a variable number of times and join the result in an array to be returned like the one in foods?
I checked the documentation and some questions in here but couldn't find anything, any help is appreciated, thank you so much.
You can use the $or property for querying anything matching "eggs" or "chicken".
Here's an example:
// split queryName by spaces
var qry = queryName.split(' ');
// convert each item into a $iLike object
// ['chicken', 'eggs'] -> [{ $iLike: '%chicken%' }, { $iLike: '%eggs%' }]
qry = qry.map(function(item) {
return {
$iLike: '%' + item + '%';
};
});
db.food.findAll({
where: {
nameFood: { $or: qry }
}
}).then(function (foods) {
foods.sort(compareFood);
res.json(foods);
}).catch(function (e) {
res.status(500).send();
});
Hope that answers your question but before you go I've also got a nice tip for you that you might find helpful.
One of them is using the .catch function for receiving any errors. Rather then using .then for both results and errors, you can leave .then to handling the results and .catch to handling the errors.
db.food.findAll()
.then(function(results) {
})
.catch(function(err) {
});
instead of
db.food.findAll()
.then(function(results) {
}, function(err) {
});

Mongoose/ express how to retrieve only the values of the array

I am new to node.js and want to do the following thing.
Write a query to fetch the annotation(array values) key from mongoDb and pass this array values [only ] as an argument to the second query.
Here is my code
// create the carousel based on the associated stills using keyword annotations
function findAssociatedArchivalStills(carousels, taskCb){
async.waterfall([
// 1st query
function findAssociatedAnnotations(archiveId, taskCb) {
Archive.findAnnotations(archiveId, function onResult(err,annotations){
console.log(annotations);
taskCb(err,annotations);
});
},
// 2nd query
function findAssociatedStills(annotations,taskCb) {
Still.findAssociatedStills(annotations,function onResult(err,stills){
taskCb(err,stills);
});
},
function buildCarousel(stills,taskCb) {
return taskCb(null, new Carousel({
title: 'Related Stills',
items: stills,
}));
},
], function onFinish(err) {
taskCb(null, carousels);
});
},
// done building the associated Episodes carousel
], function onFinish(err, carousels) {
handleResponse(err, res, carousels);
});
});
The methods are defined as follows
1st query definition in model
schema.statics.findAnnotations = function findAnnotations(archiveId, cb) {
this.findOne()
.where('_id', types.ObjectId(archiveId))
.select({'keywords':1, '_id':0})
.exec(cb);
};
2nd query definition in model
schema.statics.findAssociatedStills = function
findAssociatedStills(Annotations, cb) {
this.find()
.where({$text: { $search:Annotations}},{score:{$meta:"textScore"}})
.sort({score:{$meta:"textScore"}})
.limit(2)
.exec(cb);
};
THE PROBLEM IS
When I ran the 1st query , it is returning following
{ keywords:
[ 'IRELAND',
'ELECTIONS',
'PARTY_POLITICAL_BROADCASTS',
'FINE_GAEL' ] }
But the input to the next query should be only the values such as
'IRELAND', 'ELECTIONS', 'PARTY_POLITICAL_BROADCASTS', 'FINE_GAEL'
How to filter from the result only the values of the array without key
I know what will be the query in MongoDb
that is as follows
db.archives.episodes.find({_id:ObjectId("577cd9558786332020aff74c")}, {keywords:1, _id:0}).forEach( function(x) { print(x.keywords); } );
Is it good to filter it in the query or is it right way to filter in the returned script.
Please advice.Thanks for your time.
You're using series, not waterfall. And your archiveId cannot be set in the first function. You need to setup it before async.waterfall.
Here's the right syntax (with waterfall) :
function findAssociatedArchivalStills(carousels, masterCallback){
var archiveId = 'yourArchiveId';
async.waterfall([
// 1st query
function findAssociatedAnnotations(taskCallback) {
Archive.findAnnotations(archiveId, taskCallback);
},
// 2nd query
function findAssociatedStills(annotations, taskCallback) {
Still.findAssociatedStills(annotations,taskCallback);
},
function buildCarousel(stills, taskCallback) {
return taskCallback(null, new Carousel({
title: 'Related Stills',
items: stills
}));
}
], function onFinish(err) {
if (err){
return masterCallback(err);
}
masterCallback(null, carousels);
});
}
Documentation : http://caolan.github.io/async/docs.html#.waterfall
PS : Always use different names for your function's callback and your async functions callbacks.

Object #<Promise> has no method 'limit'

when I run code
var collection = db.get('categories');
console.log(collection.find().limit(1).sort( { _id : -1 } ));
on nodejs using mongodb I am getting error Object # has no method 'limit' . I am a beginner to node and really stuck on this section of node
here is full code for geting last insert document.
router.post('/addcategory', function(req, res) {
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var name = req.body.name;
var description = req.body.description;
// Set our collection
var collection = db.get('categories');
// Submit to the DB
collection.insert({
"name" : name,
"description" : description,
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem adding the information to the database.");
}
else {
// And forward to success page
/******************/
console.log(collection.find().limit(1).sort( { _id : -1 } ));
/*************/
}
});
});
The key piece of missing information here was that you are using Monk, not the native MongoDB Node.JS driver. The command you have for find() is how you would use the native driver (with the changes suggested by #BlakesSeven above for asynchronity), but Monk works a little bit differently.
Try this instead:
collection.find({}, { limit : 1, sort : { _id : -1 } }, function (err,res) {
console.log(res);
});
The method is still asynchronous so you still need to invoke itm either as a promise with .then() or a callback. No methods are sychronous and return results in-line.
Also the result returned from the driver is s "Cursor" and not the object(s) you expect. You either iterate the returned cursor or just use .toArray() or similar to convert:
collection.find().limit(1).sort({ "_id": -1 }).toArray().then(function(docs) {
console.log(docs[0]);
});
Or:
collection.find().limit(1).sort({ "_id": -1 }).toArray(function(err,docs) {
console.log(docs[0]);
});
But really the whole premise is not correct. You seem to basically want to return what you just inserted. Event with the correction in your code, the returned document is not necessarily the one you just inserted, but rather the last one inserted into the collection, which could have occurred from another operation or call to this route from another source.
If you want what you inserted back then rather call the .insertOne() method and inspect the result:
collection.insertOne({ "name": name, "description": description },function(err,result) {
if (err) {
res.send("There was an error");
} else {
console.log(result.ops)
}
});
The .insert() method is considered deprecated, but basically returns the same thing. The consideration is that they return a insertWriteOpResult object where the ops property contains the document(s) inserted and their _id value(s),

Memory leak, using Sequelize ORM for NodeJS

I'm trying to use this Sequelize ORM stuff for my project. I've integrated it as on example https://github.com/sequelize/express-example. So, cool - for now it's working with all relations and other goods. The problem is, that pm2 show's that my memory usage grows and never coming back.
This is my test script, that eats 100 Mb of RAM per launch. Have I missed something?
router.get('/test', hutils.authChecker, function(req, res, next) {
Project.findById(1,{ include : [Player]}).then(function(project) {
return Promise.denodeify(async.map)(project.Players, function(player, callback) {
Player.create({
project_id : 1,
name : 'iter_'+Math.floor(Math.random() * 1000000)+Math.floor(Math.random() * 1000000)
}).then(function(gamer) {
callback(null, gamer)
});
});
}).then(function(plrs) {
return Promise.denodeify(async.map)(plrs, function(guy, callback) {
guy.update({name : sqlRequest+'zzzzz'+Math.random()}).then(function(number) {
callback(null, number);
});
});
}).then(function(numbers) {
return Player.findAll({where : {name : {$like : '%zzzzz%'}}});
}).then(function(zets) {
return Promise.denodeify(async.map)(zets, function(zet, callback) {
zet.destroy().then(function(number) {
callback(null, number);
});
});
}).catch(function(err) {
next(err);
});
});
P.S. It`s make no sense, just to look how the ORM works. If it's matter, i have 1k players, for this project.
In queries that have results with a lot of rows, all of them will get loaded into memory before the callback.
So in this example, the query Project.findById(1,{ include : [Player]}) deserializes project 1 and all of its 1,000 players into JavaScript objects before returning them in the .then(function(project). Furthermore, the array of plrs, numbers and zets are all similarly stored in memory before they get returned thus increasing memory usage.
A way around this would be to get the database to do the heavy lifting. For example don't return each gamer that gets created and instead perform a update query on the db.
Player.update({
name : sqlRequest + 'zzzzz' + Math.random(),
}, {
where: {
createdAt: {
$gte: new Date() // or some other filter condition that identifies the records you need.
}
}
});
And then instead of destroying each zet, perform a delete query on the db.
Player.destroy({
where: {
name : {
$like : '%zzzzz%'
}
}
});

Resources