単一のnode.jsプロジェクト内のMongooseおよび複数のデータベース


122

サブプロジェクトを含むNode.jsプロジェクトを実行しています。1つのサブプロジェクトには1つのMongodbデータベースがあり、Mongooseはdbのラップとクエリに使用されます。しかし問題は

  • Mongooseでは、モデルが1つの接続で構築されるため、単一のMongooseインスタンスで複数のデータベースを使用することはできません。
  • 複数のmongooseインスタンスを使用する場合、Node.jsはにキャッシュシステムを備えているため、複数のモジュールインスタンスを許可しませんrequire()。Node.jsでモジュールキャッシングを無効にすることは知っていますが、Mongooseでのみ必要であるため、これは良い解決策ではないと思います。

    私が使用しようとしたcreateConnection()openSet()マングースで、それは解決策ではありませんでした。

    私は、マングースインスタンス(http://blog.imaginea.com/deep-copy-in-javascript/)をディープコピーして、新しいマングースインスタンスをサブプロジェクトに渡そうとしましたが、スローしましたRangeError: Maximum call stack size exceeded

私はとにかくこの問題のためにマングースまたは複数の回避策で複数のデータベースを使用することはありますか?マングースはとても簡単で速いと思うので。または推奨事項として他のモジュール?

回答:


37

できることの1つは、プロジェクトごとにサブフォルダを作成することです。そのため、そのサブフォルダーにmongooseをインストールし、各サブアプリケーションの独自のフォルダーからrequire()mongooseをインストールします。プロジェクトルートまたはグローバルからではありません。つまり、1つのサブプロジェクト、1つのマングースインストール、および1つのマングースインスタンスです。

-app_root/
--foo_app/
---db_access.js
---foo_db_connect.js
---node_modules/
----mongoose/
--bar_app/
---db_access.js
---bar_db_connect.js
---node_modules/
----mongoose/

foo_db_connect.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/foo_db');
module.exports = exports = mongoose;

bar_db_connect.js内

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bar_db');
module.exports = exports = mongoose;

db_access.jsファイル

var mongoose = require("./foo_db_connect.js"); // bar_db_connect.js for bar app

これで、mongooseを使用して複数のデータベースにアクセスできます。


2
つまり、すべてのプロジェクトには独自の接続があります。10万の接続を管理することはできません。useDb同じ接続プールを使用するコマンドを使用する方が良いと思います。
xpepermint 2015年

1
私は現在、この問題を持っています- xpepermintはuseDbのための一例を示すためにあなたができるstackoverflow.com/questions/37583198/...
Lion789

4
これはプロジェクトにとって大きな負担のようです。そう思いませんか?
Eshwar Prasad Yaddanapudi 2016

1
アプリケーションごとにいくつかの異なる接続インスタンス(たとえば、ユーザーDB、セッションDB、およびアプリケーションデータ)があることは、まったく問題ありません。これは「大きな負担」ではなく、スケーリングの問題を引き起こすこともなく、一般的な使用例です。
Iain Collins

あなたは私の最高の友達です!本当にありがとう!わたしにはできる!ありがとう!
Biruel Rick

214

よると細かいマニュアルcreateConnection() することができ、複数のデータベースに接続するために使用されます。

ただし、接続/データベースごとに個別のモデルを作成する必要があります。

var conn      = mongoose.createConnection('mongodb://localhost/testA');
var conn2     = mongoose.createConnection('mongodb://localhost/testB');

// stored in 'testA' database
var ModelA    = conn.model('Model', new mongoose.Schema({
  title : { type : String, default : 'model in testA database' }
}));

// stored in 'testB' database
var ModelB    = conn2.model('Model', new mongoose.Schema({
  title : { type : String, default : 'model in testB database' }
}));

それらの間でスキーマを共有できると確信していますが、確認する必要があります。


4
はい、名前付き接続と共有スキーマは私が考えている方法です。各接続には、Robertの例のように固有のモデルが必要です。
Simon Holmes

21
また、チェックアウトuseDb():基本的な接続プール共有する3.8で利用可能github.com/LearnBoost/mongoose/wiki/...
aaronheckmann

1
自動生成されたデータベースがあるとします(データベースの数はnとします)。1つか2つではありません。データベースごとに個別のモデルを作成せずにこれらに接続する方法はありますか?
AnoojクリシュナンG

1
@AnoojKrishnanGそれは可能ではないと思います、いいえ。各データベースに対して個別にモデルを作成する必要があります。ただし、既に回答で述べたように、接続間でスキーマを共有できるため、コーディング時間を節約できます。
robertklep 2015

1
さまざまなモデル、つまりDB間でスキーマを共有できます。var newSchema = new mongoose.Schema({ ... })var model2 = conn1.model('newModel', newSchema)var model2 = conn2.model('newModel', newSchema)
付与

41

かなり遅いですが、これは誰かを助けるかもしれません。現在の回答では、接続とモデルに同じファイルを使用していると想定しています。

実際には、モデルをさまざまなファイルに分割している可能性が高くなります。メインファイルで次のようなものを使用できます。

mongoose.connect('mongodb://localhost/default');

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log('connected');
});

