【问题标题】:Using cypher or traversal api to match only a single node on extreme sides of a path使用密码或遍历 api 仅匹配路径两端的单个节点
【发布时间】:2016-12-28 21:31:18
【问题描述】:

假设我在图中有以下路径:

(:Type1)<-[:RelType1]-(:Type2)<-[:RelType2]-()<-[*]-(centernode)-[*]->()-[:RelType2]->(:Type2)-[:RelType1]->(:Type1)

鉴于左侧的(:Type1) 节点的&lt;id&gt;,我能够MATCH 上面的路径并在右侧得到对应的(:Type1) 节点(注意路径是对称的,它的中心是节点(centernode) )。在我的用例中,我们得到(:Type1) 节点的&lt;id&gt;s,在另一侧获取相应的(:Type1) 节点,然后进一步处理。

但是,我可能会得到(:Type1) 的两个节点的&lt;id&gt;s。在这种情况下,将从相应节点开始触发单独的查询,并将评估到另一侧的 (:Type1) 节点,因此将在两个节点上继续执行进一步的执行。

Q1.如何避免同时处理两个节点。也就是说,如果给定两个位于同一路径两端的(:Type1) 节点中的两个&lt;id&gt;s,我如何确保只有一个查询从其中一个与另一侧的节点匹配的节点开始执行,这样只有其中一个节点被进一步处理,另一个节点被保存在临时缓冲区中以供以后处理(如果第一个节点的处理失败)。

补充事实: 上面我有一个路径,在其末端有两个 (:Type1) 节点。我可能有三个或更多路径从(centernode) 发出并以(:Type1) 节点结束。所以我希望只有一个(:Type1) 节点首先得到处理,下一个(:Type1) 节点只有在之前的处理失败时才会处理。

Q2. 这种情况甚至可以用纯密码实现吗?或者我必须最终使用 Neo4J Traversal API?如果是,那么如何做到这一点,因为我必须确保在两个不同的遍历中访问的节点/关系的唯一性。

Q3.如何在 Traversal API 中添加路径扩展器以匹配 (:Type1)&lt;-[:RelType1]-(:Type2)&lt;-[:RelType2]-() 类型的路径。我应该这样做吗:

at each traversal `next()`
    if (node is of Type1)
        follow <-[:RelType1]-
    if (node is of Type2)
        follow <-[:RelType2]-

(上面是伪代码。我是 Traversal API 的新手。我已经浏览了所有文档和示例。所以我猜测在扩展器中我必须放入 if() 过滤器来检查当前节点类型并决定哪种关系类型及其下一步展开的方向。上面的伪代码是为了表明这一点。)

这样的密码可以在 Traversal API 中编写吗?或者有没有更好的办法?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    一个老技巧是使用节点 ID 对对 (ID(a) &lt; ID(b)) 进行排序,这会过滤掉“重复”结果。因此,如果您将所有源 ID 输入到单个查询中,则可以使用此技巧过滤掉重复项:

    WITH [1, 2, 3, 4] AS sourceIds
    UNWIND sourceIds AS sourceId
    MATCH (source:Type1)
    WHERE ID(source) = sourceId
    MATCH
      (source)<-[:RelType1]-(:Type2)<-[:RelType2]-
      ()<-[*]-(centernode)-[*]->()
      -[:RelType2]->(:Type2)-[:RelType1]->(target:Type1)
    WHERE ID(source) < ID(target)
    RETURN source, target
    

    这适用于您的用例吗?

    【讨论】:

    • 问题是我不会一次获得所有源 ID。所以我会在不同的时间点获得 id(作为某些触发器的一部分),每次我获得新的源 id 时,我都会启动一个运行 cypher 的线程。当在相隔几微秒的时间收到源 ID 时会发生此问题,这将导致运行多个密码,导致两个密码匹配另一侧的对应节点,开始在两者上进行处理(或者如果超过两个源,则开始处理两个以上id 仅相隔几微秒接收)源 id 节点。
    • @Mahesha999 我自己不是 Traversal API 方面的专家,但我认为最简单的解决方案是使用一些自定义命令式 Java 代码并自行管理队列(例如 BlockingQueue) .您将在此队列中收集源 ID,并跟踪您找到的目标 ID。如果已经找到新的源 id(作为目标 id),只需跳过它。否则,运行一个简单的 Cypher 查询来查找相应的目标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多