我有这样的数据集合(例如):
{
name : "john" ,
_id : "0"
},
{
name : "Richard" ,
parent_id : "0" ,
_id : "1"
},
{
name : "Kevin" ,
parent_id : "0" ,
_id : "2"
},
{
name : "William" ,
parent_id : "1" ,
_id : "3"
},
{
name : "George" ,
parent_id : "3" ,
_id : "4"
}
我试图编写一个函数来接收_id
并返回此节点任何深度的所有子节点,例如_id = 0
我需要这样的内容:
[
{
name : "Richard" ,
parent_id : "0" ,
depth : "1" ,
_id : "1"
},
{
name : "Kevin" ,
parent_id : "0" ,
depth : "1" ,
_id : "2"
},
{
name : "William" ,
parent_id : "1" ,
depth : "2" ,
_id : "3"
},
{
name : "George" ,
parent_id : "3" ,
depth : "3" ,
_id : "4"
}
]
我编写了几个递归函数来迭代我的mongodb文档,但主要问题是我无法处理回调(异步)并且不知道何时以及如何结束递归函数。
如何使用mongodb和node.js执行此操作? 任何想法都很有用,谢谢。
答案 0 :(得分:1)
您可以使用2种着名的算法来实现目标
BFS(Breath First search)和DFS(Depth First Search)。
对于这个问题,BFS优于DFS,因为您可以在O(logn)中跟踪树
您也可以使用DFS但是必须以递归方式实现它,并且运行时间将是O(n),并且因为您在节点js 中进行编码,您必须在异步中实现它,它可能是有点难以实现它。
为了实现BFS算法,你必须使用异步while循环,因为你必须在你的while循环中使用mongo查询,如果你使用普通的javascript你的BFS将无法工作,因为我们讨论的是 node 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) });
});
}
注意:我还保存每个查询的深度,以便您可以获得每个查询的深度,并知道此查询在树中的位置。