2015-04-10 13 views

risposta

10

Contare il numero di utenti che vengono prima di questo utente nel proprio ordinamento. Inizierò con il caso di un semplice (ordinamento non composto) perché la query nel caso composto è più complicata, anche se l'idea è esattamente la stessa.

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

per questo ordine, la classifica di un documento { "x" : i } è il numero di documenti { "x" : j } con 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 

La classifica sarà basata a 0. Allo stesso modo, se si vuole calcolare il rango per il documento { "x" : i } nel tipo { "x" : 1 }, si conterebbe il numero di documenti { "x" : j } con i > j.

Per una sorta composto, la stessa procedura funziona, ma è più difficile da implementare perché l'ordine in un indice composto è lessicografico, cioè, per l'ordinamento { "a" : 1, "b" : 1}, (a, b) < (c, d) se a < c o a = c e b < d, quindi abbiamo bisogno di una più query complicata per esprimere questa condizione. Ecco un esempio per un indice composto:

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

Per trovare il rango per il documento { "x" : i, "y" : j }, è necessario trovare il numero di documenti { "x" : a, "y" : b } nell'ordine { "x" : 1, "y" : -1 } tale che (i, j) < (a, b). Data la specifica di riordino, questo è equivalente alla condizione i < a o i = a e 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 

Infine, nel caso di un indice composto tre parti

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

la funzione rank sarebbe

> 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 } } 
     ] 
    }) 
} 
Problemi correlati