密码路径与关系方向的条件

时间:2014-01-02 17:40:04

标签: neo4j cypher

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

MATCH path=(n)-[rels*1..10]-(m) 

在路径上有以下两个条件:

  1. 如果路径中后续节点之间的关系具有属性PROP ='true'
  2. ,则为true
  3. 如果type(relationship)=SENDS则为true,如果关系的方向是传出的(从一个路径节点到路径中的下一个节点)
  4. 另一种表达方式是除非关系名称为SENDS

    ,否则方向无关紧要

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

2 个答案:

答案 0 :(得分: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

或者这可能更具可读性

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

这是一个控制台:http://console.neo4j.org/?id=v3kgz9

答案 1 :(得分:0)

为了完整性,我已经使用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);

或者我的替代答案基于jjaderbags答案,但不使用累加器,但稍微慢一点

   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);