0

私の CMS は Node.js + Express + Mongoose で書かれています。これはマルチサイト CMS であり、各サイトには独自のデータベースがあります。そのため、HTTP リクエストごとに接続を切り替えるように Mongoose を作成する必要がありました。私は解決策、または同じ状態の人を探しましたが、成功しませんでした. これが私の解決策です:

HTTP リクエスト:

router.get('/site/pages', function (req, res) {
    pagesBiz.list(req.session, function(err, list) {
        //do stuff
    });
});

BIZ コンポーネント (pagesBiz):

module.exports = {
    list: function(session, callback) {
        Page(session.database).find(callback);
    }
}

モデル (ページ)

var cached = {};
var getModel = function (database) {
    if(! cached[database]) {
        var conn = mongoose.createConnection('mongodb://localhost/' + database);
        cached[database] = conn.model('Page', pageSchema);
    }

    return cached[database];
}

module.exports = function(database) {
    return getModel(database);
}

それで、それはどのように機能しますか?ユーザーがログインすると、新しいユーザー セッションが作成され、セッション Cookie を介してユーザーにバインドされます (私は MongoStore + Express Session を使用します)。セッションには、Mongoose モデルを動的にインスタンス化するために使用されるデータベースの名前が含まれています。

それは完全に機能し、さまざまなサイトのユーザーが「衝突」のリスクなしに独自のデータベースから読み取ります。反対側では、関数の周りにセッション(またはデータベース名)を渡す必要がありますが、これが Node.js の方法だと思いますマルチスレッドのコンテキストで動作します。

唯一の問題は、populate メソッド () を使用すると、次のエラーが発生することです。

f:\www\rudsjs\node_modules\mongoose\lib\connection.js:625 throw new MongooseError.MissingSchemaError(name); ^ MissingSchemaError: モデル "User" のスキーマが登録されていません。populate (f:\www\rudsjs\node_modules\mongoose) で NativeConnection.Connection.model (f:\www\rudsjs\node_modules\mongoose\lib\connection.js:625:11) で mongoose.model(name, schema) を使用します。 \lib\model.js:2136:24) で Function.Model.populate (f:\www\rudsjs\node_modules\mongoose\lib\model.js:2101:5) で Object.cb (f:\www\rudsjs) \node_modules\mongoose\lib\query.js:1159:16) Object._onImmediate (f:\www\rudsjs\node_modules\mongoose\node_modules\mquery\lib\utils.js:137:16) で processImmediate [as _immediateCallback ] (timers.js:336:15)

プロセスは終了コード 8 で終了しました

これを使用して populate() 呼び出しの前にモデルをプリロードしようとしました:

ユーザー (セッション。データベース);

しかし、問題はMongooseがモデルをキャッシュする方法に関連しているようです(それは私のものではありません)、connection.jsを見ました

  model = this.base.models[name];

  if (!model) {
    throw new MongooseError.MissingSchemaError(name);
  }

したがって、モデルをthis.base.models内に挿入する方法が必要です。何か考えはありますか?マルチサイト/マルチデータベース環境を実装するための特に優れたソリューションはありますか?

4

1 に答える 1

0

解決策を見つけました。接続ではなくモデルをキャッシュしていたので、モデルごとに新しい Mongoose 接続を生成していました。そのため、Mongoose は populate() を使用して他のモデルをロードできませんでした。

私の解決策は、すべてのモデルを構築するために使用される接続を格納するグローバル Cache オブジェクトを使用することです。

グローバル オブジェクトをキャッシュする

module.exports = {
Cache: {
        database: {}
    }
}

モデル (ページ)

module.exports = function(session) {
    if(! Cache.database[session.database]) {
        debug("Create connection to " + session.database);
        var conn = mongoose.createConnection('mongodb://localhost/' + session.database);
        Cache.database[session.database] = conn;
    }

    debug("[rud] " + session.database + " model created");
    return Cache.database[session.database].model('Page', pageSchema);
}

ご覧のとおり、すべてのモデルがCache.database[session.database]に保存されている同じ接続を共有するようになりました

于 2014-10-07T14:51:26.017 に答える