问题
我需要将定义为“整体”的文档建模为一个小的、固定的“部分”集合,其中整体及其部分都是可查询的。
切片馅饼是我需要的模型的一个很好的例子。进一步描述域:
- pie:slice 具有 1:many (1-10) 的关系。每个切片只属于一个饼,每个饼有1-10个切片。
- 对于此示例,假设饼图在创建时被切片,并且切片的数量没有变化。
- 馅饼总是用它的切片来查询。相反不一定正确,但查询的切片将需要访问有关饼图的元数据
- 例如,假设“权重”是切片的唯一属性。所有切片共享的元数据远大于每个切片的元数据。所有切片都有相同的面包师、馅料、外壳、厨房等。不必将所有数据复制到每个切片将是理想的。
- 切片和饼图都必须能够通过整个饼图的属性或切片的属性有效地查询和排序。例子:
- 找到所有正好有 2 个切片的馅饼
- 查找所有切片重量 > 10 盎司的馅饼
- 查找类型为“cherry”的所有切片
- 找出所有馅饼中最重的 5 个切片
问题:
鉴于以上几点,一个模型 apie
和它slices
如何有效地查询(如果可能的话,有效地存储)?
如果这很明显,请回答。继续阅读我迄今为止尝试过的两种方法,以及为什么它们都不令人满意。
我试过的:
1.嵌入
在整体中嵌入部分似乎是自然的选择。
Pie {
type: String, // `type` and other shared attrs are defined on Pie
slices: [{
_id: ObjectId
weight: Number
}]
}
有了这个,我可以按类型、重量、切片重量查询馅饼,我可以通过aggregate
、unzip
和查询单个樱桃馅饼切片project
。
问题在于如何对单个切片进行排序和查询。例如,如果我需要从所有饼图中检索 5 个最重的切片(如上述问题中所述)。我这可能与聚合有关,我不知道如何。
2. 单独收藏
在放弃我的第一个模式后,我回到使用两个单独的集合,并通过参考 id 加入:
Pie {
type: String // `type` and other shared attrs are defined on Pie ...
}
Slice {
pie_id: ObjectId,
type: String, // ... and duplicated to all slices
weight: Number
}
这解决了我的查询问题,但引入了更多。这里只是type
重复。在我的实际应用程序中,情况要糟糕得多,以至于我的模拟Slice
可能是 90% 的重复数据。
另一个问题是,现在每当我想查询饼图时,我都必须再次查询所有切片。此外,制作馅饼不再是原子操作,而是一批单独的插入。