Elasticsearch带点通配符查询返回无点结果的异常问题
问题排查与解决方案
让我们一步步拆解你的问题:
首先搞清楚核心矛盾
你的val字段是long类型(仅存储整数),但查询结果里却出现了带点的数值,这本身就说明数据或映射存在异常。先看你的映射:
"val": { "type": "long", "fields": { "keyword": { "type": "keyword" } } }
这个映射下,val.keyword应该只存储整数的字符串形式(比如123存为"123"),理论上不会出现带点的值。出现带点的数值,大概率是以下两种情况:
- 你在设置这个映射之前,已经存入了带小数的数据,当时Elasticsearch自动创建了text类型的映射,这些旧数据的字符串形式(比如
"123.45")还留在索引里; - 你的字段开启了
ignore_malformed: true,导致存入的浮点数被强制转成long(丢失小数),但某些场景下字符串转换出现了异常。
为什么你的wildcard查询不符合预期?
1. *.*匹配到不带点的数值
这要么是你误解了结果(比如某些数值被存成了科学计数法,比如"1e+06",它是带点的),要么是查询结果里的"不带点数值"其实是旧数据的残留,或者你的查询被其他条件干扰了。
先验证val.keyword的实际存储值,执行这个查询看10条样本:
GET /ind/_search { "size": 10, "_source": ["val.keyword"] }
你就能看到这些"不带点数值"的真实字符串形式,大概率能找到原因。
2. */.*无法匹配带点的数值
这个很简单:/在wildcard查询里是普通字符,不是通配符。*/.*的意思是"任意字符 + / + . + 任意字符",自然匹配不到带点的数值(比如"123.45"里没有/)。
解决步骤
第一步:清理异常数据
先找出所有val.keyword包含点的文档,确认这些数据是否是合法的:
GET /ind/_search { "query": { "script": { "script": "doc['val.keyword'].value.contains('.')" } } }
如果这些是错误数据(比如应该是整数),要么修正为long类型的整数,要么直接删除这些文档。如果确实需要存储小数,把val字段类型改为double或float,并更新映射。
第二步:正确匹配带点的数值
如果确认val.keyword里确实存在合法的带点字符串(比如修正映射后存入的小数),用以下查询即可精准匹配:
GET /ind/_search { "query": { "wildcard" : { "val.keyword": "*.*" } } }
如果要排除不带点的整数字符串,可以结合bool查询:
GET /ind/_search { "query": { "bool": { "must": [{"wildcard": {"val.keyword": "*.*"}}], "must_not": [{"regexp": {"val.keyword": "^[0-9]+$"}}] } } }
这里用regexp更精准,确保排除纯数字的字符串。
内容的提问来源于stack exchange,提问作者Alexey Semenyuk
相关产品推荐
相关产品推荐

