elasticsearch实现简单的脚本排序(script sort)

1、背景

我有一堆学生数据,其中湖北省的学生需要排在所有数据的最前面。其余省正序排序,对于同一个省的数据,按照年龄倒序排序。

2、分析

对于上方的排序需求湖北省的学生数据需要排在前端,但是湖北省并不是一个字段,那么这个时候改如何实现呢?对于这种场景我们很容易就想到需要脚本script sort来实现。

3、构建数据

3.1 mapping

PUT /index_person {   "settings": {     "number_of_shards": 1   },   "mappings": {     "properties": {       "id":{         "type": "long"       },       "name": {         "type": "keyword"       },       "age": {         "type": "integer"       },       "province":{         "type": "keyword"       }     }   } } 

3.2 插入数据

PUT /index_person/_bulk {"index":{"_id":1}} {"id":1, "name":"张三","age":18,"province":"湖北"} {"index":{"_id":2}} {"id":2, "name":"李四","age":19,"province":"湖北"} {"index":{"_id":3}} {"id":3, "name":"王武","age":20,"province":"西安"} {"index":{"_id":4}} {"id":4, "name":"赵六","age":21,"province":"西安"} {"index":{"_id":5}} {"id":5, "name":"钱七","age":22,"province":"上海"} 

4、实现

4.1 根据省升序排序

4.1.1 dsl

GET index_person/_search {   "query": {     "match_all": {}   },   "sort": [     {       "province": {         "order": "asc"       }     }   ] } 

4.1.2 运行结果

elasticsearch实现简单的脚本排序(script sort)
可以看到省升序的排序顺序为 上海、湖北、西安

4.2 湖北省排第一

4.2.1 dsl

GET index_person/_search {   "query": {     "match_all": {}   },   "sort": [     {       "_script": {         "type": "number",         "order": "desc",         "script": {           "lang": "painless",           "source": """                       if(params['_source']['province'] == '湖北'){                         1                       } else {                         0                       }                     """         }       }     }   ] } 

4.2.2 运行结果

elasticsearch实现简单的脚本排序(script sort)
通过如上的 script sort排序之后,就可以看到 湖北省已经是排到第一位了。

4.3 湖北省排第一,其余省升序排序,按照年龄倒序

4.3.1 dsl

GET index_person/_search {   "query": {     "match_all": {}   },   "sort": [     {       "_script": {         "type": "number",         "order": "desc",         "script": {           "lang": "painless",           "source": """                       if(params['_source']['province'] == '湖北'){                         1                       } else {                         0                       }                     """         }       }     },     {       "province": {         "order": "asc"       },       "age": {         "order": "desc",         "missing": "_last"       }     }   ] } 

4.3.2 java代码

@Test @DisplayName("脚本排序,固定的某个值的数据排在前面,其余的数据按照别的字段排序") public void test01() throws IOException {     SearchRequest request = SearchRequest.of(searchRequest ->             searchRequest.index("index_person")                     .query(query -> query.matchAll(matchAll -> matchAll))                     .size(100)                     .sort(sort ->                             sort.script(sortScript ->                                     sortScript.type(ScriptSortType.Number)                                             .order(SortOrder.Desc)                                             .script(script ->                                                     script.inline(inline ->                                                             inline.source("if(params['_source']['province'] == params.province){n" +                                                                             "                        1n" +                                                                             "                      } else {n" +                                                                             "                        0n" +                                                                             "                      }")                                                                     .params("province", JsonData.of("湖北"))                                                     )                                             )                             )                     )                     .sort(sort ->                             sort.field(field ->                                     field.field("province").order(SortOrder.Asc)                             )                     )                     .sort(sort ->                             sort.field(field ->                                     field.field("age").order(SortOrder.Desc).missing("_last")                             )                     )     );      System.out.println("request: " + request);     SearchResponse<Object> response = client.search(request, Object.class);     System.out.println("response: " + response); } 

4.3.3 运行结果

elasticsearch实现简单的脚本排序(script sort)

5、完整代码

1、https://gitee.com/huan1993/spring-cloud-parent/blob/master/es/es8-api/src/main/java/com/huan/es8/script/ScriptFieldSort.java

6、参考文档

1、https://www.elastic.co/guide/en/elasticsearch/reference/7.17/sort-search-results.html

发表评论

相关文章