【问题标题】:ElasticSearch how to sort by a giving idListElasticSearch如何按给定的idList排序
【发布时间】:2021-08-13 19:19:53
【问题描述】:

我有一个要查询的参数列表,我想按这个参数列表顺序得到结果排序

在MYSQL中是这样的

select * from tableA
where id in (3, 1, 2)
order by field(id, 3, 1, 2)

如何在es中达到同样的效果?

"query":{
    "bool":{
        "must":{
            {"terms":{ "xId" : #[givenIdList] }}
        }
    }
}
"sort":{how to sort by #[givenIdList]?}

感谢您的任何建议。

【问题讨论】:

    标签: java mysql sql sorting elasticsearch


    【解决方案1】:

    这个想法是,给定排序列表[3, 1, 2],您应该为 3 返回较小的分数,为 1 返回较大的分数,最后为 2 返回最大的分数。您可以考虑的最简单的函数是从数组元素到其索引的函数.例如,对于 3,您应该返回 0,对于 1 1 和对于 2 2。

    具体来说,您需要一个可能如下所示的函数:

    def myList = [3, 1, 2];
    // Declares a map literal
    Map m= [:];
    
    // Generate from [3, 1, 2] the mapping { 3 = 0.0, 1 = 1.0, 2 = 2.0 }
    def i = 0;
    for (x in myList) {
      m[x] = (double)i++;
    }
    
    // Extract the xId from the document
    def xId = (int)doc['xId'].value;
    
    // Return the mapped value, e.g., for 3 return 0
    return m[xId];
    

    显然,您可以通过将地图作为参数直接传递给脚本here 来提高性能。

    在这种情况下,脚本简化为:

    def xId = doc['xId'].value.toString();
    return params.m[xId];
    

    完整示例

    索引数据

    POST _bulk
    {"index": { "_index": "test", "_id": 1}}
    {"xId": 1}
    {"index": { "_index": "test", "_id": 2}}
    {"xId": 2}
    {"index": { "_index": "test", "_id": 3}}
    {"xId": 3}
    {"index": { "_index": "test", "_id": 4}}
    {"another_field": "hello"}
    

    使用列表方法的完整示例:

    GET test/_search
    {
      "query": {
        "terms": {
          "xId": [3, 1, 2]
        }
      },
      "sort": {
        "_script": {
          "type": "number",
          "script": {
            "lang": "painless",
            "params": {
              "list": [3, 1, 2]
            },
            "source": """
    Map m= [:];
    
    def i = 0;
    
    for (x in params.list) {
      m[x] = (double)i++;
    }
    
    def xId = (int)doc['xId'].value;
    
    m[xId];
    """
          },
          "order": "asc"
        }
      }
    }
    

    地图方法的完整示例

    GET test/_search
    {
      "sort": {
        "_script": {
          "type": "number",
          "script": {
            "lang": "painless",
            "params": {
              "list": [3, 1, 2],
              "map": {
                "3": 0.0,
                "1": 1.0,
                "2": 2.0
              }
            },
            "source": """
    
    def xId = doc['xId'].value.toString();
    
    params.map[xId];
    """
          },
          "order": "asc"
        }
      },
      "query": {
        "terms": {
          "xId": [3, 1, 2]
        }
      }
    }
    

    最后说明

    1. 脚本被简化,因为有一个术语查询保证只考虑具有 id 并且存在于地图中的文档。如果不是这种情况,则应处理缺少 xId 和 map 中缺少 key 的情况。
    2. 您应该小心使用类型。实际上,当您从存储的文档中检索字段时,会使用索引类型检索它,例如,xId 存储为 long 并检索为 long。在第二个示例中,映射是从字符串到双精度的,因此 xId 在用作映射中的键之前会转换为字符串。

    【讨论】:

      猜你喜欢
      • 2017-01-09
      • 2021-12-13
      • 2021-05-22
      • 1970-01-01
      • 1970-01-01
      • 2017-12-14
      • 1970-01-01
      • 1970-01-01
      • 2013-01-23
      相关资源
      最近更新 更多