Mongoose 动态模型,不能使用 populate()

Posted

技术标签:

【中文标题】Mongoose 动态模型,不能使用 populate()【英文标题】:Mongoose dynamic models, cannot use populate() 【发布时间】:2014-12-01 18:12:02 【问题描述】:

我的 CMS 是用 Node.js + Express + Mongoose 编写的。这是一个多站点 CMS,每个站点都有自己的数据库。所以我需要让 Mongoose 在每个 HTTP 请求时切换连接。我四处寻找一些解决方案,或者有我同样情况但没有成功的人。所以这是我的解决方案:

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 在多线程上下文中工作。

唯一的问题是当我使用填充方法()时,我得到了这个错误:

f:\www\rudsjs\node_modules\mongoose\lib\connection.js:625 抛出新的 MongooseError.MissingSchemaError(name); ^ MissingSchemaError:尚未为模型“用户”注册架构。使用 mongoose.model(name, schema) 在 NativeConnection.Connection.model (f:\www\rudsjs\node_modules\mongoose\lib\connection.js:625:11) 在填充 (f:\www\rudsjs\node_modules\mongoose\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() 之前使用以下方法预加载模型:

用户(session.database);

但问题似乎与 Mongoose 缓存模型的方式有关(那不是我的),我查看了 connection.js

  model = this.base.models[name];

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

所以我需要一种方法将我的模型插入到 this.base.models 中。你有什么主意吗?您是否特别有更好的解决方案来实现多站点/多数据库环境?

【问题讨论】:

【参考方案1】:

我找到了解决方案。我正在缓存模型而不是连接,所以我为每个模型生成了一个新的 Mongoose 连接,这就是为什么 Mongoose 无法使用 populate() 加载其他模型的原因。

我的解决方案是:使用一个全局缓存对象来存储将用于构建所有模型的连接。

缓存全局对象

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]

中的相同连接

【讨论】:

以上是关于Mongoose 动态模型,不能使用 populate()的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose:在一个集合下动态加载不同的模式

嵌套数组 JSON 的 Mongoose 模型

Nest.js 模型依赖注入与 Mongoose 没有构造函数

如何基于作为参数传递的动态模式的猫鼬模型?

Mongoose - 不能在 post findOneAndUpdate 钩子中调用 model.find()

Mongoose - 不能在 post findOneAndUpdate 钩子中调用 model.find()