341

MongoDBで node-mongodb-nativeドライバーを使用して Web サイトを作成しています。

接続の管理方法についていくつか質問があります。

  1. すべてのリクエストに対して MongoDB 接続を 1 つだけ使用するだけで十分ですか? パフォーマンスの問題はありますか? そうでない場合、アプリケーション全体で使用するグローバル接続をセットアップできますか?

  2. そうでない場合は、リクエストが到着したときに新しい接続を開き、リクエストを処理したときに閉じればよいですか? 接続を開いたり閉じたりするのは費用がかかりますか?

  3. グローバル接続プールを使用する必要がありますか? ドライバーにはネイティブ接続プールがあると聞きました。それは良い選択ですか?

  4. 接続プールを使用する場合、いくつの接続を使用する必要がありますか?

  5. 他に注意すべき点はありますか?

4

12 に答える 12

516

node-mongodb-native の主なコミッターは次のように述べています

アプリの起動時に do MongoClient.connect を 1 回開き、db オブジェクトを再利用します。.connect ごとに新しい接続プールが作成されるのは、シングルトン接続プールではありません。

したがって、質問に直接答えるには、 から生成された db オブジェクトを再利用してMongoClient.connect()ください。これによりプーリングが可能になり、各 db アクションで接続を開いたり閉じたりする場合と比較して、速度が大幅に向上します。

于 2013-01-22T17:41:07.950 に答える
64

Node.js アプリケーションの開始時に新しい接続を開き、既存のdb接続オブジェクトを再利用します。

/server.js

import express from 'express';
import Promise from 'bluebird';
import logger from 'winston';
import { MongoClient } from 'mongodb';
import config from './config';
import usersRestApi from './api/users';

const app = express();

app.use('/api/users', usersRestApi);

app.get('/', (req, res) => {
  res.send('Hello World');
});

// Create a MongoDB connection pool and start the application
// after the database connection is ready
MongoClient.connect(config.database.url, { promiseLibrary: Promise }, (err, db) => {
  if (err) {
    logger.warn(`Failed to connect to the database. ${err.stack}`);
  }
  app.locals.db = db;
  app.listen(config.port, () => {
    logger.info(`Node.js app is listening at http://localhost:${config.port}`);
  });
});

/api/users.js

import { Router } from 'express';
import { ObjectID } from 'mongodb';

const router = new Router();

router.get('/:id', async (req, res, next) => {
  try {
    const db = req.app.locals.db;
    const id = new ObjectID(req.params.id);
    const user = await db.collection('user').findOne({ _id: id }, {
      email: 1,
      firstName: 1,
      lastName: 1
    });

    if (user) {
      user.id = req.params.id;
      res.send(user);
    } else {
      res.sendStatus(404);
    }
  } catch (err) {
    next(err);
  }
});

export default router;

出典: Node.js/Express アプリでデータベース接続を開く方法

于 2015-10-14T10:09:46.350 に答える
24

MongoDB 接続を管理するコードを次に示します。

var MongoClient = require('mongodb').MongoClient;
var url = require("../config.json")["MongoDBURL"]

var option = {
  db:{
    numberOfRetries : 5
  },
  server: {
    auto_reconnect: true,
    poolSize : 40,
    socketOptions: {
        connectTimeoutMS: 500
    }
  },
  replSet: {},
  mongos: {}
};

function MongoPool(){}

var p_db;

function initPool(cb){
  MongoClient.connect(url, option, function(err, db) {
    if (err) throw err;

    p_db = db;
    if(cb && typeof(cb) == 'function')
        cb(p_db);
  });
  return MongoPool;
}

MongoPool.initPool = initPool;

function getInstance(cb){
  if(!p_db){
    initPool(cb)
  }
  else{
    if(cb && typeof(cb) == 'function')
      cb(p_db);
  }
}
MongoPool.getInstance = getInstance;

module.exports = MongoPool;

サーバーを起動するときに、initPool

require("mongo-pool").initPool();

次に、他のモジュールで次のことができます。

var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
    // Query your MongoDB database.
});

これはMongoDB のドキュメントに基づいています。それを見てください。

于 2015-11-18T13:05:44.787 に答える
6

アプリで redis 接続を使用して generic-pool を使用しています。これを強くお勧めします。そのジェネリックであり、mysqlで動作することは間違いなくわかっているので、それとmongoで問題が発生することはないと思います

https://github.com/coopernurse/node-pool

于 2012-05-18T18:12:04.683 に答える
1

Express を使用する場合は、別のより簡単な方法があります。それは、Express の組み込み機能を利用して、アプリ内のルートとモジュール間でデータを共有することです。app.locals というオブジェクトがあります。プロパティをアタッチして、ルート内からアクセスできます。これを使用するには、app.js ファイルで mongo 接続をインスタンス化します。

var app = express();

MongoClient.connect('mongodb://localhost:27017/')
.then(client =>{
  const db = client.db('your-db');
  const collection = db.collection('your-collection');
  app.locals.collection = collection;
});
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // view engine setup
app.set('views', path.join(__dirname, 'views'));

このデータベース接続、または実際にアプリのモジュールで共有したいその他のデータは、req.app.locals追加のモジュールを作成して必要とせずに、以下のようにルート内でアクセスできるようになりました。

app.get('/', (req, res) => {
  const collection = req.app.locals.collection;
  collection.find({}).toArray()
  .then(response => res.status(200).json(response))
  .catch(error => console.error(error));
});

この方法により、いつでも閉じることを選択しない限り、アプリの実行中はデータベース接続が開いたままになります。で簡単にアクセスでき、req.app.locals.your-collection追加のモジュールを作成する必要はありません。

于 2020-06-03T09:44:53.833 に答える
1

接続プーリングを実装するための最良の方法は、返された接続オブジェクトでデータベース名を保持するグローバル配列変数を 1 つ作成し、MongoClientデータベースに接続する必要があるときはいつでもその接続を再利用することです。

  1. あなたのServer.js定義ではvar global.dbconnections = [];

  2. サービスの命名を作成しますconnectionService.js。と の 2 つの方法がgetConnectionありcreateConnectionます。したがって、ユーザーが を呼び出すとgetConnection()、グローバル接続変数で詳細が検索され、既に存在する場合は接続の詳細が返され、それ以外の場合はcreateConnection()接続の詳細が呼び出されて返されます。

  3. を使用してこのサービスを呼び出す<db_name>と、接続オブジェクトが既にある場合は返され、それ以外の場合は新しい接続が作成されて返されます。

それが役に立てば幸い :)

connectionService.jsコードは次のとおりです。

var mongo = require('mongoskin');
var mongodb = require('mongodb');
var Q = require('q');
var service = {};
service.getConnection = getConnection ;
module.exports = service;

function getConnection(appDB){
    var deferred = Q.defer();
    var connectionDetails=global.dbconnections.find(item=>item.appDB==appDB)

    if(connectionDetails){deferred.resolve(connectionDetails.connection);
    }else{createConnection(appDB).then(function(connectionDetails){
            deferred.resolve(connectionDetails);})
    }
    return deferred.promise;
}

function createConnection(appDB){
    var deferred = Q.defer();
    mongodb.MongoClient.connect(connectionServer + appDB, (err,database)=> 
    {
        if(err) deferred.reject(err.name + ': ' + err.message);
        global.dbconnections.push({appDB: appDB,  connection: database});
        deferred.resolve(database);
    })
     return deferred.promise;
} 
于 2018-03-17T06:58:03.320 に答える