【问题标题】:Make a path where next node is not the previous node?制作下一个节点不是前一个节点的路径?
【发布时间】:2018-01-25 06:01:27
【问题描述】:

我在一个图中有大约 150 万个节点,它们的结构是这样的(图片)

我运行一个 Cypher 查询,对遍历的每个关系执行计算:

WITH 1 AS startVal
MATCH x = (c:Currency)-[r:Arb*2]->(m)
WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal
RETURN EXTRACT(n IN NODES(x) | n) as Exchanges,
    extract ( e IN relationships(x) | startVal * e.rate) AS Rel,
    endVal, endVal - startVal AS Profit
ORDER BY Profit DESC LIMIT 5

问题是它返回路径("One")->("hop")->("One"),这对我来说没用。

如何让它不选择之前遍历的节点作为下一个节点(即"One"->"hop"->"any_other_node_but_not_"one")?

我已阅读 NODE_RECENT 应该解决我的问题。但是,没有关于如何在 RestAPI 或 APOC 过程中指定最近节点长度的示例。

是否有针对我的案例的 Cypher 查询?

谢谢。

附:我对 Neo4j 和编码非常陌生(不到 2 个月)。因此,如果有明显的简单解决方案,我深表歉意。

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    我不知道我是否完全理解了你的问题,但我相信你的问题可以在MATCH 上放置一个WHERE 子句来解决,以防止匹配不想要的关系,如下所示:

    WITH 1 AS startVal
    MATCH x = (c:Currency)-[r:Arb*2]->(m)
    WHERE NOT (m)-[:Arb]->(c)
    WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal
    RETURN EXTRACT(n IN NODES(x) | n) as Exchanges,
        extract ( e IN relationships(x) | startVal * e.rate) AS Rel,
        endVal, endVal - startVal AS Profit
    ORDER BY Profit DESC LIMIT 5
    

    【讨论】:

    • 它仍然返回 [{"name":"Two"},{"name":"hop"},{"name":"Two"}]。 :( 我想做的是:让节点“一”是一个起始节点。下一步是“跳”。当我在“跳”时,我可以去“一”节点或“二”。因为我来自“一个”节点,我不想回到它。有没有办法让我获得前一个节点,当我在“跳跃”节点并修剪它成为下一个节点时?像(n -1)(n+1)?
    • @dusktea 你试过cybersam解决方案了吗?即:在MATCH 之后放置一个WHERE c <> m。这样:WITH 1 AS startVal MATCH x = (c:Currency)-[r:Arb*2]->(m) WHERE c <> m WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal RETURN EXTRACT(n IN NODES(x) | n) as Exchanges, extract ( e IN relationships(x) | startVal * e.rate) AS Rel, endVal, endVal - startVal AS Profit ORDER BY Profit DESC LIMIT 5
    • 他的解决方案使我的路径在“跳”节点上结束。这对我来说是不正确的。有没有办法让路径只考虑深度为 2 个关系的节点?
    • @dusktea :Currency 标签只在 One 节点中?
    • :货币标签用于“一”和“二”节点。 “hop”节点有标签:Account
    【解决方案2】:

    尝试在 MATCH 子句之后插入此子句,以过滤掉 c 和 m 相同的情况:

    WHERE c <> m
    

    [编辑]

    即:

    WITH 1 AS startVal
    MATCH x = (c:Currency)-[r:Arb*2]->(m)
    WHERE c <> m
    WITH x, REDUCE(s = startVal, e IN r | s * e.rate) AS endVal, startVal
    RETURN EXTRACT(n IN NODES(x) | n) as Exchanges,
        extract ( e IN relationships(x) | startVal * e.rate) AS Rel,
        endVal, endVal - startVal AS Profit
    ORDER BY Profit DESC LIMIT 5;
    

    使用此查询创建测试数据后:

    CREATE
      (c:Currency {name: 'One'})-[:Arb {rate:1}]->(h:Account {name: 'hop'})-[:Arb {rate:2}]->(t:Currency {name: 'Two'}),
      (t)-[:Arb {rate:3}]->(h)-[:Arb {rate:4}]->(c)
    

    上述查询产生以下结果:

    +-----------------------------------------------------------------------------------------+
    | Exchanges                                                     | Rel   | endVal | Profit |
    +-----------------------------------------------------------------------------------------+
    | [Node[8]{name:"Two"},Node[7]{name:"hop"},Node[6]{name:"One"}] | [3,4] | 12     | 11     |
    | [Node[6]{name:"One"},Node[7]{name:"hop"},Node[8]{name:"Two"}] | [1,2] | 2      | 1      |
    +-----------------------------------------------------------------------------------------+
    

    【讨论】:

    • 现在查询返回 [{"name":"Two"},{"name":"hop"}] 和其他以“hop”节点结束的路径。我不能有一条以“跳跃”节点结束的路径。
    • 适合我。我已编辑我的答案以显示测试数据的结果。
    • 我认为这里的问题是输出中不需要第一行。也许您应该在模式的第一个节点中使用唯一标识符MATCHed,例如:MATCH x = (c:Currency {id:1})-[r:Arb*2]-&gt;(m)。
    • @dusktea 你能澄清我的结果是否是你想要的吗?另外,哪些节点有Currency 标签?
    • @cybersam 你发布的结果正是我想要的。在我的例子中,“一”和“二”节点标记为:Currency,“跳跃”节点标记为:Account。在两个给定的货币节点之间至少有一个账户“跳”节点。但是一个“跳”节点只连接了两个 Account 节点。我需要创建一个模式,其中连接到“跳跃”节点的节点是唯一的。
    猜你喜欢
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多