在排序之前映射字段的值

时间:2017-05-01 18:29:35

标签: elasticsearch

我想使用包含customer_priorityIMMEDIATEHIGHMEDIUM值的字段LOW在ElasticSearch中对数据进行排序。

由于按字母顺序排序,我收到以下不受欢迎的排序:HIGHIMMEDIATELOWMEDIUM。但我希望:LOWMEDIUMHIGHIMMEDIATE

如何指示ElasticSearch以任意方式排序?

我调查过的一些事情:

  • 我看到你的查询中有一些名为custom scoring functions的东西,但它实际上是要走的路吗?我想要一些我可以放在映射中的东西而不是查询。
  • 更改实际存储的值,因此它是一个数字而不是字符串:我想暂时避免这种情况,这需要对我们的系统进行重大更改。

BTW:我正在使用ES 2.3

1 个答案:

答案 0 :(得分:1)

脚本基础排序是主要选项,但它有几个缺点。请参阅this documentation for how to sort with a script(我假设您目前正在使用最新的ES版本5.3)。

您可以为您的案例添加类似的内容:

"sort" : {
    "_script" : {
        "type" : "number",
        "script" : {
            "lang": "painless",
            "inline": "def val = doc['customer_priority'].value;                           
                       if (val == 'LOW') { return 0;} 
                       if (val == 'MEDIUM') {return 1;} 
                       if (val == 'HIGH') {return 2;} 
                       if (val == 'IMPORTANT') {return 3;}"
        },
        "order" : "asc"
    }
}

注意:我没有测试此代码示例。

缺点是您需要在映射中为此字段customer_priority启用fielddata,这将增加您的内存需求。默认情况下不启用它。但幸运的是,这个领域的基数很小(只有4个值)所以开销很小。另一个缺点是脚本排序很慢,因为脚本需要在每个文档上运行。

另一个选项可能是通过添加customer_priority的数字字段来进一步对customer_priority_sort进行非规范化,其值为1,2,3或4,并映射到LOW,{{ 1}},MEDIUMHIGH这样您就可以对此值进行排序而不是字符串。

你必须保持字段同步,如果它们发生了变化,这是额外的开销,但你可能对结果感到满意,并且只是为这些枚举值存储一个整数,而不是直接存储更多磁盘的字符串无论如何都很有效率。

编辑:对于ES 2.3,groovy是首选的脚本语言,因此您可能必须更新上面的IMPORTANT代码示例,但方法是相同的。基于脚本的排序在2.3和5.3中支持相同,请参阅the docs