mongodb - Mongoose:如何建模外键/反向关系?

标签 mongodb node.js mongoose

我正在使用 Mongoose 对 PersonTransaction 集合进行建模,其中每个 Transaction 将引用两个不同的 Person 实例:

var TransactionSchema = new Schema({
  , amount          : { type: Number, required: true }
  , from            : { type: ObjectId, required: true }
  , to              : { type: ObjectId, required: true }
  , date            : Date
});

var PersonSchema = new Schema({
    name            : { type: String, required: true }
  , transactions    : [ObjectId]
});

我希望每个 Person 拥有所有 Transaction 的集合,它们是 tofrom 值。到目前为止,这是我能够弄清楚如何做到这一点的最佳方法:

TransactionSchema.pre('save', function(next, done) {
    var transaction = this;

    Person.findById(this.to, function (err, person) {
        person.transactions.push(transaction);
        person.save();
    });

    Person.findById(this.from, function (err, person) {
        person.transactions.push(transaction);
        person.save();
    });

    next();
});

这似乎太过分了。有没有更好的方法来做到这一点,或者我是否试图像使用关系数据库一样使用 MongoDB?我应该直接查询 Translation 集合,而不是与每个 Person 实例关联的 Transaction 集合吗?

谢谢。

最佳答案

在设计 MongoDB 架构时,您必须更多地考虑要在数据库上执行的查询。

尝试复制数据以提高速度并引用它以确保完整性。这是什么意思?
好吧,例如,当您查询交易时,我想您不需要第一次的所有用户详细信息,不是吗? (在交易中显示信息时是否需要用户的电子邮件、位置?)
我认为您可能只需要用户 ID 和用户名,所以您应该这样做:

var TransactionSchema = new Schema({
  , amount          : { type: Number, required: true }
  , from            : { 
     user_id: {
       type: ObjectId
     , required: true
    }
   , username: {
       type: String
     , required: true
    } 
  }
  , to              : { 
     user_id: {
       type: ObjectId
     , required: true
    }
   , username: {
       type: String
     , required: true
    } 
  }
  , date            : Date
});

因此,您无需对显示交易详细信息的页面进行 3 次查询(1 次用于交易,2 次额外查询用于用户名),而您将只有一次。
这只是一个示例,您可以对 User 架构应用相同的逻辑,具体取决于您要实现的目标。

无论如何,我认为您的中间件不行,因为您没有在那里检查错误(无论如何,您总是调用 next )。这就是我编写中间件的方式(没有测试,但想法很重要):

TransactionSchema.pre('save', function(next, done) {
  var transaction = this;

  Person.where('_id').in([this.to, this.from]).run(function (err, people) {
    if (people.length != 2) { next(new Error("To or from doesn't exist")); return; }
    Step(
      function save_to() {
        people[0].transactions.push(transaction);
        people[0].save(this);
      },
      function save_from(err) {
        if (err) { next(err); return; }
        people[1].transactions.push(transaction);
        people[1].save(this);
      },
      function callback(err) {
        next(err); 
      }
    );
  });
});

在上面的代码中,我使用了 Step流控制库,我只使用一个查询而不是两个(搜索“to”和“from”时)。

关于mongodb - Mongoose:如何建模外键/反向关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7947283/

相关文章:

mongodb聚合嵌套嵌套数组

node.js - 对 mongoose mapReduce 进行分页,用于排名算法

javascript - AngularJS SPA : How to Angular Controller SPA to call Angular service?

javascript - 从 Express 静态 html 文件调用 $.getJSON() 无法获取数据

node.js - Webpack 产品与开发

Mongoose :如何使用模式字段作为另一个字段的枚举?

mongodb - 无法使用来自 c# 的 x509 证书身份验证连接到 MongoDB 服务器

MongoDB - 记录写入和读取查询

javascript - 使用 javascript/node.js 在 mongodb 中查找具有另一个条件的对象的最早日期

node.js - Mongoose find - 使用返回的数据并将其添加到变量中