ElasticSearch:嵌套对象数组的高级搜索实现方案咨询
问题描述
假设Elasticsearch中存储了如下文档:
[ { "id": "349dec5f-4ddf-4faa-beb0-79a0ea08bad6", "name": "Iphone 13", "criteria": [ { "name": "color", "options": ["Midnight", "Blue", "Green"] } ] }, { "id": "1a63de5a-4335-4e0d-83ab-c820d57709bd", "name": "IPhone 14", "criteria": [ { "name": "color", "options": ["Midnight", "Purple", "Red"] }, { "name": "size", "options": ["128GB", "256GB"] } ] }, { "id": "eae5672f-2153-4f7d-be68-122e6d9fe5e1", "name": "Iphone 14 Pro", "criteria": [ { "name": "color", "options": ["Black", "Blue", "Red"] }, { "name": "size", "options": ["64GB", "128GB", "256GB"] } ] } ]
文档的类型映射如下:
{ "properties": { "id": { "type": "keyword", "ignore_above": 36 }, "name": { "type": "text" }, "category": { "type": "keyword", "ignore_above": 36 }, "criteria": { "type": "nested", "properties": { "name": { "type": "keyword", "ignore_above": 500 }, "options": { "type": "keyword", "ignore_above": 500 } } } } }
其中criteria为嵌套对象数组,包含criteria.name和criteria.options字段,可存储color、size之外的其他值。
现在需要根据HTTP请求中的filter对象筛选文档,示例请求中的filter参数如下:
{ "search": null, "filter": { "criteria": [ { "name": "color", "options": ["Blue", "Red"], "operator": "OR" }, { "name": "size", "options": ["64GB", "128GB"], "operator": "OR" } ] } }
筛选逻辑为:
文档需同时满足:
- 存在
criteria.name为color的嵌套对象,且其options包含Blue或Red- 存在
criteria.name为size的嵌套对象,且其options包含64GB或128GB
按此条件应返回IPhone 14和Iphone 14 Pro两个文档,如何在Elasticsearch中实现该需求?
解决方案
由于criteria是nested类型,普通查询无法正确关联嵌套对象内的字段,必须使用nested查询确保每个条件作用于同一个嵌套对象实例。我们可以通过外层bool.must组合多个nested查询,实现“同时满足多个筛选维度”的逻辑,每个nested查询对应一个筛选条件(color或size)。
对应的Elasticsearch查询DSL如下:
{ "query": { "bool": { "must": [ // 处理color筛选条件 { "nested": { "path": "criteria", "query": { "bool": { "must": [ { "term": { "criteria.name": "color" } }, { "terms": { "criteria.options": ["Blue", "Red"] } } ] } } } }, // 处理size筛选条件 { "nested": { "path": "criteria", "query": { "bool": { "must": [ { "term": { "criteria.name": "size" } }, { "terms": { "criteria.options": ["64GB", "128GB"] } } ] } } } } ] } } }
逻辑说明:
- 外层
bool.must:确保两个nested查询的条件同时满足,对应需求中的“color条件且size条件”。 - 每个
nested查询:指定path为criteria,确保查询只作用于单个嵌套对象。term查询匹配criteria.name,锁定要筛选的维度(color或size)。terms查询匹配criteria.options,该查询本身就是OR逻辑,正好对应“options包含任意指定值”的要求。
动态生成查询思路:
如果需要根据前端传入的filter参数动态生成DSL,只需遍历filter中的每个criteria项,为每个项生成对应的nested查询块,再将所有块放入外层bool.must数组即可。
内容的提问来源于stack exchange,提问作者Mykyta Manuilenko
相关产品推荐
相关产品推荐

