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.
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 });
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.
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.
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.
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)
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 :)
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With