2015-04-10 5 views

Antwort

10

Zählen Sie die Anzahl der Benutzer, die diesem Benutzer in Ihrer Sortierreihenfolge vorausgehen. Ich beginne mit dem Fall einer einfachen (nicht zusammengesetzten Sortierung), weil die Abfrage im zusammengesetzten Fall komplizierter ist, obwohl die Idee genau dieselbe ist.

> db.test.drop() 
> for (var i = 0; i < 10; i++) db.test.insert({ "x" : i }) 
> db.test.find({ }, { "_id" : 0 }).sort({ "x" : -1 }).limit(5) 
{ "x" : 9 } 
{ "x" : 8 } 
{ "x" : 7 } 
{ "x" : 6 } 
{ "x" : 5 } 

Für diese Bestellung das Ranking eines Dokuments { "x" : i } ist die Anzahl der Dokumente { "x" : j } mit i < j

> var rank = function(id) { 
    var i = db.test.findOne({ "_id" : id }).x 
    return db.test.count({ "x" : { "$gt" : i } }) 
} 
> var id = db.test.findOne({ "x" : 5 }).id 
> rank(id) 
4 

Das Ranking auf 0 basieren wird Und falls Sie den Rang berechnen wollen das Dokument { "x" : i } in der Sortierung { "x" : 1 }, würden Sie die Anzahl der Dokumente { "x" : j } mit i > j zählen.

Für eine Verbindung Art arbeitet das gleiche Verfahren, aber es ist schwieriger zu implementieren, da die Reihenfolge, in einer Verbindung Index lexicographic ist, das heißt, für die Art { "a" : 1, "b" : 1}, (a, b) < (c, d) wenn a < c oder a = c und b < d, so brauchen wir ein mehr komplizierte Abfrage, um diese Bedingung auszudrücken. Hier ist ein Beispiel für eine Verbindung Index:

> db.test.drop() 
> for (var i = 0; i < 3; i++) { 
    for (var j = 0; j < 3; j++) { 
     db.test.insert({ "x" : i, "y" : j }) 
    } 
} 
> db.test.find({}, { "_id" : 0 }).sort({ "x" : 1, "y" : -1 }) 
{ "x" : 0, "y" : 2 } 
{ "x" : 0, "y" : 1 } 
{ "x" : 0, "y" : 0 } 
{ "x" : 1, "y" : 2 } 
{ "x" : 1, "y" : 1 } 
{ "x" : 1, "y" : 0 } 
{ "x" : 2, "y" : 2 } 
{ "x" : 2, "y" : 1 } 
{ "x" : 2, "y" : 0 } 

Um den Rang für das Dokument zu finden { "x" : i, "y" : j }, müssen Sie die Anzahl der Dokumente finden { "x" : a, "y" : b } in der Reihenfolge { "x" : 1, "y" : -1 } so dass (i, j) < (a, b). In Anbetracht der Art Spezifikation, ist dies gleichbedeutend mit der Bedingung i < a oder i = a und j > b:

> var rank = function(id) { 
    var doc = db.test.findOne(id) 
    var i = doc.x 
    var j = doc.y 
    return db.test.count({ 
     "$or" : [ 
      { "x" : { "$lt" : i } }, 
      { "x" : i, "y" : { "$gt" : j } } 
     ] 
    }) 
} 
> id = db.test.findOne({ "x" : 1, "y" : 1 })._id 
> rank(id) 
4 

schließlich im Fall eines dreiteiligen Verbundindex

{ "score" : -1, "time" : 1, "bonus" : -1 } 

die rank Funktion wäre

> var rank = function(id) { 
    var doc = db.test.findOne(id) 
    var score = doc.score 
    var time = doc.time 
    var bonus = doc.bonus 
    return db.test.count({ 
     "$or" : [ 
      { "score" : { "$gt" : score } }, 
      { "score" : score, "time" : { "$lt" : time } }, 
      { "score" : score, "time" : time, "bonus" : { "$gt" : bonus } } 
     ] 
    }) 
} 
Verwandte Themen