我在MongoDB中有一些图形连接:
{
from: ObjectID(user),
to: ObjectID(user)
}
如果我想让所有用户都在深度1,很容易:
db.connections.find({from:ObjectID(myUser)});
但是当我想要找到深度为2的所有用户时,很难:愚蠢的想法是“找到所有深度为1的人,然后为每个人做一个像前一个一样的查询。没办法,加上它会返回也是所有循环路径。
e.g
1->2
2->1
1->3
2->4
results of user(1).findDepth2() would be 2,1,3,4 instead of 4.
伪node.js中的示例:
var myFriends = db.connections.find({from:ObjectID(myUser)});
var friendAtDepth2 = [];
for(friend in myFriends){
// I find friends of each friend
var frendsOfFriend = db.connections.find({from:ObjectID(friend)});
for(friendOfFriend in frendsOfFriend){
if(friendAtDepth2.indexof(friendOfFriend)==-1
&& myFriends.indexof(friendOfFriend)==-1
&& myUser!=friendOfFriend){
// I haven't already found this user, so I it is actually at depth 2
friendAtDepth2.push(friendOfFriend);
}
}
}
但是通过这种方式,我确实做了很多查询,我希望存在一种类似于mysql的连接查询,我只在一个查询中执行此操作
这样的查询是否可行?
答案 0 :(得分:0)
实施Breath-First Search算法以查找距离特定节点2的所有节点。
它具有线性时间复杂度O(| E | + | V |),因此你不能做得比这更好。
如果你想要距离为2,3和3的所有节点,那么你可能需要查看All-Pairs最短路径算法并稍微定制它们。
通过自定义它我的意思是你应该从每个节点运行一个BFS并停在所需的深度。如果你想要一些具体的代码示例,你应该看一下类似的问题,比如All paths of length L from node n using python。
另外,根据您的数据,您可以向节点添加显式邻居列表,这些列表具有过多的空间要求,您可以使用一个查询将所有数据放入内存中,或者您可以尝试使用聚合框架(可能是实施起来有点棘手,但这应该是最快的解决方案。)
或者,如果您的应用程序对图形和图形算法非常重视,您应该考虑图形数据库,例如Neo4j。