基于关键值对文档进行排序和排序?
问题描述:
我正在尝试新建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}
答
我真的认为这是最实际的,简单的游标的迭代,但后来更多。
使用聚合框架“小”集团将利用从$unwind
的includeArrayIndex
用MongoDB的3.2中引入最快的可行之路:
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 }
所以真的,你可能也只是做到这一点,因为它的非常简单和快速。