0

问题

我需要将定义为“整体”的文档建模为一个小的、固定的“部分”集合,其中整体及其部分都是可查询的。

切片馅饼是我需要的模型的一个很好的例子。进一步描述域:

  • 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
  }]
}

有了这个,我可以按类型、重量、切片重量查询馅饼,我可以通过aggregateunzip和查询单个樱桃馅饼切片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% 的重复数据。

另一个问题是,现在每当我想查询饼图时,我都必须再次查询所有切片。此外,制作馅饼不再是原子操作,而是一批单独的插入。

4

3 回答 3

0

你有没有看过这个:http ://docs.mongodb.org/manual/tutorial/model-tree-structures/ 特别是“带有子引用的模型树结构”似乎正是你想要的。您只能将最特定于切片文档中特定切片的数据(例如切片权重)存储在 Pie 文档中。

于 2013-02-06T22:28:45.880 回答
0

您可以使用如下结构:

{
    "_id" : ObjectId("5112d747819e326e6c37e1e3"),
    "pie" : {
        "type" : "cherry",
        "weight" : 500,
        "slices" : [
            {
                "slice_id" : ObjectId("5112d747819e326e6c37e1e1"),
                "type" : "square",
                "weight" : 75
            },
            {
                "slice_id" : ObjectId("5112d747819e326e6c37e1e2"),
                "type" : "triangle",
                "weight" : 75
            }
        ]
    }
}

然后你可以使用 $unwind 和 $sort 像:

db.q14735834.aggregate({$unwind: "$pie.slices"}, {$sort: {"pie.slices.weight":-1}}, {$limit:10})

并进一步组合 $group 和其他聚合框架运算符来操作数据。

除了 [Alptigin Jalayr] 引用的教程之外,聚合框架文档可能有用:http ://docs.mongodb.org/manual/applications/aggregation/

于 2013-02-06T22:54:50.630 回答
0

我选择的答案,虽然可能不是唯一或最好的答案,是对关系双方的数据进行非规范化。

从本质上讲,slices它们完全嵌入在pie文档中,并且切片存在于它们自己的集合中,并带有重复的pie元数据。这样可以独立查询饼图及其切片,无需任何二次查询。

2路复制存储是否有效?可能不是,但是存储在这里也不是问题。

这是否会使更新文档变得更加复杂和多重操作?是的,但是更新将远远少于读取,在这种情况下读取更为重要。

于 2013-09-16T01:14:13.137 回答