2

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

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
    }
    ...
 ]}

但我想返回具有最低价格的对象,而不仅仅是值和城市代码。我怎么做?

谢谢!

4

2 回答 2

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
            }
        ]
    }
]
于 2013-02-08T15:26:39.143 回答
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.

于 2013-02-08T12:17:25.593 回答