按字母顺序然后按数字顺序排序的 Elasticsearch

3

我希望找到一种优雅的方式,首先按字母顺序排序结果,然后按数字排序。

我的当前解决方案是使用下一个排序脚本在数字前插入“~”,“~”在字母“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 ...
1个回答

3
您可以使用自定义分析器在索引时执行相同的操作,该分析器利用pattern_replace字符过滤器。与为每个查询运行脚本排序相比,将其放在索引中执行更加高效。
它的工作方式与您的解决方案相同,即如果我们检测到一个数字,我们会在值前面添加一个波浪符号~,否则我们不做任何操作,但我们是在索引时执行,并将结果值索引到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"
        }
      }
    ]
  }
}

我喜欢在索引时间进行更改,但是在数字前添加波浪符号没有比这更聪明的解决方案吗?这并不能说服我。 - dimartiro
因为我认为这只是一个补丁,我相信一定有更好的方法来达到相同的结果。 尽管如此,你的解决方案似乎比我的好得多。 - dimartiro
1
我可以提供另一种解决方案,它可以找出排序号码,但仍需要添加另一个字段用于排序,因为您想改变词典排序的方式。 - Val
既然你已经准备好使用添加波浪符号的脚本排序,我认为这已经是一个足够好的解决方案了。你应该更清楚地说明你知道这是一个大型黑客,并且想要以某种方式改变词典排序的工作方式。 - Val
你对于为了排序目的而添加另一个字段的想法感到满意吗? - Val
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接