これはドキュメントで説明されている方法です。次に、モデルファイルで次のようにします。

import mongoose, { Schema } from 'mongoose';

const userInfoSchema = new Schema({
  createdAt: {
    type: Date,
    required: true,
    default: new Date(),
  },
  // ...other fields
});

const myDB = mongoose.connection.useDb('myDB');

const UserInfo = myDB.model('userInfo', userInfoSchema);

export default UserInfo;

myDBはデータベース名です。


ありがとうございました。次を使用して、1つのアプリケーション内で3つの異なるデータベースを使用できました。const mongoose = require( 'mongoose'); const Schema = mongoose.Schema; const mySchema =新しいスキーマ({}); const mydbvar = mongoose.connection.useDb( 'mydb')module.exports = mydbvar.model( 'myCollection'、MySchema);
Johnathan Enslin

2
間違いなく最高で最も現実的な例です。(SQL Serverのようなものを使用していた場合と同様に)デフォルトのdbに接続し、useDbを利用して適切なデータベースでDMLをターゲットにします。(ユーザーを1つのdbに保持し、データを別のdbに保持するのに非常に役立ちます。)最終的に同じサーバーに要求を送信するときに、複数の接続を開始する必要はありません。さて、2つの異なるサーバーに接続している場合、それは別の魚のやかんです。
Newclique 2018

2
@Wadeが言ったように、私が理解している限り、このソリューションはすべてのデータベースが同じサーバー上にある場合にのみ機能します。これがOPの質問に答えるかどうかは明らかではなく、IMOは少し誤解を招きます。
joniba

これは、MongoDB Atlasからの移行に必要なものであり、test複数の接続を回避するためにも必要です。ただし、古いデータベースはマングースで管理する必要がないため.db、最後にも(const v1 = mongoose.connection.useDb('test').db)です。
Polv

37

別のアプローチとして、Mongooseはデフォルトインスタンスの新しいインスタンスのコンストラクタをエクスポートします。したがって、このようなことが可能です。

var Mongoose = require('mongoose').Mongoose;

var instance1 = new Mongoose();
instance1.connect('foo');

var instance2 = new Mongoose();
instance2.connect('bar');

これは、個別のデータソースを操作する場合や、ユーザーまたはリクエストごとに個別のデータベースコンテキストを使用する場合に非常に役立ちます。これを行うと大量の接続が作成される可能性があるため、注意が必要です。インスタンスが不要な場合は必ずdisconnect()を呼び出し、各インスタンスによって作成されるプールサイズを制限してください。


1
これは「上記の答え」を書く別の方法ですか?
プラビン、2016年

11
これは上記の答えではありません。上記の答えは、Mongooseの複数のコピーを不必要にインストールします。
マルティン・バルデス・デ・レオン

この方法を使用してクエリを作成するにはどうすればよいですか?
shahidfoy

2
await instance1.connection.collection('foo').insert({ foo: 'bar', }) await instance2.connection.collection('foo').insert({ foo: 'zoo', })
Abdallah Al Barmawi

実際には、モデルとデータベースはもちろんのこと、接続ごとに完全に異なる資格情報を持っているので、私の場合はうまく機能します。
tzn

0

少し最適化された(私にとっては少なくとも)ソリューション。これをファイルdb.jsに書き込み、必要な場所にこれを要求し、関数呼び出しで呼び出します。これで問題ありません。

   const MongoClient = require('mongodb').MongoClient;
    async function getConnections(url,db){
        return new Promise((resolve,reject)=>{
            MongoClient.connect(url, { useUnifiedTopology: true },function(err, client) {
                if(err) { console.error(err) 
                    resolve(false);
                }
                else{
                    resolve(client.db(db));
                }
            })
        });
    }

    module.exports = async function(){
        let dbs      = [];
        dbs['db1']     = await getConnections('mongodb://localhost:27017/','db1');
        dbs['db2']     = await getConnections('mongodb://localhost:27017/','db2');
        return dbs;
    };
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.