Wait until MongoDB has completed its query without using callbacks - node.js

I have an issue with the asynchrous programming model in Node.js.
I know this has been asked before, but so far I haven't found anything that I can use to solve my issue.
How do I force console.log from running before dbQueryName has been invoked and username has gotten its value from it?
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
function dbQueryName() {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection("users").findOne({}, function(err, result) {
if (err) throw err;
return result.name
db.close();
});
});
}
var username = dbQueryName();
// Wait until dbQueryName() has been invoked and username has gotten its value before running this
console.log(username);
I have managed to get it working using a callback parameter in the function, but is there a way to do this with less code and indentation?
function dbQueryName(callback) {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection("users").findOne({}, function(err, result) {
if (err) throw err;
callback(result.name)
db.close();
});
});
}
dbQuery(function(result){
var username = result
console.log(username);
});

Yes if you are not passing a callback to MongoClient.connect or collection.findOne, it returns a promise.
But you need to add another function to use async await
init()
async function dbQueryName() {
const db = await MongoClient.connect(url);
const dbo = db.db("mydb");
const user = await dbo.collection("users").findOne({})
return user.name
}
async function init() {
try {
const name = await dbQueryName()
} catch (error) {
console.log(error);
}
}

Related

Why my function for retrieving data from mongodb is returning undefined?

I am trying to return all the entries from a mongodb collection from a nodejs.
I had written the function and it works if i console log the result i see all the objects from the colletion, but if i try to return the result i am getting undefined.
I cant figure it out why? I had also tried to JSON stringify and JSON parse after but still no success.
Here is my code:
`
const mongoUrl = "mongodb://192.168.8.156:27017/";
const getRoomReadings = function (id) {
MongoClient.connect(mongoUrl, function (err, db) {
if (err) throw err;
let dbo = db.db(`room${id}`);
dbo
.collection("env")
.find({})
.toArray(function (err, result) {
if (err) throw err;
return result;
});
});
};
// API RoomX route
app.get("/api/r:id", (req, res) => {
const rez = getRoomReadings(req.params.id);
console.log(rez);
});
`
I am using nodejs with express.
Please help me. Thanks in advance.
I had also tried to JSON stringify and JSON parse after but still no success.
I don't know why you created the connection each time you do the request but using promises will help you.
Example:
const mongoUrl = "mongodb://192.168.8.156:27017/";
const getRoomReadings = function (id) {
return new Promise((res, rej) => {
MongoClient.connect(mongoUrl, function (err, db) {
if (err) rej(err);
let dbo = db.db(`room${id}`);
dbo
.collection("env")
.find({})
.toArray(function (err, result) {
if (err) rej(err);
return res(result);
});
});
})
};
// API RoomX route
app.get("/api/r:id", async (req, res) => {
const rez = await getRoomReadings(req.params.id);
console.log(rez);
});
a better way to create a connection it creating a file call conn.js and inside that file create your connection
const { MongoClient } = require("mongodb");
const connectionString = process.env.ATLAS_URI;
const client = new MongoClient(connectionString, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
let dbConnection;
module.exports = {
connectToServer: function (callback) {
client.connect(function (err, db) {
if (err || !db) {
return callback(err);
}
dbConnection = db.db(<db_name>);
console.log("Successfully connected to MongoDB.");
return callback();
});
},
getDb: function () {
return dbConnection;
},
};
initialize the connection and use getDb to get the connection

Mongodb find not printing json data

In the code I am trying to find all documents with code UE19CS204.But in the console.log
a big message is printed not the JSON data.The findOne() is working but not find().
I don’t know what change to do to find all documents with code UE19CS204.
var MongoClient = require(‘mongodb’).MongoClient;
var url = “mongodb://localhost:27017/”;
MongoClient.connect(url, { useUnifiedTopology: true } ,function(err, db) {
if (err) throw err;
var dbo = db.db(“pes”);
dbo.collection(“course”).find({“code”:“UE19CS204”}, function(err, result) {
if (err) throw err;
console.log(result);
});
dbo.collection(“course”).findOne({code:“UE19CS204”}, function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
The method find() creates a cursor for a query that can be used to iterate over results from MongoDB, see here.
Use toArray(), you can finde the documentation here.
dbo.collection(“course”).find({“code”:“UE19CS204”}).toArray(function(err, docs) {
if (err) {
throw err;
}
console.log(docs);
})
Full example:
const MongoClient = require('mongodb').MongoClient;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'pes';
// Collection Name
const collectionName = 'course';
// Filter
const filter = { 'code': 'UE19CS204' }
// Use connect method to connect to the server
MongoClient.connect(url, { useUnifiedTopology: true }, function(err, client) {
if (err) {
throw err;
}
client.db(dbName).collection(collectionName).find(filter).toArray(function(err, docs) {
if (err) {
throw err;
}
console.log(docs);
})
client.close();
});

how to handle async function that return promise?

I want to get a user from MongoDB. so I should use the async function to get the right result. but it return me [object , promise]. how can I use this data?
async function getUsers() {
var allUsers = null;
await MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('mydb');
dbo.collection("users").find({})
.toArray(function(err, results) {
if (err)
throw error;
db.close();
allUsers = results;
});
});
}
app.get('/user/', function(req, res) {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('mydb');
var id = req.params.id;
var allUsers = getUsers();
res.render('pages/user', {users: allUsers });
db.close();
});
});
You are mixing up promises and plain callbacks. You need to pick one or the other and consistently use it. Here's how to code it with promises - using the promises that MongoDb can return if used in the right way:
async function getUsers() {
const db = await MongoClient.connect(url);
try {
const dbo = db.db('mydb');
const results = await dbo.collection("users").find({});
return results;
} finally {
db.close();
}
}
app.get('/user/', function(req, res) {
getUsers().then(allUsers => {
res.render('pages/user', {users: allUsers });
}).catch(err => {
console.log(err);
// send some sort of error response here
res.sendStatus(500);
});
});
I removed the database operations from inside your route handler because they weren't actually doing anything and the db stuff was already inside of getUsers().

