我正在使用Mongodb。 考虑我的下一个文件:
{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 1, created: ISODate("2014-05-01..."), another_col : "f" },
{ uid: 2, created: ISODate("2014-05-22..."), another_col : "a" }
我想要做的是在uid上进行简单的groupby并按降序排序,这样我就可以得到每个uid的第一行。
预期输出的示例
{ uid: 1, created: ISODate("2014-05-05..."), another_col: "y" },
{ uid: 2, created: ISODate("2014-05-22..."), another_col: "a" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col: "w" }
我能得到的最好的是:
db.mycollection.aggregate( {$group: {_id: "$uid", rows: {$push: { "created" : "$created" }}}}, sort { // doesnt work well } )
任何人都可以指导我进行分组和排序的正确组合吗? 它只是没有像我期望的那样工作。 (注意:我检查了很多线程,但我无法为我的案例找到正确的答案)
答案 0 :(得分:4)
这里有一些需要了解的内容。
当您使用$group
时,边界将按照发现它们的顺序排序,而无需进行初始或结束阶段$sort
操作。因此,如果您的文档最初是这样的顺序:
{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },
然后在管道末端使用$group
而不使用$sort
会返回如下结果:
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },
这是一个概念,但它实际上似乎是您在结果中所期望的,需要按照您要查找的uid
的排序顺序返回“最后的其他字段”。在这种情况下,获取结果的方法实际上是首先 $sort
,然后使用$last
运算符:
db.mycollection.aggregate([
// Sorts everything first by _id and created
{ "$sort": { "_id": 1, "created": 1 } },
// Group with the $last results from each boundary
{ "$group": {
"_id": "$uid",
"created": { "$last": "$created" },
"another_col": { "$last": "$created" }
}}
])
或者基本上将排序应用于您想要的内容。
$last
和$max
之间的区别在于,后者将为分组_id
中的给定字段选择“最高”值,而不管当前在未分类的排序中订购。另一方面,$last
将选择与“最后”分组_id
值相同的“行”中出现的值。
如果您实际上想要对数组的值进行排序,那么方法是类似的。保持阵列成员处于“创建”顺序,你也可以先排序:
db.mycollection.aggregate([
// Sorts everything first by _id and created
{ "$sort": { "_id": 1, "created": 1 } },
// Group with the $last results from each boundary
{ "$group": {
"_id": "$uid",
"row": {
"$push": {
"created": "$created",
"another_col": "$another_col"
}
}
}}
])
带有这些字段的文档将按照已经排序的顺序添加到数组中。
答案 1 :(得分:0)
如果您正在寻找的是第一行意味着您正在寻找最大值。只需使用内置的$max
累加器。
db.mycollection.aggregate([{$group: {_id: "$uid", rows: {$max:"$created"}}}])
如果需要处理所有创建日期,可以使用$push
累加器。有关累加器的更多信息,请参阅:http://docs.mongodb.org/manual/reference/operator/aggregation/group/
如果您想要返回完整的文档,并希望能够遍历所有文档,那么您根本不需要聚合结果。这样的事情可以让你得到你想要的东西。
db.mycollection.find({$query:{}, $orderby:{uid:1,created:-1}})
答案 2 :(得分:0)
使用$ project和
db.mycollection.aggregate([{$group: {_id: "$uid", rows: {$max:"$created"}}}])
应该帮助你,参考这些链接
http://docs.mongodb.org/manual/reference/operator/aggregation/project/