Neo4j cypher查询从一个节点开始显示树状子图,没有特定的关系和节点序列(尽可能高效)

时间:2017-06-21 18:04:59

标签: neo4j cypher

我想显示一个树状子图,显示从单个节点开始的所有路径。大多数连接是双向的(此时2个边缘可能会更改为1个边缘而不是更好的性能)并且我有不同类型的关系。但是有一个特殊的节点和关系序列导致更多的循环,这个序列不应该显示在结果图中。

MATCH p=(n)-[r*0..4]-(m) WHERE n.CAT='a1' RETURN p

这个查询几乎解决了这个问题,但是我无法找到/创建正确的查询以使序列不在图中。深度仍然有限​​,因为深度[r*0..9] neo4j网络应用程序停止响应(不是主要问题!我已经知道如何改进/修复此问题)并且需要一段时间才能停止数据库。序列正在创建最多的不需要的排列和大量可能的路径和循环。没有办法改变关系(除了使用1个边而不是2个,实际上它是双向的,但据我所知,操作应该仍然相同且不太复杂,正确的我知道我是否错了)节点因为有另一个起始节点,可能需要这种关系。

序列:

(x)-[:relation2]-(y)-[:relation2]-(z)

x,y,zCAT='variable'处具有相同的属性值。它始终是相同的关系和相同的属性。值和节点各不相同。

所有节点都是潜在的起始节点。

此外,查询必须非常快速地处理长路径(不同长度)有时分裂。大多数分裂将被忽略,序列被排除。深度必须是无限的。一旦查询忽略序列,结果路径将始终结束,并且不会出现" go"这条道路。

为了防止误会:

x,y,z1和z3共享相同的属性CAT(类别)=' a'和z2.CAT =' b'例如。

display 不显示和停止

(x)-[:relation2]-(y) - [:relation2] - (z1)

(x)-[:relation2]-(y)-[:relation2]-(z2)

(x)-[:relation2]-(y)-[:relation1]-(z3)

x.CAT = y.CAT = z1.CAT = z3.CAT!= z2.CAT

查询的性能非常重要,这也是我这样做的原因,但首先我需要"简单"解决这个项目的进展。

提前多多感谢。

2 个答案:

答案 0 :(得分:1)

为此,您应该创建自定义遍历。 在Neo4j中有一个API,请查看文档:{​​{3}}

要不遍历两个节点,您应该使用NODE_PATH作为唯一性规则(在cypher中,它是RELATIONSHIP_PATH唯一性以避免图形循环。)

干杯

答案 1 :(得分:0)

  

为此,您应该创建自定义遍历。在Neo4j中有一个API,请查看文档:{​​{3}}

     

要不遍历两个节点,您应该使用NODE_PATH作为唯一性规则(在cypher中,它是RELATIONSHIP_PATH唯一性以避免图形循环)。

正如@Tezra和@logisima所指出的那样,Traversal API是关键。但它没有完成独特性或任何复杂的事情。这终于打印出了我正在寻找的结果:

TraversalDescription td = graphDb.traversalDescription()
.depthFirst()
.uniqueness(Uniqueness.RELATIONSHIP_GLOBAL)
.evaluator( new Evaluator()
{
    @Override
    public Evaluation evaluate( final Path path )
    {
        Node parent=null,grandParent =null;
        Relationship rel1=null,rel2=null;
        int nCount=0,rCount=0;

        if(path.length()>=2)
        {
            for(Node node : path.reverseNodes())
            {
                if(nCount==1)
                    parent = node;
                if(nCount==2)
                    grandParent=node;
                if(nCount>2)
                    break;
                nCount++;
            }
            for(Relationship rel : path.reverseRelationships())
            {
                if(rCount==0)
                    rel1 = rel;
                if(rCount==1)
                    rel2=rel;
                if(rCount>1)
                    break;
                rCount++;
            }
        }
        if(path.length()<2)
        {
            return Evaluation.INCLUDE_AND_CONTINUE;
        }
        else if (path.length()>=2 
                && rel1.isType(relType)
                && rel2.isType(relType)
                && path.endNode().getProperty("CATEGORY").toString().equals(parent.getProperty("CATEGORY").toString())
                && path.endNode().getProperty("CATEGORY").toString().equals(grandParent.getProperty("CATEGORY").toString()))
        {
            return Evaluation.EXCLUDE_AND_PRUNE;
        }
        else
        {
            return Evaluation.INCLUDE_AND_CONTINUE;
        }
    }
});
try ( Transaction tx = graphDb.beginTx() )
{
    Traverser traverser = td.traverse(graphDb.getNodeById(id));
    for ( Path path : traverser)
    {
        System.out.println(path.toString());
                }
    tx.success();
}

(特别感谢@Tezra让我按时走上正轨)

使用apoc的解决方案也应该是可能的,并且还避免了将图形恢复到neo4j的问题。