我有一个包含两种节点的图表:用户节点和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。
答案 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