2015-04-10 17 views
5

içinde birden çok alana göre sıralı sırada madde sıralaması almak için MongoDB koleksiyonunda bir dizi kullanıcı kaydına sahibim (> 10000), ancak desc + time asc + bonus desc. Mongoose kullanarak bu sıralamaya göre listedeki bir kullanıcının sıralamasını nasıl alabilirim? Dizin doğru bir şekilde oluşturulduğunu varsayalım.Mongoose

cevap

10

Bu kullanıcıdan önce gelen kullanıcı sayısını sıralama düzeninize göre sayın. Basit (bileşik olmayan bir sıralama) durum ile başlayacağım çünkü fikir tam olarak aynı olsa bile, bileşik vakadaki sorgu daha karmaşıktır. sizin için rütbe hesaplamak istiyorsanız bu sipariş için

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

, bir belgenin { "x" : i } sıralamasında, Benzer sıralama 0'dan esas alınacaktır 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 

ile belgelerin { "x" : j } sayısıdır belgesindeki { "x" : 1 } numaralı belgede, { "x" : j } belgelerinin sayısını i > j ile sayarsınız. Bir bileşik tür için

aynı prosedür çalışır, ancak bir bileşik endeksinde sipariş lexicographic çünkü (a, b) < (c, d) a < c veya a = c ve b < d eğer sıralama { "a" : 1, "b" : 1} için, yani uygulamak daha zordur, bu yüzden daha ihtiyacımız Bu durumu ifade etmek için karmaşık bir sorgu. İşte bileşik endeksi için bir örnek:

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

belgenin { "x" : i, "y" : j } için rütbe bulmak için, sırayla { "x" : 1, "y" : -1 } şekilde (i, j) < (a, b) belge { "x" : a, "y" : b } sayısını bulmalıyız. sıralama şartname göz önüne alındığında, bu durumun i < a veya i = a ve j > b eşdeğerdir:

> 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 

Son olarak, üç parçalı bileşik endeksi sizin durumunuzda

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

rank işlevi olacağını

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