如何从MongoDB中的组聚合返回整个对象

时间:2013-02-08 12:15:08

标签: mongodb

我有一个像这样的聚合查询:

db.yc_promotions.aggregate([
{$match:
    {
        city_from: {$in: ['x1','x2','x3']},
        city_to: {$in: ['y1','y2','y3']},
        date_ret: {$lte: "2013-06-30"},
        updated: {"$gte": "2013-02-01"}
    }
},
{$group:
    {
        _id: {city_to: "$city_to"},
        min: { $min: "$total_price" }
    }
}
])

查询响应如下所示:

{"result" : [
    {
        "_id" : {
            "city_to" : "y1"
        },
        "min" : 2404.72
    },
    {
        "_id" : {
            "city_to" : "y2"
        },
        "min" : 1619.2
    }
    ...
 ]}

但我希望以最低价格而不仅仅是价值和城市代码返回对象。我该怎么做?

谢谢!

2 个答案:

答案 0 :(得分:4)

看起来您应该可以使用以下内容添加其他字段(我忽略了匹配):

db.test.aggregate(
    { $group: {
        _id: { city_to: "$city_to" },
        min: { $min: "$total_price"  },
        city_from: { $min: "$city_from" }
    } }
);

但这不起作用。 $ min将用于每个字段。举个例子:

> db.test.find();
{ "_id" : ObjectId("51156a11056d6f966f268f7f"), "city_from" : "LHR", "city_to" : "JFK", "total_price" : 500 }
{ "_id" : ObjectId("51156a1a056d6f966f268f80"), "city_from" : "LHR", "city_to" : "LGA", "total_price" : 400 }
{ "_id" : ObjectId("51156a1e056d6f966f268f81"), "city_from" : "DUB", "city_to" : "LGA", "total_price" : 400 }
{ "_id" : ObjectId("51156a27056d6f966f268f82"), "city_from" : "DUB", "city_to" : "JFK", "total_price" : 300 }
> db.test.aggregate( {$group: { _id: { city_to: "$city_to" }, min: { $min: "$total_price"  }, city_from: { $min: "$city_from" } } } );
{
    "result" : [
        {
            "_id" : {
                "city_to" : "LGA"
            },
            "min" : 400,
            "city_from" : "DUB"
        },
        {
            "_id" : {
                "city_to" : "JFK"
            },
            "min" : 300,
            "city_from" : "DUB"
        }
    ],
    "ok" : 1
}

city_from:LHR 完全消失,即使LHR-> LGA和DUB-> LGA都具有相同的最低价格。 city_from:{$ min:“$ city_from”} 仅返回[DUB,LGA]的字符串最小值。您当然可以拥有多个具有相同最低价格的文档(在这种情况下,对于LHR-> LGA和DUB-> LGA都是400个。)

您必须分两步完成此操作:

> result = db.test.aggregate( {$group: { _id: { city_to: "$city_to" }, min: { $min: "$total_price"  } } } );
> final = []
> result.result.forEach(function(entry) { final.push( { city_to: entry._id.city_to, min: entry.min, docs: db.test.aggregate( { $match: { city_to: entry._id.city_to, total_price: entry.min } } ).result } ) } );

然后给出结果:

> final
[
    {
        "city_to" : "LGA",
        "min" : 400,
        "docs" : [
            {
                "_id" : ObjectId("51156a1a056d6f966f268f80"),
                "city_from" : "LHR",
                "city_to" : "LGA",
                "total_price" : 400
            },
            {
                "_id" : ObjectId("51156a1e056d6f966f268f81"),
                "city_from" : "DUB",
                "city_to" : "LGA",
                "total_price" : 400
            }
        ]
    },
    {
        "city_to" : "JFK",
        "min" : 300,
        "docs" : [
            {
                "_id" : ObjectId("51156a27056d6f966f268f82"),
                "city_from" : "DUB",
                "city_to" : "JFK",
                "total_price" : 300
            }
        ]
    }
]

答案 1 :(得分:1)

当你分组时,你必须告诉MongoDB你想要的其他字段的值。所以你在哪里:

min: { $min: "$total_price" }

您需要复制此字段并为要返回的投影对象的每个字段重命名,在这种情况下:

city_to: { $min: "$city_to" },
city_from: { $min: "$city_from" }
// etc

所以一个完整的例子是:

db.yc_promotions.aggregate([
{$match:
    {
        city_from: {$in: ['x1','x2','x3']},
        city_to: {$in: ['y1','y2','y3']},
        date_ret: {$lte: "2013-06-30"},
        updated: {"$gte": "2013-02-01"}
    }
},
{$group:
    {
        _id: {city_to: "$city_to"},
        min: { $min: "$total_price" },
        city_to: { $min: "$city_to" },
        city_from: { $min: "$city_from" }        
    }
}
])

了解我如何将city_tocity_from添加到$group?只需为您希望在$group中投射的每个字段执行此操作。