ES6技术问询:如何通过AND运算符将子查询关联至不同行
在Elasticsearch 6中实现跨不同行的AND关联查询
嘿,我明白你的场景了——你用的是EAV(实体-属性-值)模式存储数据,每个文档对应实体的一个属性行,现在需要查询同一个oid同时满足多个不同tag-value条件的实体对吧?这种跨文档的AND关联在ES里确实不能用常规的行内查询直接实现,我给你两种实用的解决方案:
方法一:基于现有扁平结构的聚合筛选法
如果暂时不想修改索引结构,我们可以先检索所有匹配任一条件的文档,再通过聚合筛选出同时满足所有条件的oid,最后按需获取完整数据。
第一步:查询并聚合筛选符合条件的oid
{ "query": { "bool": { "should": [ // 第一个条件:tag=t1且value=aaa { "bool": { "must": [ {"term": {"tag": "t1"}}, {"term": {"value": "aaa"}} ] } }, // 第二个条件:tag=t2且value=bbb { "bool": { "must": [ {"term": {"tag": "t2"}}, {"term": {"value": "bbb"}} ] } } ], "minimum_should_match": 1 // 只要满足任一条件的文档都被纳入 } }, "aggs": { "group_by_oid": { "terms": { "field": "oid", "min_doc_count": 2 // 因为有2个条件,所以需要该oid至少匹配2个文档(每个条件对应一个) } } } }
执行这个查询后,aggregations.group_by_oid.buckets里的就是同时满足两个条件的oid列表。
第二步:获取这些oid的完整属性数据
拿到符合条件的oid后,再发起一个查询就能获取对应的所有属性文档:
{ "query": { "terms": {"oid": [1]} // 替换成聚合得到的oid列表 } }
方法二:重构为嵌套类型(推荐长期方案)
如果可以调整索引结构,把每个实体的所有属性存为嵌套对象会让这类查询更高效、更直观。
修改映射
"mappings": { "document": { "_all": {"enabled": false}, "properties": { "oid": {"type": "integer"}, "attributes": { "type": "nested", // 标记为嵌套类型 "properties": { "tag": {"type": "text"}, "value": {"type": "text"} } } } } }
调整数据结构
每个文档对应一个完整的实体:
{ "oid": 1, "attributes": [ {"tag": "t1", "value": "aaa"}, {"tag": "t2", "value": "bbb"} ] }
执行跨属性的AND查询
现在用nested查询就能直接实现需求,每个nested子查询独立检查一个属性条件,多个nested条件的AND就表示实体同时满足所有要求:
{ "query": { "bool": { "must": [ { "nested": { "path": "attributes", "query": { "bool": { "must": [ {"term": {"attributes.tag": "t1"}}, {"term": {"attributes.value": "aaa"}} ] } } } }, { "nested": { "path": "attributes", "query": { "bool": { "must": [ {"term": {"attributes.tag": "t2"}}, {"term": {"attributes.value": "bbb"}} ] } } } } ] } } }
内容的提问来源于stack exchange,提问作者Save
相关产品推荐
相关产品推荐

