Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the right way to make a synchronous MongoDB query in Node.js?

I'm using the Node.JS driver for MongoDB, and I'd like to perform a synchronous query, like such:

function getAThing() {     var db = new mongo.Db("mydatabase", server, {});      db.open(function(err, db)     {         db.authenticate("myuser", "mypassword", function(err, success)         {             if (success)             {                 db.collection("Things", function(err, collection)                 {                     collection.findOne({ name : "bob"}, function(err, thing)                     {                                                    return thing;                     });                 });             }         });     }); } 

The problem is, db.open is an asychronous call (it doesn't block), so the getAThing returns "undefined" and I want it to return the results of the query. I'm sure I could some sort of blocking mechanism, but I'd like to know the right way to do something like this.

like image 870
Mike Pateras Avatar asked Aug 19 '12 21:08

Mike Pateras


People also ask

Which method is used to connect from Nodejs to MongoDB?

To connect a Node. js application to MongoDB, we have to use a library called Mongoose. mongoose. connect("mongodb://localhost:27017/collectionName", { useNewUrlParser: true, useUnifiedTopology: true });

Is MongoDB synchronous?

MongoDB uses two forms of data synchronization: initial sync to populate new members with the full data set, and replication to apply ongoing changes to the entire data set.

Does node js support synchronous?

Or as Node. js docs puts it, blocking is when the execution of additional JavaScript in the Node. js process must wait until a non-JavaScript operation completes. Blocking methods execute synchronously while non-blocking methods execute asynchronously.

Why we use async and await in MongoDB?

Using async / await only We declare our promise as step 1 like before, but we then utilise await to pause execution until myPromise is resolved, before closing the mongo client and resolving the API call.


2 Answers

ES 6 (Node 8+)

You can utilize async/await

await operator pauses the execution of asynchronous function until the Promise is resolved and returns the value.

This way your code will work in synchronous way:

const query = MySchema.findOne({ name: /tester/gi }); const userData = await query.exec(); console.log(userData) 



Older Solution - June 2013 ;)

Now the Mongo Sync is available, this is the right way to make a synchronous MongoDB query in Node.js.

I am using this for the same. You can just write sync method like below:

var Server = require("mongo-sync").Server; var server = new Server('127.0.0.1'); var result = server.db("testdb").getCollection("testCollection").find().toArray(); console.log(result); 

Note: Its dependent on the node-fiber and some issues are there with it on windows 8.

Happy coding :)

like image 163
Amol M Kulkarni Avatar answered Sep 17 '22 04:09

Amol M Kulkarni


There's no way to make this synchronous w/o some sort of terrible hack. The right way is to have getAThing accept a callback function as a parameter and then call that function once thing is available.

function getAThing(callback) {     var db = new mongo.Db("mydatabase", server, {});      db.open(function(err, db)     {         db.authenticate("myuser", "mypassword", function(err, success)         {             if (success)             {                 db.collection("Things", function(err, collection)                 {                     collection.findOne({ name : "bob"}, function(err, thing)                     {                                db.close();                                             callback(err, thing);                     });                 });             }         });     }); } 

Node 7.6+ Update

async/await now provides a way of coding in a synchronous style when using asynchronous APIs that return promises (like the native MongoDB driver does).

Using this approach, the above method can be written as:

async function getAThing() {     let db = await mongodb.MongoClient.connect('mongodb://server/mydatabase');     if (await db.authenticate("myuser", "mypassword")) {         let thing = await db.collection("Things").findOne({ name: "bob" });         await db.close();         return thing;     } } 

Which you can then call from another async function as let thing = await getAThing();.

However, it's worth noting that MongoClient provides a connection pool, so you shouldn't be opening and closing it within this method. Instead, call MongoClient.connect during your app startup and then simplify your method to:

async function getAThing() {     return db.collection("Things").findOne({ name: "bob" }); } 

Note that we don't call await within the method, instead directly returning the promise that's returned by findOne.

like image 32
JohnnyHK Avatar answered Sep 20 '22 04:09

JohnnyHK