MongoDB嵌套分组

时间:2014-05-13 17:53:21

标签: mongodb aggregation-framework

我有以下MongoDB数据模型:

{
"_id" : ObjectId("53725814740fd6d2ee0ca2bb"),
"date" : "2014-01-01",
"establishmentId" : 1,
"products" : [
    {
        "productId" : 1,
        "price" : 7.03,
        "someOtherInfo" : 325,
        "somethingElse" : 6878
    },
    {
        "productId" : 2,
        "price" : 4.6,
        "someOtherInfo" : 243,
        "somethingElse" : 1757
    },
    {
        "productId" : 3,
        "price" : 2.14,
        "someOtherInfo" : 610,
        "somethingElse" : 5435
    },
    {
        "productId" : 4,
        "price" : 1.45,
        "someOtherInfo" : 627,
        "somethingElse" : 5762
    },
    {
        "productId" : 5,
        "price" : 3.9,
        "someOtherInfo" : 989,
        "somethingElse" : 3752
    }
}

获得所有机构平均价格的最快方法是什么?是否有更好的数据模型来实现这一目标?

3 个答案:

答案 0 :(得分:0)

aggregation操作应该很好地处理这个问题。我建议调查$unwind操作。

这些方面的某些内容应该有用(仅作为示例):

db.collection.aggregate(
  {$match: {<query parameters>}},
  {$unwind: "$products"},
  {
    $group: { 
      _id: "<blank or field(s) to group by before averaging>",
      $avg: "$price"
    }
  }
);

以此样式构建的聚合应生成具有所需数据的JSON对象。

答案 1 :(得分:0)

由于其他任何提供的语法错误,更直接的答案是:

db.collection.aggregate([
    { "$unwind": "$products" },
    { "$group": {
        "_id": null,
        "avgprice": { "$avg": "$products.price" }
    }}
])

此处aggregation framework的用法是首先$unwind数组,这是一种将数组中的内容“反规范化”为单独文档的方法。

然后在$group阶段,您将值null传递给_id,这意味着“将所有内容分组”并传递您的$products.price(请注意点符号)进入$avg运算符,以返回集合中所有文档中所有子文档条目的总平均值。

有关详细信息,请参阅full operator reference

答案 2 :(得分:0)

我找到的最佳解决方案是:

db.collection.aggregate([
    {$match:{date:{$gte:"2014-01-01",$lte:"2014-01-31"},establishmentId:{$in:[1,2,3,4,5,6]}}
    { "$unwind": "$products" },
    { "$group": {
        "_id": {date:"$date",product:"$products.productId"},
        "avgprice": { "$avg": "$products.price" }
    }}
])

我发现的一点是,首先使用匹配然后放松更好,所以放松的项目更少。这导致整个过程更快。