ElasticSearch能否过滤文档数组对象?检索指定文档并筛选子数组
问题描述
现有如下ElasticSearch文档:
[ { "id": 1, "vehicle": "car", "equipment": [ { "v_id": 11, "gps": false, "color": "yellow" } ] }, { "id": 2, "vehicle": "bus", "equipment": [ { "v_id": 34, "gps": false, "color": "red" }, { "v_id": 99, "gps": false, "color": "yellow" }, { "v_id": 10, "gps": true, "color": "red" } ] } ]
请问能否检索出所有vehicle为car和bus的文档,同时过滤equipment数组,仅保留其中gps: true的元素?预期结果如下:
[ { "id": 1, "vehicle": "car", "equipment": [] }, { "id": 2, "vehicle": "bus", "equipment": [ { "v_id": 10, "gps": true, "color": "red" } ] } ]
解决方案
可以实现,分两种场景处理,取决于equipment字段的映射类型:
场景1:equipment为默认object类型
如果equipment是默认的object类型(数组会被扁平化存储),直接用script_fields过滤数组元素,配合terms查询筛选目标vehicle:
POST /your_index/_search { "query": { "terms": { "vehicle": ["car", "bus"] } }, "script_fields": { "id": {"script": "params._source.id"}, "vehicle": {"script": "params._source.vehicle"}, "equipment": { "script": """ def filtered = []; for (item in params._source.equipment) { if (item.gps == true) { filtered.add(item); } } return filtered; """ } }, "_source": false }
该请求会直接返回过滤后的equipment数组,完全符合预期格式。
场景2:equipment为nested类型(推荐)
如果equipment被映射为nested类型(处理数组对象的最优方式),用nested查询结合inner_hits获取匹配元素,再在客户端组装成预期格式:
POST /your_index/_search { "query": { "bool": { "must": [ {"terms": {"vehicle": ["car", "bus"]}} ], "should": [ { "nested": { "path": "equipment", "query": {"term": {"equipment.gps": true}}, "inner_hits": {} } } ] } }, "_source": ["id", "vehicle"] }
返回结果中,匹配的文档会包含inner_hits.equipment.hits.hits字段,里面是符合gps: true的元素。客户端只需将这些元素合并到equipment字段,无匹配项则设为空数组即可。
注意事项
- 大数据量场景下,优先使用
nested类型方案,script_fields的脚本执行性能会随数据规模下降。 - 使用
script_fields时,需确保Elasticsearch配置中开启了inline脚本支持。
内容的提问来源于stack exchange,提问作者Smk
相关产品推荐
相关产品推荐

