2

I'm trying to find the best solution to implement a leaderboard with Elasticsearch.

I store the following data in elastic: playerId, challengeId and score.

Now I want to add "position" column (based on score) but cannot find which is the most efficient way to do this in elastic.

Use case: when I get "all players by challengeId" I want to have "position" field in a response whose value is based on "score" value.

At first look documentation provides many ways to do this: aggregation, Evaluation API, feature datatype and features datatype.

Did anybody use any of these things in elastic? Can I choose one of them for ranking players in leaderboard?

Thanks in advance.

Nikolay Vasiliev
  • 5,656
  • 22
  • 31
Sb Lon
  • 111
  • 2
  • 6

1 Answers1

0

You can achieve it simply by using sort on your score field. For a better explanation, I created an index with some sample data according to your example. More info on sort feature with an example can be found in ES doc.

Index mapping

{
    "mappings": {
        "properties": {
            "pid": {
                "type": "integer"
            },
            "cid" :{
                "type" : "integer"
            },
            "score" :{
                "type" : "integer"
            }
        }
    }
}

Index sample docs

  1. POST /_doc/1

    { "pid" : 1, "cid" :1, "score" : 10 }

  2. POST /_doc/2

    { "pid" : 2, "cid" :1, "score" : 9 }

  3. POST /_doc/3

    { "pid" : 4, "cid" :1, "score" : 6 }

  4. POST /_doc/4

    { "pid" : 4, "cid" :2, "score" : 10 }

  5. POST /_doc/5

    { "pid" : 5, "cid" :2, "score" : 8 }

Sample query to fetch record based on cid aka challengeID and sort results based on score of pid aka playerid.

Search query

{
    "sort": [
        {
            "score": {
                "order": "desc" --> notice `desc` order on `score` field
            }
        }
    ],
    "query": {
        "term": {
            "cid": 2
        }
    }
}

The output of the above search query

"hits": {
      "total": {
         "value": 2,
         "relation": "eq"
      },
      "max_score": null,
      "hits": [
         {
            "_index": "leaderboard",
            "_type": "_doc",
            "_id": "4",
            "_score": null,
            "_source": {
               "pid": 4,
               "cid": 2,
               "score": 10
            },
            "sort": [
               10
            ]
         },
         {
            "_index": "leaderboard",
            "_type": "_doc",
            "_id": "5",
            "_score": null,
            "_source": {
               "pid": 5,
               "cid": 2,
               "score": 8
            },
            "sort": [
               8
            ]
         }
      ]
   }

Notice, search query returned 2 docs which have cid=2 and player ids are sorted in desc order of their score.

Amit
  • 30,756
  • 6
  • 57
  • 88