使用Cypher组合两个语句时的副作用

时间:2015-09-23 07:34:41

标签: neo4j cypher

我创建了以下示例案例:

MERGE (p1:C5{userId:'1234'})
mERGE (p2:C5{userId:'555'})
MERGE (p3:C5{userId:'1234'})
mERGE (p4:C5{userId:'6969'})
MERGE (p1)-[r1:follow]->(p2) 
MERGE (p2)-[t1:follow]->(p1)
MERGE (p3)-[r2:follow]->(p4) 
MERGE (p4)-[t2:follow]->(p3)
SET r1.type='mirror',
t1.type='real',
r2.type='real',
t2.type='mirror'

我正在尝试创建一个语句,该语句仅通过以下条件从给定节点(通过userId prop)删除关系:

  1. 对于给定节点,传入关系(follow.type)='mirror'
  2. 对于给定节点,传出关系(follow.type)='real'
  3. 你不需要两者都可以申请。每个规则都是个体的我只是想把它组合在同一个声明中。

    所以我设法写了些东西,但我有副作用。 它删除了所有关系,并没有考虑我提到的规则:

    MATCH (n:C5 { userId: '1234' })<-[r]-(),(g:C5{userId:'1234'})-[y]->() 
            WHERE r.type='mirror' or y.type='real'
            DELETE  r,y
    

    如果你查看这段代码,你会看到所有的关系都消失了。

    我希望只看到btw节点(1234)和节点(6969)的关系消失,因为传出和传入关系都会单独应用我的规则。

    现在,如果我将此查询拆分为2个按预期工作的语句:

    MATCH (n:C5 { userId: '1234' })<-[r]-() 
                WHERE r.type='mirror' 
                DELETE  r
    
    
    MATCH (g:C5{userId:'1234'})-[y]->() 
                WHERE y.type='real'
                DELETE  y
    

    但我确实希望将其合并为一个。 谢谢, 射线。

    评论后的新案例:

    MERGE (p1:C4{userId:'1234'})
    mERGE (p2:C4{userId:'555'})
    MERGE (p1)-[r1:follow]->(p2) 
    MERGE (p2)-[t1:follow]->(p1) 
    SET r1.type='real',
    t1.type='mirror'
    

    执行以下操作:

    match (n:C4{userId:'1234'})-[y]->(g:C4{userId:'555'}),
          (n:C4{userId:'1234'})<-[r]-(g:C4{userId:'555'})
    WHERE y.type='real' and r.type='real' 
    set y.type='mirror'
    with y,r
    match (n:C4{userId:'1234'})-[x]->(g:C4{userId:'555'}),
          (n:C4{userId:'1234'})<-[z]-(g:C4{userId:'555'})
    WHERE x.type='real' and z.type='mirror' 
    delete x,z
    

    我试图在这里创造2个条件。如果应用1个条件我只是设置如果应用2个条件我正在删除

    我的情况现在应该触发删除的第二部分。但那部分从未触发我受到0线影响。

2 个答案:

答案 0 :(得分:2)

这里的问题是&#34; OR&#34;一部分。

我的意思是,在你的查询中,你得到2个关系,如果第一个的类型是&#34;镜像&#34;或者第二种类型是&#34;真实&#34;你删除了两个。

因此,如果满足您指定的某个条件,则会删除这两个关系。

这也是分裂查询按预期工作的原因。

我认为你正在寻找这个:

MATCH (n:C5 { userId: '1234' })<-[r]-()
WHERE r.type='mirror' 
WITH r
MATCH (n:C5 { userId: '1234' })-[y]->()
WHERE y.type='real'
DELETE r,y

由于我在DELETE部分遇到CASE问题,我做了这个,使用WITH将r传递给第二个匹配,然后删除符合要求的关系。

如果我使用CASE找到解决方案,则会编辑此答案。

答案 1 :(得分:1)

我认为你使它变得比它需要的更复杂。 以下是如何执行此操作的不同示例,包括一些推理和控制台链接。 (控制台将RETURN代替DELETE,因此您可以使用它们。)

您可以表达单一条件的一种方法是,如果您首先匹配没有方向的关系,则在您的条件中包含方向。像

这样的东西
// Query 1a
MATCH (n:C5 {userId: '1234'})-[r]-()
WHERE (r.type = 'mirror' AND n<-[r]-()) OR (r.type = 'real' AND n-[r]->())
DELETE  r

// Query 1b
WHERE (r.type='mirror' AND ENDNODE(r) = n) OR (r.type = 'real' AND STARTNODE(r) = n)

请参阅console 1

您也可以使用与原始单一条件查询类似的方法。 在这里,您可以通过将条件移入MATCH模式来避免对条件逻辑感到困惑。

// Query 2
MATCH (n:C5 {userId: '1234'})<-[r {type:'mirror'}]-(), n-[s {type:'real'}]->()
DELETE r, s

对于您的示例图表,它可以正常工作,请参阅console 2

  

<强>除了:   您将需要重用节点(n)的标识符以避免两次匹配节点。   您在编辑中添加的查询也是如此。   当您匹配某些内容并将其绑定到标识符时,请使用该标识符。   对于您的上一次查询,这意味着要MATCH (n:C4 {userId:'1234'})-[y]->(g:C4 {userId:'555'}), n<-[r]-g

第二个查询(以及你的和Supiami)在r的图表和s的图表中假设只有一个关系

如果没有s或没有r ,则模式根本不匹配。 在console 3我已从图表中删除了与s匹配的关系,如您所见,该查询与r的任何内容都不匹配。

我的答案顶部的查询将处理这种情况,但您也可以通过首先匹配节点然后可选地匹配两种关系模式来处理它。

// Query 3
MATCH (n:C5 {userId: '1234'})
OPTIONAL MATCH n<-[r {type:'mirror'}]-()
OPTIONAL MATCH n-[s {type:'real'}]->()
DELETE r, s

console 4处尝试此查询。

反之亦然:如果rs存在多重关系,则其他关系将多次匹配。 在console 5中,我添加了另一个:C5节点,其关系将在查询中与s匹配。 如您所见,s返回两个不同的关系,r返回两次相同的关系。 这可能不是问题,因为DELETE将知道如何处理它。 但是,如果扩展此查询或编写更复杂的查询,请务必注意这种情况。 否则你会得到意想不到的结果。

关于样式的最后说明:这里有一些要考虑的事情,以提高示例和查询的清晰度。 这将使您和其他人更容易推理它们。

  • 大写关系类型
  • 使用您在设置查询中定义的关系类型,如果它们不相关则完全删除它们
  • 使用有意义或通用的标签(:User:A,而不是:C4:C5),如果它们不相关则删除它们
  • 尽量避免在关系中使用type作为属性名称
  • 对您的查询大写一致(mERGEmatchWHERE

这些只是约定,但在分享和推理查询时,以及在尝试查找错误时排除混乱时,它们确实非常有用。