Elasticsearch 7中如何忽略number_format_exception查询错误?
嗨,我之前也碰到过一模一样的情况!Elasticsearch对数字类型字段的类型校验很严格,当你给long类型的字段传字符串查询时,确实会直接抛出number_format_exception。不过根据你的需求(要么返回空结果,要么跳过过滤条件),这里有几个可行的方案:
方案1:跳过过滤条件(返回所有文档)
使用query_string查询并开启lenient参数,这个参数的作用是当Elasticsearch无法将查询值转换为对应字段类型时,会自动忽略该查询条件,直接返回所有文档。
请求示例:
POST /my_index/_search { "query": { "query_string": { "default_field": "sequence_number", "query": "we", "lenient": true } } }
当输入"we"这种无法转为long的字符串时,这个查询会跳过对sequence_number的过滤,直接返回索引里的所有文档,完美符合你“跳过过滤条件”的需求。
方案2:返回空结果
如果你希望遇到非数字输入时直接返回空结果,可以用bool查询结合脚本验证输入是否为有效数字。脚本会尝试将输入值转为long,失败则返回false,让整个查询没有匹配结果。
请求示例:
POST /my_index/_search { "query": { "bool": { "must": [ { "term": { "sequence_number": { "value": "we" } } }, { "script": { "script": { "source": "try { Long.parseLong(params.input); return true; } catch (Exception e) { return false; }", "params": { "input": "we" } } } } ] } } }
⚠️ 注意:这个方案需要你的Elasticsearch集群允许使用inline脚本,如果集群禁用了inline脚本,你需要将脚本保存为文件脚本或者调整集群的脚本权限配置。
方案3:从映射层面彻底解决(推荐)
如果这种类型不匹配的查询是高频场景,建议给sequence_number字段添加一个keyword类型的子字段,这样不管输入是数字还是字符串,都能找到对应的查询字段,从根源避免报错。
首先更新字段映射:
PUT /my_index/_mapping { "properties": { "sequence_number": { "type": "long", "copy_to": ["_custom_all"], "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }
之后在应用层做一个简单判断:如果输入是数字,就查询sequence_number(long类型);如果是字符串,就查询sequence_number.keyword(keyword类型)。这样既不会报错,查询效率也更高。
内容的提问来源于stack exchange,提问作者Prakash Panjwani

