Neo4j 获取仅连接到具有范围内属性的其他节点的节点

Neo4j 获取仅连接到具有范围内属性的其他节点的节点,neo4j,cypher,Neo4j,Cypher,我有4种类型的节点:S、G、R和C S节点具有标识它们的idStr属性 类型为G的每个节点只使用一个S节点:(:G)-[:uses]->(:S) 类型为C的每个节点都可以连接到多个R或G节点:(:C)-[:connected_to]->(:R|:G) R类型的每个节点都可以连接到多个R或G节点:(:R)-[:connected_to]->(:R |:G) 问题: 给定一个idStr范围,我想获得所有R和C节点,这些节点(直接或间接)仅连接到G节点,这些节点使用该范围内的S节点和idStr 我最接

我有4种类型的节点:
S、G、R
C

S
节点具有标识它们的
idStr
属性

类型为
G
的每个节点只使用一个
S
节点:
(:G)-[:uses]->(:S)

类型为
C
的每个节点都可以连接到多个
R
G
节点:
(:C)-[:connected_to]->(:R|:G)

R
类型的每个节点都可以连接到多个
R
G
节点:
(:R)-[:connected_to]->(:R |:G)

问题:

给定一个
idStr
范围,我想获得所有
R
C
节点,这些节点(直接或间接)仅连接到
G
节点,这些节点使用该范围内的
S
节点和
idStr

我最接近的方法是:

MATCH (a:S)<-[:USES]-(b:G)<-[:CONNECTED_TO*]-(n:C)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(DISTINCT b) AS GroupGs
MATCH p=(n)-[:CONNECTED_TO*]->(c:G)
WITH FILTER(x IN NODES(p) WHERE NOT x:G) AS cs,GroupGs,COLLECT(c) AS gs
WHERE ALL(x IN gs WHERE x IN GroupGs)
RETURN cs
结果是一样的[]

第三种方法(由@frobberoffits建议)

就问题的语义而言,
C
可能是网络中的
端点,
R
a
中继器
G
a
网关
S
a
Sim

Sim
节点具有标识它们的
iccid
属性

Gateway
类型的每个节点只使用一个
Sim
节点:
(:Gateway)-[:uses]->(:Sim)

端点
类型的每个节点都可以连接到多个
中继器
网关
节点:
(:端点)-[:连接到]->(:中继器|:网关)

中继器类型的每个节点可以连接到多个
中继器
网关
节点:
(:中继器)-[:连接到]->(:中继器|:网关)

我正在尝试获取所有刚刚连接到
Gateway
节点的
中继器
端点
节点,这些节点正在使用
Sim
节点,其
iccid
在一个范围内


你知道我做错了什么吗?

你的查询真的把事情和你选择的变量搞混了——把“a”绑定到标签S,把“b”绑定到标签G?后来在第二个匹配子句中将“c”约束为“G”?这个查询将来很难调试,并且很难看到发生了什么;考虑绑定标签“G”到“G”,或“GS”,或类似,等等。p> 我认为你的问题在于第二个匹配条款。第二个match子句中的(c:G)与第一个match子句中的任何内容(即(b:G))无关。这意味着通过一组从某个节点到某个节点(c:G)的连接的_-TO*关系的路径与查询第一行上的复杂匹配无关。第二个匹配匹配任何标记为G的内容,而不仅仅是第一个匹配中指定的内容

第二个匹配是不好的,因为您提出了以下要求:

仅适用于使用idStr在该范围内的S节点的G节点

我没有你的测试数据,所以我无法验证这是否有效。但这里有一些东西可以尝试:

MATCH (a:S)<-[:USES]-(b:G)<-[:CONNECTED_TO*]-(n:C),
      p=(n)-[:CONNECTED_TO*]->(b:G)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(DISTINCT b) AS GroupGs,
     FILTER(x IN NODES(p) WHERE NOT x:G) AS cs,GroupGs,COLLECT(c) AS gs
WHERE ALL(x IN gs WHERE x IN GroupGs)
RETURN cs

匹配(a:S)我想我终于得到了:

MATCH (a:S)<-[:USES]-(b:G)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(b) AS GroupGs
MATCH (c)-[:CONNECTED_TO*]->(d:G)
WHERE NOT d IN GroupGs
WITH COLLECT(c) AS badCandidates,GroupGs
MATCH (e)-[:CONNECTED_TO*]->(f:G)
WHERE NOT e IN badCandidates AND f IN GroupGs
RETURN e
匹配(a:S)(d:G)
在GroupGs中没有d的地方
以COLLECT(c)作为候选项,GroupGs
匹配(e)-[:连接到*]->(f:G)
其中不包括BAD候选者中的e和GroupGs中的f
返回e
首先,我得到
GroupGs
:在给定范围内使用
S
节点且具有
idStr
属性的所有
G
节点

现在,我收集所有连接到
G
节点的
C
R
节点,这些节点不在
GroupGs
中,我将它们称为
badCandidates

最后,我得到所有
C
R
节点,这些节点不在
badCandidates
集合中,并且连接到
GroupGs
中的
G
节点

这里有一个例子:


我希望这对某人有所帮助。

如果符号混乱,我很抱歉,@frobberoffits第二个match子句中的(c:G)节点确实与第一个match子句中的任何内容都没有必要关联。我已经编辑了问题,添加了我想做什么的部分?为了澄清这一点。谢谢你的努力!楚兹,谢谢你,但我认为你的第二场比赛仍然有问题。在您的说明中,您说:“我们必须检查这些C节点是否连接到更多的G节点(直接或通过R节点)。这是第二个匹配。”当您说这些C节点,第二个匹配中的节点时,您仅指节点“n”。在你的第一场比赛中,这个“n”与任何事情都没有关系。所以n不是那些C节点,n是任何节点(不限于C),我如何绑定它们?我以前使用代码
[…]和n,COLLECT(DISTINCT b)作为GroupGs[…]
尝试绑定它们,但结果是一样的,所以我删除了
n
。像我建议的那样,在第一个匹配中创建第二个子句,引用n。我不认为第一场比赛中的“n”这个名字会延续到第二场比赛。你可能是对的。这个查询很复杂,正如我所说的,用抽象标签很难理解。我有一种感觉,如果我们知道S、G和C是什么,以及语义是什么,这会更有意义。如果我们知道这一点,也许还会有另一种查询方法可以建议(而不是调整这个方法)。祝你好运
MATCH (a:S)<-[:USES]-(b:G)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(b) AS GroupGs
MATCH (c)-[:CONNECTED_TO*]->(d:G)
WHERE NOT d IN GroupGs
WITH COLLECT(c) AS badCandidates,GroupGs
MATCH (e)-[:CONNECTED_TO*]->(f:G)
WHERE NOT e IN badCandidates AND f IN GroupGs
RETURN e