如何跨 NodeJs 应用程序和模块正确重用与 Mongodb 的连接

2022-08-30 01:43:56

我一直在阅读和阅读,但仍然对在整个NodeJs应用程序中共享同一数据库(MongoDb)连接的最佳方式感到困惑。据我所知,当应用程序启动时,连接应该是打开的,并在模块之间重用。我目前对最佳方法的想法是(一切开始的主文件)连接到数据库并创建传递给模块的对象变量。连接后,模块代码将根据需要使用此变量,并且此连接保持打开状态。例如:server.js

    var MongoClient = require('mongodb').MongoClient;
    var mongo = {}; // this is passed to modules and code

    MongoClient.connect("mongodb://localhost:27017/marankings", function(err, db) {
        if (!err) {
            console.log("We are connected");

            // these tables will be passed to modules as part of mongo object
            mongo.dbUsers = db.collection("users");
            mongo.dbDisciplines = db.collection("disciplines");

            console.log("aaa " + users.getAll()); // displays object and this can be used from inside modules

        } else
            console.log(err);
    });

    var users = new(require("./models/user"))(app, mongo);
    console.log("bbb " + users.getAll()); // not connected at the very first time so displays undefined

然后另一个模块看起来像这样:models/user

Users = function(app, mongo) {

Users.prototype.addUser = function() {
    console.log("add user");
}

Users.prototype.getAll = function() {

    return "all users " + mongo.dbUsers;

    }
}

module.exports = Users;

现在我有可怕的感觉,这是错误的,所以这种方法有什么明显的问题吗,如果是这样,如何使它变得更好?


答案 1

您可以创建一个模块,该模块具有连接到 mongo 并返回 mongo 数据库实例的函数:mongoUtil.js

const MongoClient = require( 'mongodb' ).MongoClient;
const url = "mongodb://localhost:27017";

var _db;

module.exports = {

  connectToServer: function( callback ) {
    MongoClient.connect( url,  { useNewUrlParser: true }, function( err, client ) {
      _db  = client.db('test_db');
      return callback( err );
    } );
  },

  getDb: function() {
    return _db;
  }
};

要使用它,您可以在以下位置执行此操作:app.js

var mongoUtil = require( 'mongoUtil' );

mongoUtil.connectToServer( function( err, client ) {
  if (err) console.log(err);
  // start the rest of your app here
} );

然后,当您需要在其他地方访问mongo时,例如在另一个文件中,您可以执行以下操作:.js

var mongoUtil = require( 'mongoUtil' );
var db = mongoUtil.getDb();

db.collection( 'users' ).find();

这有效的原因是,在node中,当模块被'd'时,它们只会被加载/获取一次,所以你最终只会得到一个实例,并且总是会返回相同的实例。require_dbmongoUtil.getDb()

注意,代码未经过测试。


答案 2

有很多方法可以调整它以接受位置的配置对象,但总的来说,它类似于你如何布局你的代码,尽管使用更现代的JS语法。可以很容易地重写为原型和回调,如果这是你的要求。

蒙戈.js

const { MongoClient } = require('mongodb');
const config = require('./config');
const Users = require('./Users');
const conf = config.get('mongodb');

class MongoBot {
  constructor() {
    const url = `mongodb://${conf.hosts.join(',')}`;

    this.client = new MongoClient(url, conf.opts);
  }
  async init() {
    await this.client.connect();
    console.log('connected');

    this.db = this.client.db(conf.db);
    this.Users = new Users(this.db);
  }
}

module.exports = new MongoBot();

用户.js

class User {
  constructor(db) {
    this.collection = db.collection('users');
  }
  async addUser(user) {
    const newUser = await this.collection.insertOne(user);
    return newUser;
  }
}
module.exports = User;

应用程序.js

const mongo = require('./mongo');

async function start() {
  // other app startup stuff...
  await mongo.init();
  // other app startup stuff...
}
start();

一些文件.js

const { Users } = require('./mongo');

async function someFunction(userInfo) {
  const user = await Users.addUser(userInfo);
  return user;
}