MongoDB嵌入式文档引用其他嵌入式文档

时间:2015-06-24 13:58:21

标签: mongodb mongoose

我刚刚学习mongodb,正在寻求文档设计建议。在同一文档中,我希望嵌入式引用引用其他嵌入式引用。

想象一下,我有一个收藏品“个人资料”,它以一系列的东西开始。在某些时候,某些计算逻辑会查看thingILike以得出(并保存)结论。结论应该参考原始清单中的项目......

var myProfile = {
  "thingsILike": [
    {"type": "movie", "name": "300"},
    {"type": "movie", "name": "gladiator"},
    {"type": "tvshow", "name": "spartacus"}
  ],
  "conclusions": [
    {"ancientGore": [SOMEHOW REFERENCE: 300, gladiator, spartacus]},
    {"gladiators": [SOMEHOW REFERENCE: gladiator, spartacus]}
  ]
}

假设我有2个列表的单个集合的正当理由,在结论条目中引用原始thingILike的最佳方法是什么?

我想得出结论保留thingIL的ObjectID列表(即使它们不是集合,也需要objectIds for thingsILike)。如果mongo(或mongoose)填充这些引用就像它们用于集合引用那样会很好。

那么,是否有一些已知的优雅模式或支持我尚未找到?或者我只需要在这里使用暴力并通过代码处理引用?

1 个答案:

答案 0 :(得分:0)

我认为重新评估是否使用子文档数组是一个很好的设计选择。来自MongoLab post on subdocument arrays:“但是,必须小心。需要非常大的数组的数据模型,或者具有高修改率的数组,通常可以导致性能问题。“这可能不是您设计的问题,但值得重新审视。

继续讨论手头的问题,MongoDB没有为文档属性提供内部引用其他属性的方法。猫鼬可以virtuals的形式,但我不相信这会直接解决你的问题。

关于填充conclusions中的值,假设“后一次计算”可能会为每个结论提供一个ObjectId数组,您需要对返回的文档进行后处理以填充值。这可以通过虚拟或通过猫鼬模型上的方法来完成。

使用虚拟getter的方法可以部分解决这个问题,但需要带有结论键的thingsILike标记项。这种更新可以通过虚拟设置器完成,也可以直接通过“后期计算”完成。

使用这种方法,mongodb中的实际对象看起来像:

{
  "thingsILike": [
    {"type": "movie", "name": "300", conclusions: ["ancientGore"]},
    {"type": "movie", "name": "gladiator", conclusions: ["ancientGore", "gladiators"]},
    {"type": "tvshow", "name": "spartacus", conclusions: ["ancientGore", "gladiators"]}
  ]
}

conclusions的虚拟路径为:

MyProfileSchema.virtual('conclusions').get(function () {
  // `this` is the parent document
  // Iterate over things and create conclusions
  return this.thingsILike.reduce(function createConclusions(conclusions, thing) {
    if (Array.isArray(thing.conclusions)) {
      thing.conclusions.forEach(function assignConclusion(conclusion) {
        if (conclusions[conclusion] === undefined) {
          conclusions[conclusion] = [];
        }

        conclusions[conclusion].push(thing);
      });
    }

    return conclusions;
  }, {});
});

请注意,这是一个如何使用虚拟getter的示例,并且可以对其进行各种优化。例如,如果thingsILike被更新,则缓存对象并仅重建对象。