Why is `func` not a function here in node.js?

I am learning mongodb, and in the book, there's a code
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://127.0.0.1:27017/testdb";
module.exports = function (func) {
MongoClient.connect(url, function(err, db) {
if (err) throw err;
else {
console.log("connected");
func(db);
db.close();
}
});
};
I run this code, but throw the error TypeError: func is not a function, I googled, but lots of codes like this, my mongodb version is 4.0, and node.js version is 9.10, any ideas?
Whatever func you are passing must be a function.
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://127.0.0.1:27017/testdb";
module.exports = function (func) { //func must be function, dont pass just a variable
MongoClient.connect(url, function(err, db) {
if (err) throw err;
else {
console.log("connected");
func(db);
db.close();
}
});
};

Mongo DB make connection outside of post?

I am using MongoDB to insert a record into the database, every time the post method is called. I know I do not want to connect to the db inside of the post function every time, but this is giving me errors? How can I correct this?
var mongo = require('mongodb');
var url = 'mongodb://localhost:27017/Wedding'
var db = function() {
mongo.connect(url, function(err, db){
if (!err){
return db;
}
});
}
app.post('/rsvp', function (req, res) {
var item ={
name: req.body.name,
attending: req.body.attending,
};
insertItem(item);
res.sendFile(path.join(__dirname + '/confirm.html'));
})
function insertItem(item){
db.collection('rsvpList').insertOne(item, function(err, result){
assert.equal(null, err);
})
}
I am getting this error:
TypeError: Object function () {
mongo.connect(url, function(err, db){
if (!err){
return db;
}
});
} has no method 'collection'
at insertItem (C:\Users\A587092\Documents\weddingWebsite\server.js:53:8)
at app.listen.host (C:\Users\A587092\Documents\weddingWebsite\server.js:38:4)
at Layer.handle [as handle_request] (C:\Users\A587092\Documents\weddingWebsite\node_modules\express\lib\router\layer.js:95:5)
The problem is your db does not point to the Mongo instance rather to a function!
Try this -
var mongo = require('mongodb');
var url = 'mongodb://localhost:27017/Wedding'
var db;
mongo.connect(url, function(err, connectedDB){
if (!err){
db = connectedDB;
}
});
You couldn't simply return a value from an asynchronous method:
You should use a callback function:
var connectDb = function(url, cb) {
mongo.connect(url, function(err, db){
if ( err ) {
cb( err );
}
cb(null, db);
});
};
Usage:
function insertItem(item) {
connectDb(url, function(error, db) {
if ( error ) {
throw error;
}
db.collection('rsvpList').insertOne(item, function(err, result) {
assert.equal(null, err);
});
});
}
Or a promise:
var connectDb = function(url) {
return new Promise(function(resolve, reject) {
mongo.connect(url, function(err, db){
if ( err ) {
reject(err);
}
resolve(db);
});
});
};
Usage:
function insertItem(item) {
connectDb(url)
.then(function(db) {
db.collection('rsvpList').insertOne(item, function(err, result) {
assert.equal(null, err);
});
}, function(err) {
throw err;
});
}
I change the function name from db to connectDb because we want to connect to db and then doing something after connecting. and this way your code reads well.
Also note that here also your insertItem function doing an asynchronous task so if you need the result outside of this function you should implement a similar approach, i leave it to you ;)

Resources