Mongo DB make connection outside of post? - node.js

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 ;)

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.connect does not execute callback function

Im trying to connect to my Mongodb and insert some documents if they are not already in the db. It works fine with the first inserts but in the function existInDatabase it sometimes does not execute the callback function.
var MongoClient = require('mongodb').MongoClient;
var mongoData = require('./mongoData');
var exports = module.exports = {};
var dbName = 'checklist';
MongoClient.connect(mongoData.ConString, {
useNewUrlParser: true
}, function(err, db) {
if (err) throw err;
for (var key in mongoData.Customers) {
if (!existsInDatabase(mongoData.Customers[key], 'Customers')) {
db.db(dbName).collection('Customers').insertOne(mongoData.Customers[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
db.close();
});
}
}
for (var key in mongoData.Categorys) {
if (!existsInDatabase(mongoData.Customers[key], 'Customers')) {
db.db(dbName).collection('Categorys').insertOne(mongoData.Categorys[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
db.close();
});
}
}
});
function existsInDatabase(obj, collection) {
var result = false;
MongoClient.connect(mongoData.ConString, {
useNewUrlParser: true
}, function(err, db) {
db.db(dbName).collection(collection).find({}).forEach(function(doc) {
if (doc.id == obj.id) {
result = true;
}
}, function(err) {
console.log(err);
});
});
return result;
}
I have made a few changes to your code. It seems you are new to async programming, spend some time to understand the flow. Feel free for any further query. Here is your code.
// Welcome to aync programming
// Here no one waits for the slow processes
var MongoClient = require('mongodb').MongoClient;
var mongoData = require('./mongoData');
var exports = module.exports = {};
var dbName = 'checklist';
// Make the connection for once only
MongoClient.connect(mongoData.ConString, { useNewUrlParser: true },
function(err, db) {
if (err) throw err;
var myDB = db.db(dbName); // create DB for once
for (var key in mongoData.Customers) {
//make call to the function and wait for the response
existsInDatabase(mongoData.Customers[key], 'Customers', function(err, result) {
//once the response came excute the next step
if (result) {
myDB.collection('Customers').insertOne(mongoData.Customers[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
});
}
});
}
for (var key in mongoData.Categorys) {
//make call to the function and wait for the response
existsInDatabase(mongoData.Customers[key], 'Customers', function(err, result) {
//once the response came excute the next step
if (result) {
myDB.collection('Categorys').insertOne(mongoData.Categorys[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
});
}
});
}
// Both the for loop will work randomly without any order
function existsInDatabase(obj, collection, cb) {
var result = false;
myDB.collection(collection).findOne({ id: obj.id }, function(err, result)
{
if (err) {
//this cb will work only when db operation is complited
cb(err);
} else if (result) {
cb(null, true);
} else {
cb(null, false);
}
});
}
});
This code may result in some error. Feel free to ask more questions over it
db.db(dbName).collection(collection).find({}) returns a cursor per the docs. You are missing .toArray():
db.db(dbName).collection(collection).find({}).toArray()...

Keep getting Error: Can't set headers after they are sent

So I am trying out my code for updating and showing it to the user. Basically it is able to do what I need to do but after performing it I get this error
C:\Users\tester01_2\myproject\node_modules\mongodb-core\lib\cursor.js:174
throw err;
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:357:11)
at ServerResponse.header (
C:\Users\tester01_2\myproject\node_modules\express\lib\response.js:725:10)
at ServerResponse.send
(C:\Users\tester01_2\myproject\node_modules\express\lib\response.js:170:12)
at C:\Users\tester01_2\myproject\dbUpdate.js:13:14
at C:\Users\tester01_2\myproject\dbUpdate.js:28:5
at handleCallback (C:\Users\tester01_2\myproject\node_modules\mongodb-
core\lib\cursor.js:171:5)
at nextFunction (C:\Users\tester01_2\myproject\node_modules\mongodb-
core\lib\cursor.js:682:5)
at Cursor.next [as _next]
(C:\Users\tester01_2\myproject\node_modules\mongodb-
core\lib\cursor.js:692:3)
at loop
(C:\Users\tester01_2\myproject\node_modules\mongodb\lib\cursor.js:694:8)
at _each
(C:\Users\tester01_2\myproject\node_modules\mongodb\lib\cursor.js:741:16)
This is my code
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var url = 'mongodb://localhost:27017/myproject';
module.exports = {
postCollection : function(req, res){
var issueQty = req.body.issueQty;
var itemDescrip = req.body.itemDescrip;
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
updateRecord(db, req, function(doc) {
return res.send('Record Found. Now updating this document...' +
itemDescrip + ' Record Updated. This is the new record ' + doc )
res.end();
db.close();
});
});
}
}
var updateRecord = function(db, req, callback) {
var cursor = db.collection('documents').find({'Item Description':
req.body.itemDescrip, 'Issued QTY': req.body.issueQty})
cursor.each(function(err,doc){
assert.equal(err, null);
if(doc != err){
console.log('Successfully queried');
console.log(doc);
callback(JSON.stringify(doc));
} else{
throw err;
}
});
db.collection('documents').updateMany(
{ 'Item Description': req.body.itemDescrip},
{
$set: { 'Issued QTY': req.body.issueQty }
},function(err, results) {
console.log(results);
console.log('Done');
console.log(results);
});
};
I think it has to do with my res due to all the threads I have seen being res being in a wrong position but I need to put my res.send there so that it can use doc. Is there any way to solve this problem? Thanks.
Firstly, you should remove return in front of res.send().
Secondly, in updateRecord function, the callback function shouldn't be called in a loop, it will execute multiple times. And you close the db before you execute updateMany.
If you want to send doc, you should use a temp array to hold the doc, and pass it to res when you finish all logics in updateRecord.
If I understand you correctly, following is my modification of your codes,
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/myproject';
var updateRecord = function(db, req, callback) {
db.collection('documents').updateMany({ 'Item Description': req.body.itemDescrip }, {
$set: { 'Issued QTY': req.body.issueQty }
}, function(err, results) {
if (err) return callback(err);
console.log('Done');
console.log(results);
var cursor = db.collection('documents').find({
'Item Description': req.body.itemDescrip,
'Issued QTY': req.body.issueQty
});
var temp = [];
cursor.each(function(err, doc) {
if (err) {
return callback(err);
}
console.log('Successfully queried');
console.log(doc);
temp.push(JSON.stringify(doc));
});
callback(null, temp);
});
};
module.exports = {
postCollection: function(req, res) {
var issueQty = req.body.issueQty;
var itemDescrip = req.body.itemDescrip;
MongoClient.connect(url, function(err, db) {
if(err) {
res.send(err);
res.end();
db.close();
return;
}
updateRecord(db, req, function(err, docs) {
if(err){
res.send(err);
}
else{
res.send(docs);
}
res.end();
db.close();
});
});
}
}

