求助:Node.js中Mongoose graphLookup的正确使用语法
Mongoose graphLookup 实现递归查询的正确用法
先修正你的代码问题
你的代码存在两个核心问题:
- 集合名称不匹配:Mongoose默认会把模型名转为小写复数形式作为集合名,比如
UserTree模型对应的默认集合是usertrees,而非你写的user_tree。如果你的集合确实叫user_tree,需要在模型定义时显式指定collection: 'user_tree'。 - 缺少初始匹配逻辑:直接对全集合执行graphLookup会为每一条文档生成递归结果,通常我们需要先定位到特定起始文档,再执行递归查询。
正确实现示例
假设你要查询userid: "MongoDB"的所有上级依赖链(Databases→Programming→Books),代码如下:
const UserTree = require('./model/usertree'); // 完整聚合查询逻辑 const trees = await UserTree.aggregate([ // 先匹配起始文档 { $match: { userid: "MongoDB" } }, // 执行递归查询 { $graphLookup: { from: 'user_tree', // 确保这里是你的实际集合名称 startWith: '$userpid', // 从当前文档的userpid开始递归 connectFromField: 'userpid', // 递归时传递的字段 connectToField: 'userid', // 目标集合中用于匹配的字段 as: 'prerequisites', // 结果存储的字段名 maxDepth: 3, // 最大递归深度 depthField: 'depth' // 可选:添加字段标识节点的递归层级 } } ]); console.log(trees);
预期输出
基于你的示例文档,上述代码会返回:
[ { userid: "MongoDB", userpid: "Databases", prerequisites: [ { userid: "Databases", userpid: "Programming", depth: 0 }, { userid: "Programming", userpid: "Books", depth: 1 }, { userid: "Books", userpid: null, depth: 2 } ] } ]
关键参数说明
from: 必须是MongoDB中的实际集合名称,不是Mongoose模型名。startWith: 递归的起始值,用$引用当前文档的字段。connectFromField: 递归过程中,用来传递到下一次查询的字段。connectToField: 目标集合中用来匹配的字段,建立递归关联。maxDepth: 限制递归的最大层级,避免无限递归。depthField: 可选参数,添加后会在结果中显示每个节点的递归深度(从0开始计数)。
如果要查询所有文档的递归结果
若不需要指定起始文档,直接对全集合执行graphLookup,去掉$match阶段即可:
const trees = await UserTree.aggregate([ { $graphLookup: { from: 'user_tree', startWith: '$userpid', connectFromField: 'userpid', connectToField: 'userid', as: 'prerequisites', maxDepth: 3 } } ]);
内容的提问来源于stack exchange,提问作者Allex
相关产品推荐
相关产品推荐

