mongodb:如何模拟馅饼(整个馅饼的一小部分)

时间:2013-02-06 18:07:01

标签: mongodb mongoose data-modeling

问题

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

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

  • pie:slice具有1:many(1-10)的关系。每个切片只属于一个饼图,每个饼图有1-10个切片。
  • 对于此示例,假设饼图在创建时被切片,并且切片的数量不会更改
  • 一个饼始终查询其切片。相反的情况不一定如此,但查询的切片需要访问有关饼图的元数据
  • 例如,假设“weight”是切片的唯一属性。所有切片共享的元数据远大于每个切片的元数据。所有切片都有相同的面包师,馅料,面包皮,厨房等。要必须将所有数据复制到每个切片都是理想的。
  • 切片和馅饼必须可以通过整个饼图的属性或切片的属性进行有效查询和排序。例子:
    • 找到所有2个切片的馅饼
    • 找到切片称重的所有馅饼> 10盎司
    • 查找所有类型为“cherry”的切片
    • 查找所有馅饼中最重的5个切片

问题:

鉴于以上几点,如何模拟pie及其slices是否可以有效查询(如果可能,有效存储)?

如果这很明显,请回答。请继续阅读我迄今为止尝试的两种方法,以及为什么两种方法都不令人满意。


我尝试了什么:

1。嵌入

将部件嵌入整个seemed to be the natural choice内。

Pie {
  type: String, // `type` and other shared attrs are defined on Pie
  slices: [{
    _id: ObjectId
    weight: Number
  }]
}

有了这个,我可以按类型,重量,切片重量查询馅饼,我可以通过aggregateunzipproject查询单个樱桃馅饼切片。

问题在于如何在各个切片上排序和查询。例如,如果我需要从所有饼中检索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%的重复数据。

另一个问题是,现在每当我想查询馅饼时,我都要再次查询所有切片。更进一步使馅饼不再是原子操作,而是一批单独的插入。

3 个答案:

答案 0 :(得分:0)

你看过这个:http://docs.mongodb.org/manual/tutorial/model-tree-structures/ 特别是,“带有子引用的模型树结构”似乎正是您正在寻找的。您只能存储切片文档中特定切片的特定数据(例如切片重量)以及饼图文档中的所有其他内容。

答案 1 :(得分: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/

答案 2 :(得分:0)

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

基本上,slices嵌入在pie文档中的entiredy中, 切片存在于自己的集合中,并且重复{ {1}}元数据。通过这种方式,可以独立查询饼图及其切片,无需任何二次查询。

双向复制存储是否有效?可能不会,但是再次存储不是问题。

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