Persistent mongodb connection function?

How to manage mongodb connections in a nodejs webapp?
The answer of that question is superb. I would like code however to show this. I've tried the following but since it connects async the connection is not ready by the time I want to do my database query. I'm wondering how do others do this?
'use strict';
// database stuff
var mongodb = require('mongodb'); // mongodb drivers
var MongoClient = mongodb.MongoClient; // interface
var url = 'mongodb://127.0.0.1:27017/self';
// generator flow control
var co = require('co');
// database connect function
var dbConnect = function (url) {
// get the db object
MongoClient.connect(url, {
safe: true
}, function (err, db) {
if (err) throw err;
console.log('mongodb connection successful');
return db;
});
};
var db = dbConnect(url);
// generator function with flow control
co(function* () {
console.log('starting db query');
// count documents in collection
var result =
yield new Promise(function (resolve, reject) {
if (err) reject(err);
db.collection('test').count(function (err, res) {
if (err) reject(err);
resolve(res);
});
});
// output number of documents in collection
console.log(result);
});
// more code....
I would like to use the variable db anywhere in my app.
Here maybe one way to reuse the connection.
var myDb;
//reuse connection if already created
function connect(callback) {
if (myDb === undefined) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) { return callback(err)};
myDb = db;
callback(null, db);
});
} else {
callback(null, myDb);
}
function doDBOperation(err, db) {
// your mongodb operation through db is here
co(function* () { ...
}
connect(doDBOperation);
You can wrap your database connection into promise and wait it in generator
function connect() {
return new Promise((resolve, reject) => {
MongoClient.connect(url, {safe: true}, (err, db) => {
if (err) return reject(err);
resolve(db);
});
});
}
var dbConnection = connect();
co(function* () {
var db = yield dbConnection;
// your code
});

How to reference a connection to MongoDB in NodeJS [duplicate]

This question already has an answer here:
NodeJS Can't Access Variable Inside Callback
(1 answer)
Closed 7 years ago.
I have the following code:
var db;
MongoClient.connect("mongodb://localhost:27017/mobregserver", function(err, database) {
if(!err) {
console.log("We are connected");
}
db = database;
});
db.collection('bbr').insert({fields: "fields", files: "files"}, {upsert:true}, function(err, result) {
if(!err){
console.log("written");
}
});
And I get the following output:
We are connected
TypeError: Cannot call method 'collection' of undefined
var db;
MongoClient.connect("mongodb://localhost:27017/mobregserver", function(err, database) {
if(!err) {
console.log("We are connected");
db = database;
db.collection('bbr').insert({fields: "fields", files: "files"}, {upsert:true}, function(err, result) {
if(!err){
console.log("written");
}
});
}
});
Connect method is asyncrone, so your db variable will be initialized much later, then you start using it. Try this code:
MongoClient.connect("mongodb://localhost:27017/mobregserver", function(err, database) {
if(err) {
// Here, it may be better to interrupt further work in case of error
console.log('fail', err);
return;
}
var db = database;
db.collection('bbr').insert({fields: "fields", files: "files"}, {upsert:true}, function(err, result) {
if(!err){
console.log("written");
}
});
});
EDIT
A full example of nodejs server, taken from here
var express = require('express');
var mongodb = require('mongodb');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var db;
// Initialize connection once
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, database) {
if(err) throw err;
db = database;
// Start the application after the database connection is ready
app.listen(3000);
console.log("Listening on port 3000");
});
// Reuse database object in request handlers
app.get("/", function(req, res) {
db.collection("replicaset_mongo_client_collection").find({}, function(err, docs) {
docs.each(function(err, doc) {
if(doc) {
console.log(doc);
}
else {
res.end();
}
});
});
});

Resources