在多个关系中过滤Cypher

时间:2017-06-21 09:02:35

标签: neo4j cypher

采用以下模式,该模式以标记为“对话”的节点开头,并且具有一长串[:RESPONSE]关系。

此模式中有许多节点,但我们只关心其中的2个:(答案)和(元素)。 我们关心的只有一种关系:[:响应]

(Conversation) <-[:RESPONSE]-(unimportant_node)<-[:RESPONSE]
..()..()..()..(Answer)<-()..()..(Element)..().().()..()..()..
(Answer)…()..(Element)<—()..()..(Answer)-..()-..(Element)<-..().()

我想要的是找到所有(答案),每个都有关联的(元素)。

变量部分:(对话)和(答案)之间以及(答案)和(元素)之间的节点数是可变的。

不变部分:每个(Answer)之后都有一个(Element)节点,它基本上与之相关联(Answer)。然后,在某些时候,还有另一个(答案),它也有一个相关的(元素)。

我正在做什么: 因为我想检索所有(答案),我使用(c:会话)&lt; - [:RESPONSE *] - (答:答案)。

然后,因为我不知道(Answer)与其关联的(Element)之间有多少个节点,我再次使用[:RESPONSE *]。

所以,我的查询看起来像这样:

match (c:Conversation) <- [:RESPONSE*] - (a:Answer) <-[:RESPONSE*]-(e:Element)

这会使每个(元素)跟随每个(答案),这是不好的,因为我只对每个(答案)之后的FIRST(元素)感兴趣。

我确实找到了 解决方案

match (c:Conversation) <- [:RESPONSE*] - (a:Answer) <- [:RESPONSE*] - (e:Element)
with c,a,head(collect(e)) as first_e  //could also use: collect(e)[0] as first_e
    ...code continues...

然而,我正在寻找一种替代解决方案,它只需在每个(答案)后找到第一个(元素)然后停止,从而使Cypher的工作量减少很多。

玩这个,我注意到如果我愿意,只带第一个(答案)很容易。 (但在我的情况下,我想要所有这些,所以我不这样做。)

match (c:Conversation) <- [:RESPONSE*] - (a:Answer) <- [:RESPONSE*]-(e:Element)
where not(  (:Answer)<- [:RESPONSE]-(a)  )

我认为必须有一种简单的方法来应用这种技术在每个之后只带第一个(元素)(答案),所以我尝试过:

match (c:Conversation) <- [:RESPONSE*]-(a:Answer)
with c,a
match (a) <-[:RESPONSE*]-(e:Element)
           where not( (:Answer)<- [:RESPONSE]-(a) )

不幸的是,这个逻辑不适用于for_each(Answer)范围,而是应用于整个查询。因此,这只会带来一行结果:

conversation | the_very_last_Answer | the_very_last_element

我也尝试将MATCH放在FOREACH中,但是我得到了一个SyntaxError。

1 个答案:

答案 0 :(得分:1)

您可以安装APOC procedures并使用apoc.cypher.run程序执行此操作。像这样:

MATCH (c:Conversation)<-[:RESPONSE*]-(a:Answer)
CALL apoc.cypher.run('
    WITH {a} AS a
    MATCH (a)-[:RESPONSE*]->(e:Element)
    RETURN e LIMIT 1',
    {a:a}) YIELD value
RETURN c, value.e

使用apoc.cypher.run,您可以执行每行LIMIT(在本例中为1)的子查询。