我正在尝试新手mongodb并试图为收集mytest1的学生提取最高分的文件并在下面形成一个查询。
{
"_id" : ObjectId("5943b63496459374d40da429"),
"name" : "Person1",
"marks" : 20
},
{
"_id" : ObjectId("5943b65196459374d40da43a"),
"name" : "Person2",
"marks" : 20
},
{
"_id" : ObjectId("5943b65196459374d40da43c"),
"name" : "Person1",
"marks" : 30
},
{
"_id" : ObjectId("5943b6d696459374d40da47a"),
"name" : "Person1",
"marks" : 25
},
{
"_id" : ObjectId("5943b6d696459374d40da47c"),
"name" : "Person2",
"marks" : 50
},
{
"_id" : ObjectId("5943b6d696459374d40da47e"),
"name" : "Person1",
"marks" : 90
},
{
"_id" : ObjectId("5943b6d696459374d40da480"),
"name" : "Person3",
"marks" : 990
}
查询:
db.mytest1.aggregate( [
{ $sort : { "name" : 1,"marks" : -1} },
{$group:
{
_id: "$name",
name: { $first: "$name" },
marks: { $first: "$marks" }
}}
])
结果:
{"name" : "Person1","marks" : 30,"rank" : 1}
{"name" : "Person1","marks" : 25,"rank" : 2}
{"name" : "Person1","marks" : 20,"rank" : 3}
{"name" : "Person2","marks" : 50,"rank" : 1}
{"name" : "Person2","marks" : 20,"rank" : 2}
{"name" : "Person3","marks" : 990,"rank" : 3}
答案 0 :(得分:5)
我认为这最简单的游标迭代是最实用的,但稍后会更多。
使用聚合框架的“小”分组的最快实用方法是使用MongoDB 3.2引入的includeArrayIndex
中的$unwind
:
db.mytest1.aggregate([
{ "$sort": { "name" : 1,"marks" : -1} },
{ "$group": {
"_id": "$name",
"items": { "$push": "$$ROOT" }
}},
{ "$unwind": { "path": "$items", "includeArrayIndex": "items.rank" } },
{ "$replaceRoot": { "newRoot": "$items" } },
{ "$sort": { "name" : 1,"marks" : -1} }
])
产生:
{ "name" : "Person1", "marks" : 90, "rank" : NumberLong(0) }
{ "name" : "Person1", "marks" : 30, "rank" : NumberLong(1) }
{ "name" : "Person1", "marks" : 25, "rank" : NumberLong(2) }
{ "name" : "Person1", "marks" : 20, "rank" : NumberLong(3) }
{ "name" : "Person2", "marks" : 50, "rank" : NumberLong(0) }
{ "name" : "Person2", "marks" : 20, "rank" : NumberLong(1) }
{ "name" : "Person3", "marks" : 990, "rank" : NumberLong(0) }
或者再多走一点:
db.mytest1.aggregate([
{ "$sort": { "name" : 1,"marks" : -1} },
{ "$group": {
"_id": "$name",
"items": { "$push": "$$ROOT" }
}},
{ "$unwind": { "path": "$items", "includeArrayIndex": "items.rank" } },
{ "$project": {
"_id": 0,
"name": "$items.name",
"marks": "$items.marks",
"rank": { "$add": [ "$items.rank", 1 ] }
}},
{ "$sort": { "name" : 1,"marks" : -1} }
])
以你想要的方式。
{ "name" : "Person1", "marks" : 90, "rank" : 1 }
{ "name" : "Person1", "marks" : 30, "rank" : 2 }
{ "name" : "Person1", "marks" : 25, "rank" : 3 }
{ "name" : "Person1", "marks" : 20, "rank" : 4 }
{ "name" : "Person2", "marks" : 50, "rank" : 1 }
{ "name" : "Person2", "marks" : 20, "rank" : 2 }
{ "name" : "Person3", "marks" : 990, "rank" : 1 }
要小心,因为我们将所有内容放入数组中以进行“分组”,以便在提取时获得“索引”位置。这适用于小型列表,但您绝不会尝试使用数千个项目。
对于1000个项目,然后迭代光标并在休息时排名:
var current = null,
rank = 0;
db.mytest1.find().sort({ "name": 1, "marks": -1 }).forEach(doc => {
if ( doc.name != current || current == null ) {
rank = 0;
current = doc.name;
}
rank++;
doc.rank = rank;
delete doc._id;
printjson(doc);
})
结果相同:
{ "name" : "Person1", "marks" : 90, "rank" : 1 }
{ "name" : "Person1", "marks" : 30, "rank" : 2 }
{ "name" : "Person1", "marks" : 25, "rank" : 3 }
{ "name" : "Person1", "marks" : 20, "rank" : 4 }
{ "name" : "Person2", "marks" : 50, "rank" : 1 }
{ "name" : "Person2", "marks" : 20, "rank" : 2 }
{ "name" : "Person3", "marks" : 990, "rank" : 1 }
所以,你可以这样做,因为它非常简单快速。