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

Neo4j cypher查询显示从一个节点开始的树状子图,没有特定的关系和节点序列(尽可能有效),neo4j,cypher,Neo4j,Cypher,我想显示一个树状子图,显示从单个节点开始的所有路径。大多数连接都是双向的(为了更好的性能,目前可能将2条边改为1条边),我有不同类型的关系。但是有一个特殊的节点和关系序列导致更多的循环,这个序列不应该显示在结果图中 匹配p=(n)-[r*0..4]-(m)其中n.CAT='a1'返回p 这个查询几乎解决了这个问题,但我无法找到/创建正确的查询以将序列保留在图形之外。深度仍然有限,因为使用depth[r*0..9]neo4j web app停止响应(不是主要问题!我已经知道如何改进/修复此问题),

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

匹配p=(n)-[r*0..4]-(m)其中n.CAT='a1'返回p

这个查询几乎解决了这个问题,但我无法找到/创建正确的查询以将序列保留在图形之外。深度仍然有限,因为使用depth
[r*0..9]
neo4j web app停止响应(不是主要问题!我已经知道如何改进/修复此问题),并且需要一段时间才能停止数据库。该序列正在创建最不需要的排列以及大量可能的路径和循环。无法更改节点之间的关系(除了使用1个边而不是2个边,实际上是双向的,但据我所知,操作应该仍然相同且不太复杂,请纠正我的错误,如果我错了,请告诉我),因为对于另一个起始节点,可能需要关系

顺序:

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

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

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

此外,查询有时必须非常快速地处理长路径(不同长度)拆分。大多数拆分将被忽略,并显示序列。深度必须是无限的。一旦查询忽略序列并且不“转到”该路径,结果路径将始终结束

为避免误解:

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

显示
不显示并停止

(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

查询的性能非常重要,这也是我这样做的原因,但首先我需要“简单”的解决方案来推进这个项目


非常感谢。为此,您应该创建一个自定义遍历。 Neo4j中有一个API,请查看文档:

要不遍历一个节点两次,应使用
节点路径
作为唯一性规则(在cypher中,它是一个
关系路径
唯一性以避免图形循环)

干杯


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

要不遍历一个节点两次,应该使用节点路径作为唯一性规则(在cypher中,这是一种关系路径唯一性,以避免图循环)

正如@Tezra和@logisima指出的,遍历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();
}
TraversalDescription td=graphDb.TraversalDescription()
.depthFirst()
.唯一性(唯一性、关系和全局性)
.评估员(新评估员()
{
@凌驾
公共评估(最终路径)
{
节点父节点=null,祖父母节点=null;
关系rel1=null,rel2=null;
int nCount=0,rCount=0;
if(path.length()>=2)
{
for(节点:path.reverseNodes())
{
如果(n计数=1)
父节点=节点;
如果(n计数=2)
祖父母=节点;
如果(n计数>2)
打破
nCount++;
}
for(关系rel:path.reverseRelationships())
{
如果(rCount==0)
rel1=rel;
如果(rCount==1)
rel2=rel;
如果(rCount>1)
打破
rCount++;
}
}
如果(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(祖父母.getProperty(“CATEGORY”).toString())
{
返回Evaluation.EXCLUDE和PRUNE;
}
其他的
{
返回评估。包括_和_CONTINUE;
}
}
});
try(事务tx=graphDb.beginTx())
{
Traverser Traverser=td.traverse(graphDb.getNodeById(id));
for(路径:遍历器)
{
System.out.println(path.toString());
}
成功();
}
(特别感谢@Tezra让我按时步入正轨)


apoc的解决方案也应该是可行的,并且还可以避免将图形恢复到neo4j中的问题。

因此,让我看看我是否正确,给定3个参数(起始节点、CAT值和关系类型),您想要起始节点和所有具有CAT值的子节点(递归),并且只考虑关系类型边?(在显示部分,z1不应该显示,z2不应该显示吗?)唯一的问题是Relationtype 2连续出现两次,并且与它们连接的节点共享同一类别。在注意到特殊情况后,算法必须停止运行路径,因为在此之后,可能的路径会爆炸!由于忽略了作为路径的序列,因此我有大约20条路径。由于特例被接受并被视为路径,因此我有超过1360条路径。查询必须快速,并考虑到具体情况