我有这样的数据集合(例如):
{ name : "john",_id : "0" },{ name : "Richard",parent_id : "0",_id : "1" },{ name : "Kevin",_id : "2" },{ name : "William",parent_id : "1",_id : "3" },{ name : "George",parent_id : "3",_id : "4" }
我正在尝试编写一个函数来接收_id并返回此节点任何深度的所有子节点,例如_id = 0我需要这样的东西:
[ { name : "Richard",depth : "1",_id : "1" },{ name : "Kevin",_id : "2" },{ name : "William",depth : "2",_id : "3" },{ name : "George",depth : "3",_id : "4" } ]
我写了几个递归函数来迭代我的mongodb文档但主要问题是我无法处理回调(异步)并且不知道何时以及如何结束递归函数.
我怎么能用mongodb和node.js做到这一点?
任何想法都有用,谢谢.
解决方法
您可以使用2种着名算法来实现目标
BFS(Breath First search)和 DFS(Depth First Search).
对于这个问题,BFS优于DFS,因为您可以在O(logn)中跟踪树
您也可以使用DFS但是必须以递归方式实现它,并且运行时间将是O(n)并且因为您在节点j中编码,所以必须在异步中实现它并且实现它可能有点困难.
为了实现BFS算法,你必须使用异步while循环,因为你必须在你的while循环中使用mongo查询,如果你使用普通的javascript你的BFS将无法工作,因为我们讨论的是节点js而不是PHP !!!
所以首先这是我在BFS代码中使用的异步while循环
BFS(Breath First search)和 DFS(Depth First Search).
对于这个问题,BFS优于DFS,因为您可以在O(logn)中跟踪树
您也可以使用DFS但是必须以递归方式实现它,并且运行时间将是O(n)并且因为您在节点j中编码,所以必须在异步中实现它并且实现它可能有点困难.
为了实现BFS算法,你必须使用异步while循环,因为你必须在你的while循环中使用mongo查询,如果你使用普通的javascript你的BFS将无法工作,因为我们讨论的是节点js而不是PHP !!!
所以首先这是我在BFS代码中使用的异步while循环
function asyncLoop(iterations,func,callback,foo) { var done = false; var loop = { next: function() { if (done) { return; } if (iterations) { func(loop); } else { done = true; if(callback) callback(foo); } },isEnd : function(){ return done ; },refresh : function(it){ iterations = it ; },break: function() { done = true; callback(); } }; loop.next(); return loop; }
这是BFS算法节点js代码:
function bfs (_id,callback){ _id = String(_id); var q = [],res = [] ; db.tasks.findOne({ _id : _id }).lean().exec(function(err,root){ root.depth = 0 ; q.push(root); asyncLoop(q.length,function(loop){ res.push(q[0]); db.tasks.find({ _parent : q[0]._id }).lean().exec(function(err,new_nodes){ if(err) console.log(err); else { var d = q[0].depth ; q.shift(); loop.refresh(new_nodes.length + q.length); if(new_nodes.length > 0){ new_nodes.forEach(function(new_node){ new_node.depth = d+1 ; q.push(new_node); }); } loop.next(); } }); },function(){ callback(res) }); }); }