How to use multi query with nodejs express mongodb - node.js

How to use multi query like find , update , insert , delete in one service on mongodb
I can query this below
router.get('/userlist', function(req, res) {
  User.find({},function (err, docs) {
    res.json(docs);
  });
});
but i want to query like this is an error
router.get('/userlist', function(req, res) {
  var data = array();
  User.find({},function (err, docs) {
     data['data1'] = docs
  })
  Content.find({},function (err, docs) {
    data['data2']  = docs
  })
  res.json(docs)
});
Can anyone help me or It is possible to use query like this?
Thank you

You can use async await to run multiple mongo queries inside a function like below:
router.get('/userlist', async function(req, res) {
var data = array();
try{
//first query
let user_data = await User.find({}).exec();
data['data1'] = user_data;
//second query
let content_data = await Content.find({}).exec();
data['data2'] = content_data;
return res.status(200).json(data)
}
catch(err){
return res.status(400).json({err})
}
});

My question is what is stopping you? Yes, you can do this. I did those kinds of works.
There remain two points.
If you need to perform multiple queries, based on the response of the previous query, you can use async/await or promises. If you don't wanna try those, there is still a way. You can check the response of the previous query, make conditions, and if right, execute the seconde one. And thus you can make a chain of queries.
And if you don't need to rely on the responses, do whatever you want. There is nothing wrong...
Happy Coding!

You have to wait for your database call response. So, You can use promise for this. MDN: Promise Make promise of database call and resolve that after you got data from database. Promise.all will wait until your both the promises resolved. MDN: Promise.all()
router.get('/userlist', function(req, res) {
var data = [];
let promise1 = new Promise((resolve, reject) => {
User.find({},function (err, docs) {
data['data1'] = docs;
resolve();
})
});
let promise2 = new Promise((resolve, reject) => {
Content.find({},function (err, docs) {
data['data2'] = docs
})
});
Promise.all([promise1, promise2]).then(result => res.json(docs))
});

Related

Node js route need to wait for processing of another request

We processing the order requests, on the time of multiple HTTP requests hitting the same route function means the function not working properly
Actually, we write the async await operation for all DB related queries
our coding example is
buyCtrl.orderPlace = async function (req, res, next) {
var response = await table1.find({exchange:ref_m}).sort({_id:-1}).limit(1);
if(response.length > 0)
{
var incRes = await table2.findOneAndUpdate({_id:1},{a:b}, {new: true});
var OrdersIns = new Orders();
OrdersIns.userid = userid;
OrdersIns.from = 'a';
OrdersIns.to = 'b';
await OrdersIns.save();
await compare(positiondetails[0]);
res.status(200).json({status:true,message:'Order placed successfully'});
}
}
const compare = async (curOrder) => {
var result = await Orders.find({userid:mongoose.Types.ObjectId(userid),type:opp}).sort({posTimestamp:1});
if(result.length>0)
{
for(var pi=0;pi<result.length;pi++)
{
if(parseFloat(curOrder.qty)==parseFloat(result[i].qty))
{
var updatedata = {a:b}
await Orders.findOneAndUpdate({_id:mongoose.Types.ObjectId(curOrder._id)}, updatedata, {new: true});
await Orders.remove({_id:mongoose.Types.ObjectId(result[i]._id)});
}
else
{
var updatedata = {a:b}
await Orders.findOneAndUpdate({_id:mongoose.Types.ObjectId(result[i]._id))}, updatedata, {new: true});
await Orders.remove({_id:mongoose.Types.ObjectId(curOrder._id)});
}
}
}
}
This is the flow we have I cannot paste my full code so make some example code
Please check and share your ideas
when we make an automation test with more concurrent requests the compare and update is not working properly
Thanks in advance
For atomic operations such as increment and decrement, this can be done using MongoDB's provided API. Another solution is to work with versioning, which MongoDB provides out of the box. The concurrent connection might update the object which changed before the update could take place.

await doesn't wait for function to end

