繁体   English   中英

ElasticSearch 如何按给定的 idList 排序

[英]ElasticSearch how to sort by a giving idList

我有一个要查询的参数列表,我想按此参数列表顺序获取结果排序

在 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]?}

感谢您的任何建议。

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

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

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];

显然,您可以通过直接将 map 作为参数传递给此处报告的脚本来提高性能。

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

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"
    }
  }
}

使用 map 方法的完整示例

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 并且存在于 map 中的文档。 如果不是这种情况,则应处理 map 中缺少 xId 和缺少密钥的情况。
  2. 你应该小心类型。 实际上,当您从存储的文档中检索字段时,会使用索引类型检索它,例如,xId 存储为 long 并检索为 long。 在第二个示例中,map 是从字符串到双精度,因此在将 xId 用作 map 中的键之前将其转换为字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM