Get document's placement in collection based on sort order

不问归期 提交于 2019-12-24 03:29:24

问题


I'm new to MongoDB (+Mongoose). I have a collection of highscores with documents that looks like this:

{id: 123, user: 'User14', score: 101}
{id: 231, user: 'User10', score: 400}
{id: 412, user: 'User90', score: 244}
{id: 111, user: 'User12', score: 310}
{id: 221, user: 'User88', score: 900}
{id: 521, user: 'User13', score: 103}

+ thousands more...

now I'm getting the top 5 players like so:

highscores
    .find()
    .sort({'score': -1})
    .limit(5)
    .exec(function(err, users) { ...code... });

which is great, but I would also like to make a query like "What placement does user12 have on the highscore list?"

Is that possible to achieve with a query somehow?


回答1:


It is possible to do this with mapReduce, but it does require that you have an index on the sorted field, so first, if you already have not done:

db.highscores.ensureIndex({ "score": -1 })

Then you can do this:

db.highscores.mapReduce(
    function() {
        emit( null, this.user );
    },
    function(key,values) {
        return values.indexOf("User12") + 1;
    },
    {
        "sort": { "score": -1 },
        "out": { "inline": 1 }
    }
)

Or vary that to the information you need to return other than simply the "ranking" position. But since that is basically putting everything into a large array that has already been sorted by score then it probably will not be the best performance for any reasonable size of data.

A better solution would be to maintain a separate "rankings" collection, which you can again update periodically with mapReduce, even though it does not do any reducing:

db.highscores.mapReduce(
    function() {
        ranking++;
        emit( ranking, this );
    },
    function() {},
    {
        "sort": { "score": -1 },
        "scope": { "ranking": 0 },
        "out": {
            "replace": "rankings"
        }
    }
)

Then you can query this collection in order to get your results:

db.rankings.find({ "value.user": "User12 })

So that would contain the ranking as "emitted" in the _id field of the "rankings" collection.




回答2:


If you don't have to get the placement in real time, Neil Lunn's answer is perfect. But if your app has always data to insert in this collection, for the new data, you can't get the placement for it.

Here is another solution:

Firstly, you add index on the field score in this collection. Then use query db.highscores.count({score:{$gt: user's score}). It will count the documents whose score it greater than the target. This number is the placement.



来源:https://stackoverflow.com/questions/22898757/get-documents-placement-in-collection-based-on-sort-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!