Search code examples
pythonmongodbsortingindexingranking

Python MongoDB ranking index receiving?


Hello!

I use the latest MongoDB (5.3) pymongo==4.1.1 I have a collection with users. Each of them has a 'points' key. When user opens his profile I want to shown his PLACE IN LEADERBOARD sorted by the 'points' key.

I've seen the $rank aggregation in the docs, but to make this query i should use the $setWindowFields, but I receive an error:

pymongo.errors.OperationFailure: Unrecognized pipeline stage name: '$setWindowFields', full error: {'ok': 0.0, 'errmsg': "Unrecognized pipeline stage name: '$setWindowFields'", 'code': 40324, 'codeName': 'Location40324'}

I've tried a lot of methods, but no one works. How to fix my problem, or advice me a new solution

[
    {"_id": 1, "points": 10},
    {"_id": 2, "points": 30},
    {"_id": 3, "points": 90},
    {"_id": 4, "points": 50}
]

For example I want to see the place if player with '_id': 3. I make some query and find out that his place is the 1st, because he has the greatest points value. I don't need to receive all the documents in collection, because there are even more than 100k documents. I need only index value.

There was a quite same question, but the goal hasn't reached there, using this method you receive sorted list of documents, and each of them just has its index, but anyway you can't find the index of one current document with the particular '_id' :(

Thank you for your help!


Solution

  • Query1

    • this is simple example of how to do it, i think you need this
    • you can replace the 3 with the _id value

    Playmongo

    aggregate(
    [{"$setWindowFields": 
       {"sortBy": {"points": -1}},"output": {"rank": {"$rank": {}}}},
     {"$match": {"$expr": {"$eq": ["$_id", 3]}}},
     {"$project": {"_id": 0, "rank": 1}}])
    

    Query2

    • more complicated but its 1 query, and without $setWindowFields

    Playmongo

    coll.aggregate(
    [{"$match": {"$expr": {"$eq": ["$_id", 2]}}},
     {"$lookup": 
       {"from": "coll",
        "pipeline": 
         [{"$match": {"$expr": {"$gte": ["$points", "$$points"]}}},
           {"$count": "count"}],
        "as": "rank",
        "let": {"points": "$points"}}},
     {"$project": {"_id": 0, "rank": {"$first": "$rank"}}}])
    

    Query3

    You can also send 2 simpler queries

    • find to get the points of the user
    • find and count to get the users with >= points (count in database not on client, or aggregate and count stage)

    I don't know why it says unregognized stage, if you have >= MongoDB 5 it should be working.