Skip to content

Instantly share code, notes, and snippets.

@darklow
Last active May 31, 2022 05:25
Show Gist options
  • Save darklow/7132077 to your computer and use it in GitHub Desktop.
Save darklow/7132077 to your computer and use it in GitHub Desktop.
ElasticSearch custom sort, based on provided ids array order. Original code from here: http://damienalexandre.fr/post/elasticsearch-ids-query-order Rewritten to new "function_score" syntax Note: You need to remove \n new lines from "script" field in order to get it work.
q = {
"query": {
"function_score": {
"boost_mode": "replace",
"query": {
"ids": {
"values": [
50,
80,
44,
12
]
}
},
"script_score": {
"params": {
"ids": [
50,
80,
44,
12
]
},
"script": """
count = ids.size();
id = org.elasticsearch.index.mapper.Uid.idFromUid(doc['_uid'].value);
for (i = 0; i < count; i++) {
if (id == ids[i]) { return count - i; }
}""",
}
}
},
"size": 20,
"from": 0
}
@darklow
Copy link
Author

darklow commented Nov 5, 2017

Not 1:1 example, but you adjust to IDS as well, this is how I boosted certain items on top of others, while maintaining default sort as well (for ES 5.4+):

{
   "query": {
      "function_score": {
         "query": {
           "match_all": {}
         },
         "boost_mode": "replace",
         "script_score": {
            "script": {
               "params": {
                  "important_tags": ["tag1", "tag2, "tag3"]
               },
               "source": "params.important_tags.indexOf(doc['tag'].value) > -1 ? 10 : 0"
            }
         }
      }
   },
   "sort" : [
       "_score",
        { "defaultOrderField" : "desc" }
    ]
}

@nelsoneldoro
Copy link

According with Elasticsearch Reference [6.6]

{
   "query":{
      "function_score":{
         "boost_mode":"replace",
         "query":{
            "bool":{
               "filter":{
                  "ids":{
                     "values":[
                        50,
                        80,
                        44,
                        12
                     ]
                  }
               }
            }
         },
         "script_score":{
            "script":{
               "params":{
                  "ids":[
                     50,
                     80,
                     44,
                     12
                  ]
               },
               "source":"params.ids.length - params.ids.indexOf(doc['_id'].value)"
            }
         }
      }
   },
   "size":20,
   "from":0
}

@sonureddoorz
Copy link

I am achieving my result using script but I want alternate solution for this. Please help....
I have the similar problem, but I want to boost certain set of documents using functional score :

My current code

{
.
.
.
"sort": [
    {
      "_script": {
        "type": "number",
        "script": {
          "lang": "painless",
          "source": "double pscore = 0;for(id in params.boost_ids){if(params._source.midoffice_master_id == id){pscore = -999999999;}}return pscore;",
          "params": {
            "boost_ids": [
              90,
              687,
              333,
              756
            ]
          }
        }
      }
    },
    {
      "_geo_distance": {
        "location": {
          "lat": -8.4095178,
          "lon": 115.188916
        },
        "order": "asc"
      }
    }
  ]
.
.
.
.
.
}

@terrynguyen255
Copy link

"script_score": {
  "params": {
    "ids": [
        50,
        80,
        44,
        12
    ]
  },
  "script": """
    count = ids.size();
    id    = org.elasticsearch.index.mapper.Uid.idFromUid(doc['_uid'].value);
    for (i = 0; i < count; i++) {
      if (id == ids[i]) { return count - i; }
     }""",
}

This doesn't work in my case.

I update it to:

sort: {
  _script: {
    type: 'number',
    script: {
      lang: 'painless',
      params: {
        ids: [4,8,2,4,8,16],
      },
      source: `
        int idsCount = params.ids.size();
        def id = doc['slug.keyword'].value;
        int foundIdx = params.ids.indexOf(id);
        return foundIdx > -1 ? foundIdx: idsCount + 1;
      `
    }
  }
}

hope it helps someone

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment