Using (and reusing) multiple mongoose database connections on express.js

蹲街弑〆低调 提交于 2019-12-04 14:44:25

Is this approach is efficient? Are there any bottlenecks/pitfalls I'm missing?

This all seems generally correct to me

What about the model registering?

I agree with @narc88 that you don't need to register models in middleware.

For lack of a better term, I would use a factory pattern. This "factory function" would take in your sub-domain, or however you decide to detect tenants, and return a Models object. If a given middleware wants to use its available Models you just do

var Models = require(/* path to your Model factory */);

...

// later on inside a route, or wherever
var models = Models(req.sub/* or req.tenant ?? */);
models.Project.find(...);

For an example "factory", excuse the copy/paste

var mongoose = require('mongoose');
var fs = require('fs');
var debug = require('debug')('app:middleware:registerModels');

var models = [];
var conns = [];
var path = __dirname + '/../schemas';

function factory(tenant) {
    // if the connection is cached on the array, reuse it
    if (conns[tenant]) {
        debug('reusing connection', tenant, '...');
    } else {
        debug('creating new connection to', tenant, '...');
        conns[tenant] = mongoose.createConnection('mongodb://localhost:27017/' + tenant);
    }

    if(models[tenant]) {
        debug('reusing models');
    } else {
        var instanceModels = [];
        var schemas = fs.readdirSync(path);
        debug('registering models');
        schemas.forEach(function(schema) {
            var model = schema.split('.').shift();
            instanceModels[model] = conns[tenant].model(model, require([path, schema].join('/')));
        });
        models[tenant] = instanceModels;
    }
    return models[tenant];
}

module.exports = factory;

Aside from potential (albeit probably small) performance gain, I think it also has the advantage of:

  • doesn't clutter up the request object as much
  • you don't have to worry as much about middleware ordering
  • allows more easily abstracting permissions for a given set of models, i.e. the models aren't sitting on the request for all middleware to see
  • This approach doesn't tie your models to http requests, so you might have flexibility to use the same factory in a job queue, or whatever.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!