如何在Elasticsearch的long类型字段上执行通配符查询?
解决Elasticsearch long类型字段通配符查询报错的方法
无需修改索引的临时方案
直接通过脚本将数值字段转为字符串进行匹配,不需要改动现有索引结构,但注意大数据量下性能较差,适合低频查询场景:
包含特定字符串的查询
GET calls-*/_search { "query": { "bool": { "filter": [ { "script": { "script": { "source": "doc['foo.number'].value.toString().contains('16922')", "lang": "painless" } } } ] } } }
通用通配符匹配
如果需要更灵活的通配符(比如*16922*),可以用正则匹配:
GET calls-*/_search { "query": { "bool": { "filter": [ { "script": { "script": { "source": "doc['foo.number'].value.toString().matches('.*16922.*')", "lang": "painless" } } } ] } } }
必须修改索引的长期优化方案
如果查询频率较高,建议给目标字段添加多字段(multi-field),保留原long类型字段不影响业务,同时新增text类型子字段用于字符串匹配:
1. 更新索引映射
给foo.number字段添加text类型的子字段:
PUT calls-*/_mapping { "properties": { "foo": { "properties": { "number": { "type": "long", "fields": { "text": { "type": "text" } } } } } } }
2. 重新索引数据
旧数据不会自动生成子字段的值,需要通过_reindex API同步数据(可以创建新索引或者覆盖原有索引,根据生产环境情况选择):
POST _reindex { "source": { "index": "calls-*" }, "dest": { "index": "calls-reindexed-*" } }
3. 使用子字段执行查询
之后就可以用新增的text子字段做通配符查询,性能和常规text字段一致:
GET calls-reindexed-*/_search { "query": { "bool": { "filter": [ { "query_string": { "default_field": "foo.number.text", "query": "*16922*" } } ] } } }
内容的提问来源于stack exchange,提问作者heymynameisfoo
相关产品推荐
相关产品推荐

