This question already has an answer here:
-
How do I manage MongoDB connections in a Node.js web application?
10 answers
I've read a few guides on how to use Mongo with Node, and they all seem to connect to databases differently. One particular way that worked well for me was:
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(err) { return console.dir(err); }
db.createCollection('users', function(err, collection) {});
//Do all server/database operations in here
});
However, this seems inefficient/odd to me, I would have to reconnect to the database every time there is an app.get()
, like for making a new user or retrieving information.
Another way that seems better suited to me is
var mongoose = require("mongoose")
var db = mongoose.connect("localhost:27107/users");
db.createCollection('users', function(err, collection) {});
I've seen several sites do something along these lines, but I personally can't get the above to work. I keep getting the error TypeError: db.createCollection is not a function
server-side. So, my question is why the above code doesn't work, if the first code is a good alternative, and if there are any other ways to do this.
You can use a global variable to hold the connection (e.g. db
), for example:
var db = null // global variable to hold the connection
MongoClient.connect('mongodb://localhost:27017/', function(err, client) {
if(err) { console.error(err) }
db = client.db('test') // once connected, assign the connection to the global variable
})
app.get('/', function(req, res) {
db.collection('test').find({}).toArray(function(err, docs) {
if(err) { console.error(err) }
res.send(JSON.stringify(docs))
})
})
Or, if you prefer, you can also use the Promise object that is returned by MongoClient
if it is called without a callback argument:
var conn = MongoClient.connect('mongodb://localhost:27017/') // returns a Promise
app.get('/', function(req, res) {
conn.then(client=> client.db('test').collection('test').find({}).toArray(function(err, docs) {
if(err) { console.error(err) }
res.send(JSON.stringify(docs))
}))
})
Please note that I used the ES6 fat arrow function definition in the second example.
You are absolutely correct that you should not call MongoClient
every time. Using a global variable or Promises allows the MongoDB node.js driver to create a connection pool, which achieves at least two good things:
- Connections are reused in a pool, so there is no multiple expensive setup/teardown process for the lifetime of your application. You connect once, and let the driver take care of the rest for you.
- You can control the amount of connection your application makes into the database, by limiting the size of the connection pool.
Edit 2018-08-24: The MongoClient.connect()
method in node.js driver version 3.0 and newer returns a client object instead of a database object. The examples above were modified to keep it up to date with the latest node.js driver version.
You could use it this way:
that's server.js file:
import path from 'path'
import express from 'express'
import bodyParser from 'body-parser'
import morgan from 'morgan'
import db from './server/database'
import routes from './server/routes'
import webpack from 'webpack'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import webpackConfig from './config/webpack'
const app = express()
const port = process.env.PORT || process.env.NODE_PORT
const compiler = webpack(webpackConfig)
db(λ => {
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: webpackConfig.output.publicPath }))
app.use(webpackHotMiddleware(compiler))
app.use(morgan('dev'))
app.use(bodyParser.json({ limit: '20mb' }))
app.use(bodyParser.urlencoded({ limit: '20mb', extended: false }))
app.use('/static', express.static('static'));
//app.use('/api', jwt)
app.use('/api', routes())
app.set('json spaces', 2)
app.get('*', function(request, response) {
response.sendFile(path.resolve(__dirname, 'index.html'))
})
app.listen(port, (error) => {
if (error) {
console.error(error)
throw error
} else {
console.info(`==>