每个用户的单独猫鼬模式

Posted

技术标签:

【中文标题】每个用户的单独猫鼬模式【英文标题】:Individual mongoose schema for each user 【发布时间】:2016-04-24 14:22:22 【问题描述】:

我是 nodejs 的新手。 我有一个带有猫鼬和用户登录的应用程序。 mongoDB 中的一些集合适用于所有用户,还有一些像 e.g. customer-collection 是单独的,因此所有用户都有自己的客户集合。 当用户登录并获得他的 jwt-token 时,各个 mongoose 模型将被实例化:

var models = require('../models')(userID);

在文件夹 /models 中有一个 index.js:

var Customer = require('./customermodel'); 

module.exports = function (userID) 
   Customer(userID) 

文件/models/customermodel.js:

var mongooseCustomer = function(userID) 
    var schema = mongoose.Schema(
          _id:  type: Number,
          Name:   type: String ,
          Address:   type: String ,
        , collection: userID + 'userID')
        return mongoose.model(userID + 'customer', schema);

Module.exports = mongooseCustomer;

当客户从两个不同的浏览器登录并返回错误时会出现问题: 编译后无法覆盖123customer 模型。 我通过改变解决了这个问题:

var models = require('../models')(userID);

到:

try 
     var models = require('../models')(userID);
     console.log('Schema was created');

catch (err) 
     console.log('User is already logged in');

现在我的问题是,如果整个设置过于复杂,是否有更简洁的方法来处理以动态方式创建模型?

【问题讨论】:

为每个用户创建单独的集合背后的基本原理是什么?如果您使用 SQL 数据库,这类似于为每个用户创建一个新表,这听起来不是一个好主意。 我习惯使用 .net 和 mysql,我曾经将所有客户行放在一个表中,但有时查询会因表的连接而变得复杂,我一直很担心在特定情况下,查询中的错误可能会向用户显示错误的客户。因此,我正在考虑制作单独系列的想法。无论如何,使用 mongoDB 不会有像 mySQL 那样的连接,并且查询不会太长和太复杂。 @saintedlama 在他们的回答中提出的设置是我自己熟悉的设置,并且效果很好。如果您正确设置查询,并且最好让 QA 人员来测试您的系统,那么在同一个集合中拥有属于不同用户的数据是完全可以的。 【参考方案1】:

如果您真的想坚持为用户动态创建集合,比try catch(err) 更好的方法是查询 mongoose 是否已经为用户编译了模型。 mongoose.model 函数可用于定义检索模型:

var mongooseCustomer = function(userID) 
  var model = mongoose.model(userID + 'customer');

  if (!model) 
    var schema = mongoose.Schema(
      _id:  type: Number,
      Name:   type: String ,
      Address:   type: String ,
    , collection: userID + 'userID');

    model = mongoose.model(userID + 'customer', schema);
  

  return model;
;

Module.exports = mongooseCustomer;

我希望您为每个用户动态创建集合的方法不会扩展,因为 mongoose 不是为处理第 1000 个模型而构建的,而且 Mongodb 像大多数数据库一样具有最大集合限制。

恕我直言,更好的方法是在集合中使用鉴别器来识别租户并公开一个数据库层以透明的方式处理租户。

让我们定义一个暴露最小数据层的模型 node.js 模块

// First define the schema and model
var customerSchema = mongoose.Schema(
    _id:  type: Number,
    // Additional tenant discriminator
    userID:  type: Number, required: true , 
    Name:   type: String ,
    Address:   type: String ,
  );

var customerModel = mongoose.model('customer', schema);

module.exports = function(userID) 
  return 
    customer: 
      find: function(query, callback) 
        query.userID = userID;
        customerModel.find(query, callback);
      ,

      findOne: function(callback) 
        var query =  userID : userID ;
        customerModel.findOne(query, callback);
      
    
  

在使用这个最小层时,您确保始终将用户 ID 添加到 Mongodb 函数中。

var models = require('../models')(123124432);

models.customer.findOne(...);

您还可以使用 mongoose 中间件 (http://mongoosejs.com/docs/middleware.html) 以透明方式处理多租户,而不是在 mongoose 之上定义您自己的数据层。

【讨论】:

这个答案非常有用。使用最小数据层,我可以确保用户 ID 始终包含在查询中。因此,我可以将所有客户移动到同一个集合中,并且只需为客户集合创建一个模式,而无需添加用户 ID。我还将深入研究 mongoose 中间件链接。非常感谢您提供这个快速解决方案 :) saintedlama 我听从了您的建议,并使用了 mongoose 中间件来确保 userID 包含在对自定义集合的所有请求中。它确实是一个很棒的工具:schema.pre('find', function() this.find('userId':userId); ); 我已经用了几天了。一开始它似乎工作正常,但是当模型设置时,它就不能再改变了。这意味着下一个登录的用户会看到第一个用户的客户,因为它使用第一个登录的用户的用户 ID。

以上是关于每个用户的单独猫鼬模式的主要内容,如果未能解决你的问题,请参考以下文章

用户模式中的数组 - 猫鼬

如果文件未导出,如何使用在单独文件中定义的猫鼬模型?

如果用户角色(卖家与买家)有所不同,我该如何构建我的猫鼬模式?

猫鼬从模型中的数组中查找对象

多用户账户的 MongoDB/Mongoose 模式

国家电话代码前缀的猫鼬模式类型,例如“+44”