Reputation: 1796
I am wondering what the best way is to reuse db connections in my case its couchebase connection in NodeJs as well as express. For the Express part i created a middleware like this
var couchbase = require('couchbase')
var config = require('../config/config')
module.exports = (req,res,next)=>{
var cluster = new couchbase.Cluster(config.cluster)
cluster.authenticate(config.userid, config.password)
let bucket = cluster.openBucket(config.bucket);
bucket.manager().createPrimaryIndex(function() {});
req.bucket = bucket;
req.N1qlQuery = couchbase.N1qlQuery;
next();
}
which works fine in the express app since i tell it to
const dbSessionMiddleware = require('../middleware/couch')
app.use(dbSessionMiddleware)
which allows me to access it via req.bucket . My issue is that i have controllers in my app which in case might call a helper function and they might call another function to get some data back. I want to avoid to have to keep passing the request object down 5 levels or so to use the middleware. Is there a better way how i can expose the connection / bucket to normal functions ?
Upvotes: 4
Views: 2409
Reputation: 358
Have you tried taking your init code out of the middleware function? The Couchbase Documentation doesn't show it being used that way. Albeit the example is in vanilla Node. By placing it in a middleware function, you're going to be re-connecting to your database everytime the server receives a request.
I connect to my Mongo server in top-level app.js body, which allows the connection to persist. Then I can just import the mongoose reference I need in my Models and Controller to outline how to fetch certain data, and then call the controller's method inside the relevant route endpoint.
Edited to show an example of assigning bucket as a controller class field
In your app.js
const couchbase = require("couchbase");
const config = require("../config/config");
// ...app.js
const CouchController = require("../controllers/CouchController")(couchbase, config);
// app.js...
In your controller
class CouchController {
constructor(couchbase, config) {
// You may either pass couchbase and config as params, or import directly into the controller
this.cluster = new couchbase.Cluster(config.cluster);
this.cluster.authenticate(config.userid, config.password);
this.bucket = cluster.openBucket(config.bucket);
this.N1qlQuery = couchbase.N1qlQuery;
}
doSomeQuery(queryString, callback) {
// Use your query however its meant to be used. I'm not familiar with couchbase queries.
this.bucket.manager().createPrimaryIndex(function() {
this.bucket.query(
this.N1qlQuery.fromString("SELECT * FROM bucketname WHERE $1 in interests LIMIT 1"),
[queryString],
callback(err, result)
)
});
}
}
Then call your Controller method from inside a route
router.get("/", function(req, res, next) {
let searchParam = req.query.someParam;
CouchController.doSomeQuery(searchParam)
.then(result => {
res.json(result);
});
});
Upvotes: 3
Reputation: 187
You could create a specialized module (e.g. db.js
) where you would implement a singleton for you pool of connections.
// pseudo-code
export const getDb = () => {
let db
if (!db) {
const connection = createConnectionPool()
db = connection.db
}
return db
}
This function could be imported on your middleware and on other parts of your code.
Upvotes: 1