ElasticSearch中text字段的Painless过滤脚本无法运行问题
如何在Painless脚本中访问未启用fielddata的text字段实现精确匹配
问题背景
需在Elasticsearch中通过Painless脚本实现text字段的精确匹配过滤,但该字段未启用fielddata且无法修改映射。尝试使用doc['my_field'] == 'MY_VALUE'时触发错误,提示找不到目标字段。
索引映射(不可修改)
{ "my_index": { "aliases": {}, "mappings": { "properties": { "my_field": { "type": "text" } } }, "settings": { "index": { "max_ngram_diff": "60", "number_of_shards": "8", "blocks": { "read_only_allow_delete": "false", "write": "false" }, "analysis": {...} } } } }
原查询及错误
原查询尝试结合match_phrase与脚本过滤:
{ "size": 10, "index": "my_index", "body": { "query": { "bool": { "should": [{ "match_phrase": { "my_field": { "query": "MY_VALUE", "boost": 1.5, "slop": 0 } } }], "must": [], "filter": [{ "script": { "script": { "lang": "painless", "source": "doc['my_field'] == 'MY_VALUE'" } } }], "minimum_should_match": 1 } } } }
错误信息:
{ "error": { "root_cause": [ { "type": "script_exception", "reason": "runtime error", "script_stack": [ "org.opensearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:101)", "org.opensearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:53)", "doc['my_field'] === 'MY_VALUE'", " ^---- HERE" ], "script": "doc['my_field'] === 'MY_VALUE'", "lang": "painless", "position": { "offset": 4, "start": 0, "end": 30 } } ], "type": "search_phase_execution_exception", "reason": "all shards failed", "phase": "query", "grouped": true, "failed_shards": [ { "shard": 0, "index": "my_index", "node": "R99vOHeORlKsk9dnCzcMeA", "reason": { "type": "script_exception", "reason": "runtime error", "script_stack": [ "org.opensearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:101)", "org.opensearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:53)", "doc['my_field'] === 'MY_VALUE'", " ^---- HERE" ], "script": "doc['my_field'] === 'MY_VALUE'", "lang": "painless", "position": { "offset": 4, "start": 0, "end": 30 }, "caused_by": { "type": "illegal_argument_exception", "reason": "No field found for [my_field] in mapping with types []" } } } ] }, "status": 400 }
原因分析
doc对象仅能访问带有doc values或fielddata的字段,而text类型字段默认不启用这两者,且无法修改映射开启,因此无法通过doc访问。
解决方案
改用_source对象直接获取原始字段值进行匹配,_source存储了文档的原始内容,无需额外配置。修改后的查询如下:
{ "size": 10, "index": "my_index", "body": { "query": { "bool": { "should": [{ "match_phrase": { "my_field": { "query": "MY_VALUE", "boost": 1.5, "slop": 0 } } }], "must": [], "filter": [{ "script": { "script": { "lang": "painless", "source": "_source.my_field == 'MY_VALUE'" } } }], "minimum_should_match": 1 } } } }
注意事项
- 使用
_source的性能略低于doc,因为需要加载整个文档的原始数据,但在无法修改映射的场景下是可行的替代方案。 - 确保
_source字段未被禁用(默认启用),否则此方法无法生效。
内容的提问来源于stack exchange,提问作者Paolo Magnani
相关产品推荐
相关产品推荐

