Does mongodb require connection on each operation - node.js

So i am very new to mongodb and i wish to use it in my application. Now i HATE redundant code but reading up on how to use mongodb with node.js it seems that there is a pattern where you always have to connect before making any CRUD operation.
Example from the offical documentation:
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
insertDocument(db, function() {
db.close();
});
});
My question is. is it possible to make a middleware that keeps the connection open so you only has to call insertDocument (in the above example) ?

Yea of course, just keep the db variable around until you don't need it any longer - then call close()
var mdb;
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
mdb = db;
insertDocument(mdb, function() {
// ...
});
});
// do other stuff with mdb

You can also look into using Mongoose as you mentioned middleware.
The connection is only opened once (on the global scope) and then you can use it throughout the app.

Related

How do I get a MongoDB import script to close the db after inserting results?

I am running a quick little nodejs script to find documents in one collection and insert them into another collection but on the same DB. I came up with this guy, but it has no way to close because I think its running open or async?
I have tried placing the db.close() in various places and tried mongoClient.close(). No luck which had me thinking about trying to force a timeout for the async call. Added a connection Time out but it did not have the desired behaviour.
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
const async = require("async");
// Connection URL
var url = 'mongodb://localhost:27017/sourceDB';
// Use connect method to connect to the Server
MongoClient.connect(url,{connectTimeoutMS: "5"}, (err, db) => {
db.collection('source.collection', function(err, col) {
assert.equal(null, err);
col.find().forEach(function (data) {
console.log(data);
db.collection('destination.collection').insertOne(data, function(err, res) {
assert.equal(null, err);
});
console.log("Moved");
});
});
});
The script does well and picks up the collection and inserts, but the connection remains open.
It is not recommended to explicitly close the connection as shown by this SO thread.
Rather, allow the client library to manage the connection for you.

Disconnect PostgreSQL when client goes to new page

I'm trying to build a real time web page and use postgreSQL as my database. I use node.js and express to build backend stuff. Since this is a real time webpage and needs to update information very frequently, I keep a long connection with postgreSQL, which looks like:
app.get('/:A/:B', function(req,res){
var A = req.params.A;
var B = req.params.B;
var client = new pg.Client(config[A][B]);
client.connect(function(err){
if (err) {
console.log("Error occurred when try to connect the database",err);
}
else {
console.log("Connected to the database");
}
});
Do some queries with current database connection...
}
The problem is, when I change the value of A and B in browser and try to connect to a new database, I didn't disconnect with the old one so the info on my page are still from the old database. I'm new to node and web development. Can anyone let me know how to disconnect with the old database when client try to go to a new url?
I think is not good way to create connection for each request. If size of A-B variants is limited then create of connection pool on start is better.
app.get('/:A/:B', function(req, res, next){ // next to forwarding error
var A = req.params.A;
var B = req.params.B;
var client = new pg.Client(config[A][B]);
client.connect(function(err){
if (err)
return next(err); // go to error-middleware
console.log("Connected to the database");
// Do some queries with current database connection...
// Keep it mind that they're also asynchronous, so better way is use promises or async (https://github.com/caolan/async)
client.end(function (err) {
if (err)
next(err);
});
});
}
// Error middleware
app.use(function(err, req, res, next) {
console.log(req.url, err.message);
})

access collection in mongodb through native driver

I have set up a mongo database and have successfully connected through the native driver like so:
var mongo=require('mongodb').MongoClient;
var db;
mongo.connect('mongodb://path/to/db',function(err,db1){
if(err){
console.log(err);
}else{
console.log('mongo connection established');
db=db1;
}
});
I then try to update a preexisting collection:
if(db){db.test.save({hello:'world'});}
I get an error saying cannot call save of undefined.
Try using the following syntax:
db.collection('test').save({hello:'world'}, callback);
In Node.js you need to use the collection method to access the collection (which is different from the MongoDB shell)

How to init native Mongo in NodeJS with at Sign in password

I am trying to figure out how to connect to my mongodb db using the native node mongo driver and I have two issues:
My password contains an # sign making it break the normal user:pass#host connection string format
How do I list databases from what I have below?
Any ideas on how to address this?
Here is an attempt which does not work:
var Mongo = require('mongodb');
var server = new Mongo.Server('mongodb://myhost', 27017);
var db = new Mongo.Db('test', server);
db.open(function(err, db) {
console.log(err); //unable to connect
});
For future readers, I was able to resolve this with the connection option uri_decode_auth. You will need to encodeURIComponent(password) before embedding it in the connection string.
Here's a complete working example:
MongoClient.connect(connection, { uri_decode_auth: true }, function(err, db) {
if(err) {
return cb(err);
}
db.admin().listDatabases(function(err, dbs) {
console.log(dbs);
});
});
As mentioned on this answer:
The solution is to replace # with %40
I tested with the C# driver and it works like a charm.

What's the best practice for MongoDB connections on Node.js?

This is something that is a bit unclear to me (I'm just getting started with Node and Mongo), and it really concerns me because of server performance and strain (which I guess is another question, but I'll get to that at the end of the post).
So, assuming I'm writing an API with Node.js and Restify, where each API endpoint corresponds to a function, should I:
a) open the db connection and store it in a global var, and then just use that in every function?
Example:
// requires and so on leave me with a db var, assume {auto_reconnect: true}
function openDB() {
db.open(function(err, db) {
// skip err handling and so on
return db;
}
}
var myOpenDB = openDB(); // use myOpenDB in every other function I have
b) open the db connection and then just put everything in one giant closure?
Example:
// same as above
db.open(function(err, db) {
// do everything else here, for example:
server.get('/api/dosomething', function doSomething(req, res, next) { // (server is an instance of a Restify server)
// use the db object here and so on
});
}
c) open and close the db each time it is needed?
Example:
// again, same as above
server.get('/api/something', function doSomething(req, res, next) {
db.open(function(err, db) {
// do something
db.close();
});
});
server.post('/api/somethingelse', function doSomethingElse(req, res, next) {
db.open(function(err, db) {
// do something else
db.close();
});
});
This last one is what I would do out of intuition, but at the same time I don't feel entirely comfortable doing this. Doesn't it put too much strain on the Mongo server? Especially when (and I hope I do get to that) it gets hundreds — if not thousands — of calls like this?
Thank you in advance.
I like MongoJS a lot. It lets you use Mongo in a very similar way to the default command line and it's just a wrapper over the official Mongo driver. You only open the DB once and specify which collections you'll be using. You can even omit the collections if you run Node with --harmony-proxies.
var db = require('mongojs').connect('mydb', ['posts']);
server.get('/posts', function (req, res) {
db.posts.find(function (err, posts) {
res.send(JSON.stringify(posts));
});
});
Option A is not a great idea since there is no guarantee that the DB will be finished opening before an HTTP request is handled (granted this is very unlikely)
Option C is also not ideal since it needlessly opens and closes the DB connection
The way that I like to handle this is using deferreds/promises. There are a bunch of different promise libraries available for Node but the basic idea is to do something like this:
var promise = new Promise();
db.open(function(err, db) {
// handle err
promise.resolve(db);
});
server.get('/api/something', function doSomething(req, res, next) {
promise.then(function(db)
// do something
});
});
I believe Mongoose handles connections in a way that vaguely resembles this.

Resources