【问题标题】:Get nodes connected only to other nodes that have a property in a range获取仅连接到在某个范围内具有属性的其他节点的节点
【发布时间】:2014-05-08 11:47:38
【问题描述】:

我有 4 种类型的节点:S, G, RC

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

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

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

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

问题:

给定一个idStr 范围,我希望所有RC 节点仅连接(直接或间接)到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

但仍有一些连接到G 节点的节点使用不在范围内的S 节点。 [Neo4j Console Test]

我想做什么?

第一个匹配用于获取两件事:G 节点使用 S 节点,idStr 在给定范围 (GroupGs) 和连接到这些 G 节点的 C 节点.

一旦我们得到它,我们必须检查那些C 节点是否连接到更多G 节点(直接或通过R 节点)。那是第二场比赛。

现在我们必须检查每个C 节点是否所有连接到它的G 节点(直接或通过R 节点)都在GroupGs 范围内。如果是这样,那C 节点(以及G 节点路径中的R 节点)是匹配的,这就是我想要得到的。

第二种方法(@FrobberOfBits 建议)

尝试只使用一个匹配,所以我们确定n 节点在匹配中是相同的:

MATCH (a:S)<-[:USES]-(b:G)<-[:CONNECTED_TO*]-(n:C), p=(n)-[:CONNECTED_TO*]->(c: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,COLLECT(c) AS gs
WHERE ALL(x IN gs WHERE x IN GroupGs)
RETURN cs

结果是一样的。 [Neo4j Console Test]

第三种方法(@FrobberOfBits 建议)

为问题赋予语义,C 可能是网络中的 endpointR 一个 repeaterG 一个 gatewayS 一个 Sim 卡。

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

Gateway 类型的每个节点只使用一个 Sim 节点:(:Gateway)-[:USES]-&gt;(:Sim)

Endpoint 类型的每个节点都可以连接到多个 RepeaterGateway 节点:(:Endpoint)-[:CONNECTED_TO]-&gt;(:Repeater|:Gateway)

Repeater 类型的每个节点都可以连接到多个 RepeaterGateway 节点:(:Repeater)-[:CONNECTED_TO]-&gt;(:Repeater|:Gateway)

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

知道我做错了什么吗?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    您的查询确实与您选择的变量混淆 - 将“a”绑定到标签 S,将“b”绑定到标签 G?稍后在第二个匹配子句中将“c”绑定到“G's”?这个查询在未来将很难调试,并且很难看到发生了什么;考虑将标签“G”绑定到“g”或“gs”或类似标签,等等。

    我认为你的问题是第二个匹配子句。第二个匹配子句中的 (c:G) 与第一个匹配子句中的任何内容(即 (b:G))无关。这意味着通过一组 CONNECTED_TO* 关系从某个节点到某个 (c:G) 的路径与查询第一行的复杂匹配无关。第二个匹配匹配标记为 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
    

    如果此处编辑的语法不完美,我们深表歉意;这是一个复杂的查询,需要一些麻烦,但我认为第二个MATCH 的放置和错误标签是你的问题。我的解决方案可能并不完美,可能需要修修补补,但应该能帮到您。

    【讨论】:

    • 对不起,如果符号令人困惑,@FrobberOfBits 第二个匹配子句中的 (c:G) 节点确实与第一个匹配项中的任何内容都没有必要相关。我已经编辑了这个问题,添加了 我想要做什么? 部分以澄清这一点。感谢您的努力!
    • ChusZ,这澄清了谢谢,但我认为你的第二场比赛仍有问题。在您的澄清中,您说:“我们必须检查 那些 C 节点是否连接到更多 G 节点(直接或通过 R 节点)。这是第二次匹配。”当您说 那些 C 节点时,在第二个匹配中的节点,您指的只是一个节点“n”。在你的第一场比赛中,那个“n”不绑定任何东西。所以n不是那些C节点,n是任意节点(不限于C的)
    • 如何绑定它们?我之前使用代码[...] WITH n, COLLECT(DISTINCT b) AS GroupGs [...]尝试绑定它们,但结果是一样的,所以我删除了n
    • 像我建议的那样,将第二个子句作为第一个匹配的一部分,引用 n。我不认为第一场比赛中的名字“n”会延续到第二场比赛中。
    • 你可能是对的。查询很复杂,正如我所说,使用抽象标签很难理解。我有一种感觉,如果我们知道 S、G 和 C 是什么,以及语义是什么,它会更有意义。如果我们知道这一点,也许甚至会有另一种查询方法来建议(而不是调整这个)。祝你好运。
    【解决方案2】:

    我想我终于明白了:

    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
    

    首先我得到GroupGs:所有使用S 节点的G 节点在给定范围内具有idStr 属性。

    现在我收集所有连接到G 节点的CR 节点不在GroupGs 中,我称它们为badCandidates

    最后,我得到了所有不在badCandidates 集合中并连接到GroupGs 中的G 节点的CR 节点。

    这里有一个例子:[Neo4j Console Test]

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

    【讨论】:

      猜你喜欢
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-08
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      相关资源
      最近更新 更多