Neo4j 带关系方向条件的cypher路径

Neo4j 带关系方向条件的cypher路径,neo4j,cypher,Neo4j,Cypher,我想找到给定起始节点的所有路径 MATCH path=(n)-[rels*1..10]-(m) 在路径导入上具有以下两个条件: 如果路径中后续节点之间的关系具有属性PROP='true',则为true 如果type(relationship)=发送,则如果关系的方向为传出(从路径中的一个节点到下一个节点),则为真 另一种表达方式是,除非关系名是SENDS,否则方向并不重要 我可以用WHERE ALL(r IN rels WHERE r.PROP='true')执行条件1,但是我不知道如何执行

我想找到给定起始节点的所有路径

MATCH path=(n)-[rels*1..10]-(m) 
在路径导入上具有以下两个条件:

  • 如果路径中后续节点之间的关系具有属性PROP='true',则为true
  • 如果
    type(relationship)=发送
    ,则如果关系的方向为传出(从路径中的一个节点到下一个节点),则为真
  • 另一种表达方式是,除非关系名是SENDS,否则方向并不重要


    我可以用WHERE ALL(r IN rels WHERE r.PROP='true')
    执行条件1,但是我不知道如何执行条件2

    我能想到的在匹配模式中过滤关系方向而不声明方向的唯一方法是将路径中每个关系的开始节点与路径中
    nodes()
    集合的相应索引处的节点进行比较。为此,您需要路径中的关系和节点集合、一个索引计数器和一些相当于
    ALL()
    的布尔求值。一种方法是对累加器的集合使用
    REDUCE
    ,这样就可以累加索引,同时为路径维护真/假值。这里有一个例子,累加器从
    [0,1]
    开始,其中
    0
    是用于测试
    startNode(r)
    是否等于节点集合中相应索引处的节点(即,它是一个传出关系),
    1
    表示
    true
    ,这表示该路径尚未满足您的条件。对于每个关系,索引值递增,
    CASE/WHEN
    子句将“boolean”乘以1(如果满足条件),如果不满足,则乘以0。然后,对路径的求值是对
    REDUCE
    返回的集合中第二个值的求值——如果为1,则为yay;如果为0,则为boo

    MATCH path = (n)-[*1..10]-(m)
    WITH path, nodes(path) as ns, relationships(path) as rs
    WHERE REDUCE(acc = [0,1], r IN rs |
        [acc[0]+1, CASE WHEN 
            r.PROP='true' AND
            (type(r) <> "SENDS" OR startNode(r) = ns[acc[0]]) THEN acc[1]*1 ELSE acc[1]*0 END]
    )[1] = 1
    RETURN path
    
    匹配路径=(n)-[*1..10](m)
    使用路径,节点(路径)作为ns,关系(路径)作为rs
    其中REDUCE(acc=[0,1],r以rs表示|
    [acc[0]+1,情况如下
    r、 PROP='true'和
    (输入(r)“发送”或开始节点(r)=ns[acc[0]])然后acc[1]*1否则acc[1]*0结束]
    )[1] = 1
    返回路径
    
    或者这更具可读性

    WHERE REDUCE(acc = [0,1], r IN rs |
        CASE WHEN 
            r.PROP=true AND
            (type(r) <> "SENDS" OR startNode(r) = ns[acc[0]]) 
            THEN [acc[0]+1, acc[1]*1]
            ELSE [acc[0]+1, acc[1]*0]
        END
    )[1] = 1
    
    其中REDUCE(acc=[0,1],r以rs表示|
    当
    r、 PROP=正确且
    (类型(r)“发送”或起始节点(r)=ns[acc[0]])
    然后[acc[0]+1,acc[1]*1]
    其他[acc[0]+1,acc[1]*0]
    结束
    )[1] = 1
    

    这里有一个控制台:

    为了完整起见,我已经使用jjaderberg正确的解决方案以及修复开始节点并确保不包含零长度路径的条件回答了这个问题

    MATCH p = (n)-[*1..10]-(m) 
    WHERE ALL(n in nodes(p) WHERE 1=length(filter(m in nodes(p) WHERE m=n)))  
        AND (id(n)=1) 
    WITH p, nodes(p) as ns, relationships(p) as rs 
    WHERE REDUCE(acc = [0,1], r IN rs | [acc[0]+1, 
        CASE WHEN r.PROP='true' AND (type(r) <> "SEND" OR startNode(r) = ns[acc[0]]) 
        THEN acc[1]*1 
        ELSE acc[1]*0
        END])[1] = 1 
    RETURN nodes(p);
    

    也许我误解了,但您不能在模式中声明类型和方向吗?也就是说,
    匹配路径=(n)-[rels:SENDS*1..10]->(m)
    不,我不这么认为,只有一些关系是“SENDS”,以便更好地解释。。。我想在PROP='true'和direction为任意一种方式的交叉关系中设置路径,但是当遇到发送时,我还需要检查方向,因为对于发送,我只允许路径中的传出方向谢谢。这是正确的。我马上就找到了一个不用reduce或累加器的解决方案。我的问题是,我没有我可以传递多个集合从与。我用这些知识来修正我的方法,结果也证明是正确的,但速度较慢。匹配p=(n)-[rels*1..10]-(m)其中ALL(r在rels中,r.TRAVERSABLE='true')与p匹配,范围(0,长度(p)-1)作为idx,节点(p)作为ns,关系(p)作为rs,其中ALL(i在idx中,CASE type(rs[i])='a'当为true,则startnode(rs[i])=ns[i]否则为true END)返回节点(p);哦,这个模式在我的用例上运行需要很长时间!
       MATCH p=(n)-[rels*1..10]-(m) 
    WHERE ALL(n in nodes(p) WHERE 1=length(filter(m in nodes(p) WHERE m=n)))  
        AND(  ALL (r IN rels WHERE r.PROP='true')  
        AND id(n)=1)        
    WITH p, range(0,length(p)-1) AS idx, nodes(p) as ns, relationships(p) as rs      
    WHERE ALL (i in idx WHERE 
        CASE type(rs[i])='SEND' 
        WHEN TRUE THEN startnode(rs[i])=ns[i] 
        ELSE TRUE 
        END)  
    RETURN nodes(p);