如何优化Elasticsearch 6.8.x天文对象编码查询与自动补全排序
问题解决方案
你遇到的两个问题本质都是字符串字典序与自然数字序不匹配,可通过预处理字段+统一排序规则解决:
1. 自然排序优化
当前keyword类型排序走ASCII字典序,逐字符比较时会将m10排在m2前,推荐优先使用预处理字段方案,查询性能无额外损耗:
方案1:新增预处理字段(推荐)
- 先修改mapping新增两个字段,写入时拆分编码的前缀和数字部分分别存储:
{ "mappings": { "_doc": { "properties": { // 编码前缀,取值为m/ngc等 "code_prefix": { "type": "keyword", "normalizer": "lowercase_normalizer" }, // 编码数字部分,取值为1/10/101等 "code_num": { "type": "integer" } } } } }
- 排序时指定先按前缀排序、再按数字排序即可得到预期顺序:
{ "sort": [ {"code_prefix": {"order": "asc"}}, {"code_num": {"order": "asc"}} ] }
方案2:脚本临时排序(仅适合小数据量场景)
如果不想修改写入逻辑,可使用painless脚本动态提取数字排序,大数据量下性能较低:
{ "sort": { "_script": { "type": "number", "script": { "lang": "painless", "source": "def m = /^([a-z]+)(\\d+)$/.matcher(doc['id.raw'].value); return m.matches() ? Integer.parseInt(m.group(2)) : 0;" }, "order": "asc" } } }
2. 自动补全查询优化
当前使用phrase_prefix查询时默认按匹配度评分,前缀更长的匹配项评分更高,才会出现m103排在m10前的问题,可复用上文的排序规则统一解决:
- 若要优先展示完全匹配的结果,可给精确匹配项增加权重:
{ "query": { "bool": { "should": [ { "multi_match" : { "query": "m10", "fields": [ "id", "id.raw^10", "desigs"], "type": "phrase_prefix" } }, { "term": { "id.raw": { "value": "m10", "boost": 100 } } } ] } }, // 复用上面的自然排序规则 "sort": [ {"code_prefix": {"order": "asc"}}, {"code_num": {"order": "asc"}} ] }
如果要更高的补全查询性能,可直接使用你已定义的completion类型suggest字段,写入时将code_num作为权重值绑定,数字越小权重越高,即可直接返回符合顺序的补全结果。
内容的提问来源于stack exchange,提问作者Astro-Otter
相关产品推荐
相关产品推荐

