mongodb - 在执行$ unwind时过滤掉一些值

时间:2015-04-01 09:35:02

标签: mongodb aggregation-framework

我在mongodb

中有以下客户订单数据
 "_id" : 7,
 "customer name" : "John Smith",
 "OrderItem" : [
         {
                 "product_category" : "Mobile",
                 "price" : 900
         },
         {
                 "product_category" : "Computer",
                 "price" : 4200.48
         },
         {
                 "product_category" : "TV",
                 "price" : 670.20
         },
         {
                 "product_category" : "TV",
                 "price" : 960.52
         }
 ]

我需要将每个产品类别平均为:

 "_id" : 7,
 "customer name" : "John Smith",
 "OrderItem" : [
         {
                 "product_category" : "Mobile",
                 "price" : 900
         },
         {
                 "product_category" : "Computer",
                 "price" : 4200.48
         },
         {
                 "product_category" : "TV",
                 "price" : 815.36
         }
 ]

我试图使用$ unwind但不确定如何对它们进行分组。有什么帮助吗?

3 个答案:

答案 0 :(得分:1)

aggregation framework 与包含以下各个阶段的管道一起使用:第一个管道阶段中的$match操作过滤文档流以仅允许匹配的文档(文档与在您的情况下_id = 7)将未修改的内容传递到下一个管道阶段,即$unwind操作。这将从输入文档中解构所需的OrderItem数组字段,以便为每个元素输出一个文档,然后可以对其进行分组,并执行查找类别价格平均值的聚合操作。管道中的下一个阶段是$ group操作,然后按product_category对输入文档进行分组,并将$avg表达式应用于price上的每个组。然后,最后一个阶段$project重新整形流中的每个文档以产生所需的结果。因此,您的聚合看起来像:

db.collection.aggregate([
    {
        "$match": {"_id": 7}
    },
    {   
        "$unwind": "$OrderItem"
    },
    {
        "$group": {
            "_id": "$OrderItem.product_category",
            "average_price": {
                "$avg": "$OrderItem.price"
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "product_category" : "$_id",
            "average_price": 1
        }

    }
])

<强>结果

{
    "result" : [ 
        {
            "average_price" : 4200.48,
            "product_category" : "Computer"
        }, 
        {
            "average_price" : 815.36,
            "product_category" : "TV"
        }, 
        {
            "average_price" : 900,
            "product_category" : "Mobile"
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

首先你应该放松OrderItem然后将它们分组并mongo $avg来计算平均值。下面的聚合将计算avg

    db.collectionName.aggregate(
                    {"$match":{"customer name":"John Smith"}}, // match specified  customername  
                    {"$unwind":"$OrderItem"}, // unwind the OrderItem

                    {"$group":{"_id":"$OrderItem.product_category",
                       "avg":  {"$avg":"$OrderItem.price"} // mongo avg method used for avrage
                }}
              ).pretty()

以上查询返回以下结果

{ "_id" : "Computer", "avg" : 4200.48 }
{ "_id" : "TV", "avg" : 815.36 }
{ "_id" : "Mobile", "avg" : 900 }

但是上面的结果与您给定的预期输出不匹配,因此您应该分组两次以获得准确的输出

        db.collectionName.aggregate(
                {"$match":{"customer name":"John Smith"}},  //match given criteria
                {"$unwind":"$OrderItem"},           //unwind $OrderItem

                {"$group":{"_id":"$OrderItem.product_category",
                           "customerName":{"$first":"$customer name"}, // group all data with calculating avg
                           "id":{"$first":"$_id"}, 
                               "avg":{"$avg":"$OrderItem.price"}}},

                    {"$group":{"_id":"$id",
                       "customer Name":{"$first":"$customerName"},
                           "OrderItem":{"$push":   {"product_category":"$_id","price":"$avg"}}}} // group them for expected output

               ).pretty()

答案 2 :(得分:0)

.aggregate([
    {$unwind: "$OrderItem"},
    {$group: {
        _id: {id: "$_id", cat: "$OrderItem.product_category"}, 
        name: {$first: "$customer name"}, 
        price: {$avg: "$OrderItem.price"}
    }}, 
    {$group: {
        _id: "$_id.id", 
        OrderItem: {$push: {product_category: "$_id.cat", price: "$price"}}, 
        "customer name": {$first: "$name"}
    }}
])