如何在Elasticsearch中用query_string同时匹配嵌套与非嵌套字段
解决方案
方案1:无需修改现有Mapping(推荐)
Elasticsearch 6.8版本中query_string本身不支持直接跨根字段和嵌套字段检索,你可以通过bool查询组合嵌套查询和外层普通查询实现需求,两者内部都可以使用query_string保留语法灵活性,查询DSL示例如下:
{ "query": { "bool": { "must": [ { "nested": { "path": "email", "query": { "query_string": { "fields": ["email.to", "email.from", "email.subject"], "query": "email.to:foo@example.com" } } } }, { "query_string": { "fields": ["textExact"], "query": "textExact:bar" } } ] } } }
说明:nested查询指定路径为email,专门处理所有嵌套字段的检索逻辑,外层query_string处理根层级的非嵌套字段,bool.must保证两个条件同时生效,完全匹配你期望的查询逻辑。如果需要支持用户输入整段原生查询语句,只需要提前做简单的语法解析,把涉及嵌套路径的条件和根路径条件拆分到对应子查询即可。
方案2:修改Mapping简化后续查询
如果你频繁需要做这类混合检索,也可以通过copy_to参数把嵌套字段内容同步到根层普通字段,之后就可以直接用单条query_string查询所有字段。
调整后的Mapping示例:
"email" : { "type" : "nested", "properties" : { "from" : { "type" : "text", "analyzer" : "lowercase_keyword", "fielddata" : true, "copy_to": "email_from_root" }, "subject" : { "type" : "text", "analyzer" : "lowercase_keyword", "fielddata" : true, "copy_to": "email_subject_root" }, "to" : { "type" : "text", "analyzer" : "lowercase_keyword", "fielddata" : true, "copy_to": "email_to_root" } } }, "textExact" : { "type" : "text", "analyzer" : "lowercase_standard", "fielddata" : true }, "email_from_root": { "type" : "text", "analyzer" : "lowercase_keyword", "fielddata" : true }, "email_subject_root": { "type" : "text", "analyzer" : "lowercase_keyword", "fielddata" : true }, "email_to_root": { "type" : "text", "analyzer" : "lowercase_keyword", "fielddata" : true }
简化后的查询示例:
"query": { "query_string": { "fields": [ "textExact", "email_to_root" ], "query": "email_to_root:foo@example.com AND textExact:bar" } }
注意:该方案会额外占用磁盘存储空间,且无法保留嵌套文档的关联约束(比如无法判断email.to和email.from属于同一个嵌套对象),如果有这类关联查询需求请优先使用方案1。
内容的提问来源于stack exchange,提问作者ThisSuitIsBlackNot
相关产品推荐
相关产品推荐

