在mongoDB聚合框架中组合组和项目

Rob*_*ten 4 mongodb aggregation-framework

我的文档看起来像这样:

{ 
  "_id" : ObjectId("5748d1e2498ea908d588b65e"), 
  "some_item" : {
    "_id" : ObjectId("5693afb1b49eb7d5ed97de14"), 
    "item_property_1" : 1.0, 
    "item_property_2" : 2.0,
  }, 
  "timestamp" : "2016-05-28",  
  "price_information" : {
    "arbitrary_value" : 111, 
    "hourly_rates" : [
        {
            "price" : 74.45, 
            "hour" : "0"
        }, 
        {
            "price" : 74.45, 
            "hour" : "1"
        }, 
        {
            "price" : 74.45, 
            "hour" : "2"
        }, 
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

我通过以下方式平均每天的价格:

db.hourly.aggregate([
  {$match: {timestamp : "2016-05-28"}},
  {$unwind: "$price_information.hourly_rates"},
  {$group: { _id: "$unique_item_identifier", total_price: { $avg: "$price_information.hourly_rates.price"}}}
]);
Run Code Online (Sandbox Code Playgroud)

我正努力在结果集中引入(投射)其他参数.我想有也some_itemtimestamp在结果集中.我试图$project: {some_item: 1, total_price: 1, ...}在查询中使用a ,但那不对.

我想要的输出就像:

{ 
  "_id" : ObjectId("5693afb1b49eb7d5ed97de27"), 
  "someItem" : {
    "_id" : ObjectId("5693afb1b49eb7d5ed97de14"), 
    "item_property_1" : 1.0, 
    "item_property_2" : 2.0,
  }, 
  "timestamp" : "2016-05-28",  
  "price_information" : {
    "avg_price": 34
  }
}
Run Code Online (Sandbox Code Playgroud)

如果有人可以给我一个提示,如何将分组和其他参数投射到结果集中,我将感激不尽.

最好的Rob

chr*_*dam 6

如果使用MongoDB 3.2及更高版本,则可以$avg$project管道中使用,因为它返回每个文档的指定表达式或表达式列表的平均值,例如

db.hourly.aggregate([
    { "$match": { "timestamp": "2016-05-28" } },
    {
        "$project": { 
            "price_information": { 
                "avg_price": { "$avg": "$price_information.hourly_rates.price" }
            },
            "someItem": 1,
            "timestamp": 1,
        }
    }
]);
Run Code Online (Sandbox Code Playgroud)

在早期版本的MongoDB中,$avg仅在$group阶段中可用.因此,要包含其他字段,请$first在分组中使用运算符:

db.hourly.aggregate([
    { "$match": { "timestamp": "2016-05-28" } },
    { "$unwind": "$price_information.hourly_rates" },
    {
        "$group": { 
            "_id": "$_id", 
            "avg_price": { "$avg": "$price_information.hourly_rates.price" },
            "someItem": { "$first": "$some_item" },
            "timestamp": { "$first": "$timestamp" },
        }
    },
    {
        "$project": {
            "price_information": { "avg_price": "$avg_price" },
            "someItem": 1
            "timestamp": 1
        }
    }
]);
Run Code Online (Sandbox Code Playgroud)

注意:$first$group阶段中使用运算符很大程度上取决于如何按顺序排列进入该管道的文档以及按组分组.因为$first将返回按键共享同一组的一组文档中的第一个文档值,所以该$group阶段逻辑上应该在一个$sort阶段之前,以便按照定义的顺序输入文档.只有在知道正在处理数据的顺序时才使用它.

但是,由于上面是按主文档的_id键进行分组,因此$first当应用于非非规范化字段(而不是展平的price_information数组字段)时,运算符将保证结果中的原始值.因此,不需要预先排序阶段来定义订单,因为在这种情况下不需要.