2017-06-16 165 views
0

我正在尝试新建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" } 
     }} 
]) 
  1. 有没有更好的方式来做到这一点?
  2. 如果我的方案是基于标记对文档进行编号,我该如何实现它?

结果:

 {"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} 

回答

1

我真的认为这是最实际的,简单的游标的迭代,但后来更多。

使用聚合框架“小”集团将利用从$unwindincludeArrayIndex用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 } 

所以真的,你可能也只是做到这一点,因为它的非常简单和快速。