Elasticsearch动态层级数据查询与树形结构构建方案咨询
针对你的Elasticsearch层级文档查询与树形结构构建问题
先给你明确答案:完全没问题可以构建仅返回目标树形关联文档的查询,下面是两种实用方案:
方案1:利用Join字段(官方推荐的父子层级建模方式)
如果你已经用Elasticsearch的join字段定义了文档间的父子关系,比如mapping是这样的:
{ "mappings": { "properties": { "relation": { "type": "join", "relations": { "base": "a", "a": ["b", "c"] } }, "id": {"type": "keyword"}, "parent": {"type": "keyword"} } } }
那你可以用一个bool查询一次性捞出所有关联base的文档:
{ "query": { "bool": { "should": [ // 匹配顶层base文档本身 {"term": {"id": "base"}}, // 匹配直接父为base的a类型文档 {"parent_id": {"type": "a", "id": "base"}}, // 匹配父是a且a的父为base的b/c类型文档 {"has_parent": { "parent_type": "a", "query": {"parent_id": {"type": "a", "id": "base"}} }} ] } } }
这个查询会精准返回base、a、b、c这四个文档,刚好是你需要的关联集合。
方案2:预处理祖先字段(深度层级下查询效率更高)
如果你的文档层级可能更深,用上面的嵌套查询会比较麻烦,建议在索引文档时,给每个文档加一个ancestors字段,把所有祖先的id都存进去:
- base文档:
"ancestors": [] - a文档:
"ancestors": ["base"] - b文档:
"ancestors": ["base", "a"] - c文档:
"ancestors": ["base", "a"] - d文档:
"ancestors": ["someotherbase"]
这时候查询就超简单了,直接用term匹配ancestors字段就行:
{ "query": { "term": {"ancestors": "base"} } }
这种方式不管层级有多深,都能一次查出所有关联文档,查询性能是最优的。
再说说第二个问题:Elasticsearch原生不会直接返回你想要的树形结构,但可以借助inner_hits快速拿到层级关联数据,再自己组装成树
比如用parent-join结合inner_hits,查询base文档时可以同时带出它的子文档,以及子文档的子文档:
{ "query": { "term": {"id": "base"} }, "inner_hits": { "children": { "type": "a", "inner_hits": { "children": { "type": ["b", "c"] } } } } }
这个查询的返回结果里,inner_hits会包含a类型的子文档,每个a文档的inner_hits又会包含对应的b/c子文档。你只需要基于这个结构,用代码递归组装就能得到目标树形JSON了。
不过要注意:Elasticsearch的inner_hits嵌套层级有一定限制,而且它不会自动帮你把数据拼成完整的树形结构,最终的结构组装还是得靠你自己写代码实现。
总结一下:
- 仅返回关联文档:完全可以,用Join字段的组合查询或者预处理祖先字段都能搞定
- 原生构建树形结构:Elasticsearch不直接支持,但可以通过
inner_hits获取层级关联数据,再自行组装
内容的提问来源于stack exchange,提问作者TheDude
相关产品推荐
相关产品推荐

