MongoDB嵌套文档中$graphLookup聚合仅返回单文档的问题排查
MongoDB $graphLookup处理嵌套文档结果异常的解决方案
问题场景
使用MongoDB聚合框架的$graphLookup阶段处理嵌套结构文档时,出现结果不符合预期的问题:
- 非嵌套模式下,
$graphLookup能正确返回所有符合配置的文档 - 嵌套模式下,仅返回空的
nest数组,尝试$unwind和$replaceRoot后仍未解决
非嵌套正常示例
文档结构
db={ "fileSystem": [ { "_id": "a", "label": "Root", "children": ["b"], }, { "_id": "b", "label": "Nested folder 1", "children": ["c","d","e"], "parent": "a" }, { "_id": "c", "label": "Nested File 1.1", "parent": "b" }, { "_id": "d", "label": "Nested File 1.2", "parent": "b" } ] }
聚合查询
db.fileSystem.aggregate([ {"$match": {"_id": "a"}}, { "$graphLookup": { "from": "fileSystem", "startWith": "$children", "connectFromField": "children", "connectToField": "_id", "as": "nest", "depthField": "level", "maxDepth": 1 } } ])
正确结果
[ { "_id": "a", "children": ["b"], "label": "Root", "nest": [ {"_id": "b","children": ["c","d","e"],"label": "Nested folder 1","level": NumberLong(0),"parent": "a"}, {"_id": "d","label": "Nested File 1.2","level": NumberLong(1),"parent": "b"}, {"_id": "c","label": "Nested File 1.1","level": NumberLong(1),"parent": "b"} ] } ]
嵌套异常示例
文档结构
db={ "fileSystem": [ { pp: [ { "_id": "a", "label": "Root", "children": ["b"], }, // 其余内容与非嵌套示例一致 ] } ] }
错误聚合查询
db.fileSystem.aggregate([ {"$unwind": "$pp"}, {"$replaceRoot": {"newRoot": "$pp"}}, {"$match": {"_id": "a"}}, { "$graphLookup": { "from": "fileSystem", "startWith": "$pp.children", "connectFromField": "pp.children", "connectToField": "pp._id", "as": "nest", "depthField": "level" } } ])
错误结果
[ { "_id": "a", "children": ["b"], "label": "Root", "nest": [] } ]
问题原因与解决方案
错误原因
$replaceRoot之后,当前文档已经是pp数组中的节点,不存在$pp.children字段,应该直接使用$children$graphLookup的from指向fileSystem集合,但该集合的文档嵌套在pp数组中,直接查询无法匹配到_id和children字段
正确聚合查询
需要在$graphLookup的pipeline中先对from集合的文档进行$unwind和$replaceRoot处理,将嵌套的pp数组展开为根节点:
db.fileSystem.aggregate([ {"$unwind": "$pp"}, {"$replaceRoot": {"newRoot": "$pp"}}, {"$match": {"_id": "a"}}, { "$graphLookup": { "from": "fileSystem", "startWith": "$children", "connectFromField": "children", "connectToField": "_id", "as": "nest", "depthField": "level", "maxDepth": 1, "pipeline": [ {"$unwind": "$pp"}, {"$replaceRoot": {"newRoot": "$pp"}} ] } } ])
执行结果
将返回与非嵌套模式一致的正确结果,包含所有关联的子节点。
内容的提问来源于stack exchange,提问作者Nugget
相关产品推荐
相关产品推荐

