ElasticSearch 6.8.22如何查询数组对象中同时匹配多条件的文档
Elasticsearch 6.8.22 对象数组查询解决方案
1. 匹配单个数组对象多条件(无需nested类型)
由于Elasticsearch会扁平化对象数组,默认的多字段匹配会跨元素生效。不用nested类型的话,有两种可行方案:
方案一:Painless脚本查询
直接遍历数组元素,检查是否存在同时满足country:fr和valid:yes的对象:
{ "query": { "bool": { "filter": { "script": { "script": { "source": "doc['papers.country'].values.stream().anyMatch(country -> { int idx = doc['papers.country'].values.indexOf(country); return country == 'fr' && doc['papers.valid'].values.get(idx) == 'yes'; })", "lang": "painless" } } } } } }
- 逻辑:遍历
papers.country的所有值,找到等于fr的位置,再验证对应位置的valid是否为yes,只要存在一个符合的元素就匹配。 - 注意:数组元素过多时性能会下降,适合小规模数组场景。
方案二:索引时预处理组合字段
在写入数据时,给每个papers对象生成一个组合字段(比如papers_combined,值为{country}_{valid}),比如Amy的papers会生成fr_no和us_yes两个值。查询时直接匹配组合值:
{ "query": { "match": { "papers_combined": "fr_yes" } } }
- 优势:性能最优,查询逻辑简单。
- 劣势:需要在数据写入阶段额外维护这个字段,适合写入频率低或可以批量处理的场景。
2. 检查数组中所有对象均符合条件
你提到的“所有idcard类型证件均为有效”需求,同样可以用脚本查询实现:
{ "query": { "bool": { "filter": { "script": { "script": { "source": "doc['papers.type'].values.stream().allMatch(type -> { int idx = doc['papers.type'].values.indexOf(type); return type != 'idcard' || doc['papers.valid'].values.get(idx) == 'yes'; })", "lang": "painless" } } } } } }
- 逻辑:遍历所有papers类型,只要是
idcard类型的元素,对应位置的valid必须为yes;非idcard类型不做限制。
如果要求所有papers对象(无论类型)都满足valid:yes,脚本可以简化为:
{ "query": { "bool": { "filter": { "script": { "script": { "source": "doc['papers.valid'].values.stream().allMatch(valid -> valid == 'yes')", "lang": "painless" } } } } } }
内容的提问来源于stack exchange,提问作者arso
相关产品推荐
相关产品推荐

