Neo4j和Cypher:从具有一些约束的一组节点中查找所有可到达的节点

时间:2018-02-02 21:38:53

标签: neo4j cypher

我有一个包含两种节点的图表:用户节点和IP节点。

我唯一的优势是:LOGGED_IN从用户节点到IP节点。

我想要找到的是来自一个用户节点的所有可访问用户节点。

所以我有一个这样的Cypher:

MATCH (u: User)-[*]-(connected: User) 
WHERE u.user_id = 'xxxxxxxxxxx'
RETURN distinct u, connected

但是,我发现某些IP节点可能是代理IP,因此该特定IP节点的边缘将超过100 :LOGGED_IN

我正在寻找一种方法来查找所有可访问的用户节点,但是使用代理IP绕过路径中的所有节点。

此外,代理IP节点的定义应该是可配置的,就像我可以将阈值设置为1000 :LOGGED_IN个边缘。如果IP的传入边缘超过1000个,那么它就是代理IP。

3 个答案:

答案 0 :(得分:0)

试一试:

match (i:ip)
where size(()-[:LOGGED_IN]->(i)) > 1000
match p = (u:User)-[*]-(connected:User) 
where u.user_id = 'xxxxxxxxxxx'
and not i in nodes(p)
return distinct u, connected

即:获得超过1000 :LOGGED_IN个关系的所有IP节点。然后,获取所有不包含这些节点的路径并返回所需的数据。

答案 1 :(得分:0)

Bruno的解决方案的替代方案(如果你有一个很好的代理ip节点),是在扩展期间添加一个WHERE子句来排除任何这些代理节点。

match p = (u:User)-[*]-(connected:User) 
where u.user_id = 'xxxxxxxxxxx'
and none(node in nodes(p) where node:ip and size((node)<-[:LOGGED_IN]-()) >= 1000)
return distinct u, connected

none()功能将在扩展期间进行评估,而不是在扩展后的过滤器中进行评估,这应该适合您。

您可以尝试的另一件事是使用APOC Procedures中的扩展过程,其中一些针对仅查找不同的节点进行了优化,而不是查找到同一节点的所有可能路径。

match (u:User)
where u.user_id = 'xxxxxxxxxxx'
call apoc.path.subgraphNodes(u, {labelFilter:'>User'}) yield node as connected
return u, connected

目前无法对此进行优化以排除代理IP节点,但扩展期间使用的NODE_GLOBAL唯一性可能会弥补它。

答案 2 :(得分:0)

这是@ BrunoPeres的另一个版本&#39;修复的查询以正确查找没有任何代理节点的路径。

此外,与@InverseFalcon的第一个查询不同,这个查询检查每个ip节点的度数,而不是检查每个路径中每个节点的(标签和)度。哪种方法更好取决于您的数据库的数据特征。

MATCH (i:ip)
WHERE SIZE(()-[:LOGGED_IN]->(i)) >= 1000
WITH COLLECT(i) AS proxies
MATCH path = (u:User)-[*]-(connected:User) 
WHERE u.user_id = 'xxxxxxxxxxx' AND NONE(p IN proxies WHERE p IN nodes(path))
RETURN DISTINCT u, connected