I know this has been asked a lot but I can't seem to use the existing answers to get my code to work. I am trying to use mongojs to make a single query, then put the results in a global (relative to the scope) variable to avoid nesting multiple callbacks. However, I can't seem to get the code to wait for the query to end before continuing.
async function taskmaster() {
const db = mongojs(mongoUri.tasker);
let currentDoc;
const getTask = async function() {
db.tasks.findOne({'task_id': {'$in': [taskId, null]}}, function(err, doc) {
console.log(doc);
currentDoc = doc;
});
}
await getTask();
console.log(currentDoc);
// Code to process currentDoc below
}
No matter what I do, console.log(doc) shows a valid MongoDB document, yet console.log(currentDoc) shows "undefined". Thanks in advance!
Inside your async function, you use findOne method() in callback style, so it's totally normal that console.log(currentDoc) shows undefined, because it executes before
currentDoc = doc;
You can promisify the findOne method, to use it with async/await keyword.
I found a tutorial to promisfy a callback style function here, hope it help : https://flaviocopes.com/node-promisify/
--- EDIT ---
I rewrite your code when promising the findOne method, as suggested by O.Jones
async function taskmaster() {
const getTask = async (taskId) => {
return new Promise((resolve, reject) => {
db.tasks.findOne({'task_id': {'$in': [taskId, null]}}, function(err, doc) {
if(err) {
console.log("problem when retrieve data");
reject(err);
} else {
resolve(doc);
}
});
})
const db = mongojs(mongoUri.tasker);
const currentDoc = await getTask(taskId);
console.log(currentDoc);
}

What is the best way to handle nodejs database async functions

I want a suggestion on how to perform nodejs-DB operations
Here are my options
case one : When you have to run more than one query and former one is dependent on the latter
first way
connection.query(Q1, function(error, results, fields) {
if (error) {
throw error;
}
console.log(results[0]);
//call the second query here
connection.query(Q2, function(error, results, fields) {
if (error) {
throw error;
}
console.log(results[0]);
});
});
or
define first query in a function return the result via promise and await function
call the second query in the same way
use both results
like
var res1 = await funcName1(params);
var res2 = await funcName2(params);// params deducted from res1
which one is better?
case two : when we want to call select query more than 1 times
and capture the results in an array
the last one is pretty preplexing, do i have to call the mysql async function in a loop? is it a correct way?
Can you guys redirect me in the correct way?
I would suggest using the second option, or rather a similar approach to the second option. I believe the code is much easier to read and simpler to maintain. You'll also end up with a fraction of the number of lines of code.
It's also worth nothing that many database modules such as mysql2 and mongodb return promises directly, so there's no need to create wrapper functions, that is you won't need to maintain a load of funcName1, funcName2.. etc.
for example using mysql2:
const mysql = require('mysql2/promise');
const connection = await mysql.createConnection({
host: 'localhost',
user: 'some_user',
password: '***',
database: 'test_db'
});
let [users] = await connection.query('select * from users');
let [accounts] = await connection.query('select * from accounts');
console.log( { users, accounts })
If you wish to create promisified wrapper functions for a generic db access proc, have a look at Util.promisify, this allows you to cut down on boilerplate code.
e.g.
const dbQuery = util.promisify(db.query);
Then you can use like
let result = await dbQuery(param1, param2...);
As long as db.query looks something like
db.query(query, callback(err, result))
Also, querying within loops should work very well, for example:
async function testLoopQuery() {
for(let organization of organizationList) {
let [users] = await connection.query('select * from users where org_id = ?', [organization.id]);
}
}

Mongoose do something after "model.findById" in node

I am looping over a collection of Users in node using mongoose. I want to save the data of every User in a excel File.
Usr.findById(usrID, function(err, foundTagestipp){
sheet1.set(1, counter, 'some Userdata');
}
The problem is that I want to save the file after it went through the whole collection.
So when do I know when the last user is done? Can I somehow give that to a callback or can I somehow get information from mongoose when it is done?
I hope it is clear what I meant by that...
Sorry for the nooby question
you can wrap each async call inside a promise, collect a list of promises and resolve them outside the loop with a call to Promise.all() then execute your business logic.
let promises = [];
myCollection.forEach(elem => {
let promise = new Promise( (resolve, reject) => {
Usr.findById(elem.usrID, function(err, foundTagestipp){
if(err) {
return reject(err);
}
resolve({userId: elem.usrId, userData: foundTagestipp})
}
})
promises.push(promise);
})
Promise.all(promises)
.then(data => {
//here all the findById have already been called
//you can save your data to the csv
})

Program behaving abnormally due to weird async nature of nodejs

I get a post from mongodb then using that post's id I get the likes on that post, my postlikes object contains a "post" and the "likedby" array that contains usernames of people who liked it. The problem is that when i get a post, the callback for getting likes on it is somehow complex thats why node runs ahead and I couldn't get the likes i always get likes of the last post in the db mostly because the loop has reached its end then my callback is called for likes. Any solution for this??
for(var i=0;i<posts.length;i++)
{
db.collection('likes',function(err,likesCollec){
console.log("before likes posts[i].post",posts[i].post);
function wait(done){
while(done);
}
done=true;
likesCollec.find({postid:(posts[i]._id).toString()})
.toArray(function(err,likes){
console.log("posts[i].post:",posts[i].post);
postlikes[i].post=posts[i].post;
console.log("postlikes[i].post: ",postlikes[i].post);
for(j=0;j<likes.length;j++)
{
postlikes[i].likedby[j]=likes[j].username;
}
console.log(postlikes[i]);
done=false;
wait(done);
});
});
if(i==(posts.length)-1)
{
return res.json(posts);
}
}
The wait function isn't working properly also maybe I am going to the wrong direction, please help.
You may use bluebird;
var Promise = require('bluebird');
Var p = Promise.resolve();
forEach(posts, function(item, index, arr) {
p.then(new Promise(function(resolve, reject) {
// do here in sync.
resolve(); //in last
}));
});
p.then(function(){
// all tasks launched in the loop are finished.
// do extra here.
});
Use async forEach
https://www.npmjs.com/package/async
async = require('async');
async.forEach(posts,function(post, callback){
// Do functionality here
return callback();
})

Resources