【问题标题】:Elasticsearch sort alphabetically then numericallyElasticsearch 按字母顺序排序,然后按数字排序
【发布时间】:2016-06-04 14:10:49
【问题描述】:

我正在寻找一种优雅的方法来先按字母排序,然后再按数字排序。

我目前的解决方案是使用下一个排序脚本在数字前插入“~”,“~”按字典顺序在“z”之后:

"sort": {
  "_script":{
      "script" : "s = doc['name.raw'].value; n = org.elasticsearch.common.primitives.Ints.tryParse(s.split(' ')[0][0]); if (n != null) { '~' + s } else { s }",
      "type" : "string"
  }
 }

但我想知道是否有更优雅、或许更高效的解决方案。

输入:

ZBA ABC ...
ABC SDK ...
123 RIU ...
12B BTE ...
11J TRE ...
BCA 642 ...

期望的输出:

ABC SDK ...
BCA 642 ...
ZBA ABC ...
11J TRE ...
12B BTE ...
123 RIU ...

【问题讨论】:

    标签: sorting elasticsearch


    【解决方案1】:

    您可以在索引时使用利用pattern_replace character filter 的自定义分析器执行相同的操作。在索引时执行此操作比在搜索时为每个查询运行脚本排序更高效。

    它的工作原理与您的解决方案相同,即如果我们检测到一个数字,我们会在该值前面加上波浪号 ~,否则我们什么都不做,但我们会在索引时执行并索引结果name.sort 字段中的值。

    PUT /tests
    {
      "settings": {
        "analysis": {
          "char_filter": {
            "pre_num": {
              "type": "pattern_replace",
              "pattern": "(\\d)",
              "replacement": "~$1"
            }
          },
          "analyzer": {
            "number_tagger": {
              "type": "custom",
              "tokenizer": "keyword",
              "filter": [],
              "char_filter": [
                "pre_num"
              ]
            }
          }
        }
      },
      "mappings": {
        "test": {
          "properties": {
            "name": {
              "type": "string",
              "fields": {
                "sort": {
                  "type": "string",
                  "analyzer": "number_tagger",
                  "search_analyzer": "standard"
                }
              }
            }
          }
        }
      }
    }
    

    然后你就可以索引你的数据了

    POST /tests/test/_bulk
    {"index": {}}
    {"name": "ZBA ABC"}
    {"index": {}}
    {"name": "ABC SDK"}
    {"index": {}}
    {"name": "123 RIU"}
    {"index": {}}
    {"name": "12B BTE"}
    {"index": {}}
    {"name": "11J TRE"}
    {"index": {}}
    {"name": "BCA 642"}
    

    那么您的查询可以如下所示:

    POST /tests/_search
    {
      "sort": {
        "name.sort": "asc"
      }
    }
    

    你会得到的回应是:

    {
      "hits": {
        "hits": [
          {
            "_source": {
              "name": "ABC SDK"
            }
          },
          {
            "_source": {
              "name": "BCA 642"
            }
          },
          {
            "_source": {
              "name": "ZBA ABC"
            }
          },
          {
            "_source": {
              "name": "11J TRE"
            }
          },
          {
            "_source": {
              "name": "12B BTE"
            }
          },
          {
            "_source": {
              "name": "123 RIU"
            }
          }
        ]
      }
    }
    

    【讨论】:

    • 这个运气好吗?
    • 我喜欢在索引时进行更改,但没有比在数字前添加波浪号更聪明的解决方案了吗?这无法说服我。
    • 波浪号仅添加到您仅用于排序的字段中。字典排序就是这样。原始输入根本没有改变。该解决方案与您在索引时执行的解决方案相同,而不是在搜索时利用昂贵的脚本
    • 是的,我明白这一点,但我想找到另一种方法,而不是在数字前用波浪号 (~) 保存另一个字段
    • 我可以提供另一种计算排序号的解决方案,但是仍然需要添加另一个字段来进行排序,因为您想更改字典排序的工作方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    相关资源
    最近更新 更多