Elasticsearch如何排除指定及嵌套字段不参与搜索
Elasticsearch 搜索排除指定字段落地方案
Elasticsearch 完全支持无需全量枚举可搜索字段的排除匹配能力,你当前用的7.10版本即可直接落地,不需要强制升级。
方案1:零索引改动,查询端直接实现(灵活度最高)
ES 7.x 版本的multi_match、query_string查询原生支持字段通配符+排除语法,不需要提前改索引映射、不需要reindex存量数据,直接写查询即可满足需求,完全不用手动枚举50多个业务字段:
- 规则逻辑:用
*通配符匹配索引内所有可搜索字段,用-字段名/路径的格式指定要排除的字段,支持路径通配符 - 对应第一个需求(排除
Service_Sold下所有字段,其余字段正常搜索),查询写法如下:
GET _dev/_search { "query": { "multi_match": { "query": "Product ABC", "fields": ["*", "-Service_Sold.*"] } } }
- 对应第二个需求(仅排除
Service_Sold.Type嵌套子字段,保留同路径下其他字段可搜索),查询写法如下:
GET _dev/_search { "query": { "multi_match": { "query": "Product ABC", "fields": ["*", "-Service_Sold.Type"] } } }
注意点:如果索引中存在数值、日期等不需要参与全文搜索的字段,可以把通配符收窄为文本字段匹配规则,比如业务中文本字段统一带.text子字段的话,把*替换为*.text即可,日常业务场景直接用*不会有功能问题。
方案2:索引层预配置(性能最优,适合固定排除规则)
如果你的排除规则是固定的(比如所有搜索场景都不匹配Service_Sold下的字段),可以在索引映射层做一次配置,后续查询只需要搜单个自定义字段即可,性能比多字段通配符匹配高30%以上,后续新增业务字段也不需要改任何配置:
- 配置逻辑:通过动态模板自动给字段打规则,所有非排除字段的值自动拷贝到自定义的全量搜索字段
search_all,需要排除的字段设置为不拷贝、甚至直接设为不可索引 - 对应需求的映射配置样例:
PUT _dev { "mappings": { "dynamic_templates": [ { "skip_service_sold_all": { "path_match": "Service_Sold.*", "mapping": { "copy_to": "_none_" } } }, { "skip_service_sold_type": { "path_match": "Service_Sold.Type", "mapping": { "index": false, "copy_to": "_none_" } } }, { "auto_copy_to_search_all": { "match": "*", "mapping": { "copy_to": "search_all" } } } ], "properties": { "search_all": { "type": "text" } } } }
配置完成后重建索引导入存量数据,后续查询直接匹配search_all字段即可,不需要关心字段增减、不需要写排除规则:
GET _dev/_search { "query": { "match": { "search_all": "Product ABC" } } }
不管Service_Sold是默认object类型还是nested嵌套类型,上述两个方案的路径匹配规则都能正常生效,不需要额外适配。
之前了解到的白名单、手动枚举excludes的方案维护成本高,核心是没用到ES原生的通配符、动态模板能力,这两个方案都不需要手动维护全量字段列表,新增业务字段会自动适配规则。
内容的提问来源于stack exchange,提问作者deepak prem
相关产品推荐
相关产品推荐

