Neo4j cypher查询显示从一个节点开始的树状子图,没有特定的关系和节点序列(尽可能有效)
我想显示一个树状子图,显示从单个节点开始的所有路径。大多数连接都是双向的(为了更好的性能,目前可能将2条边改为1条边),我有不同类型的关系。但是有一个特殊的节点和关系序列导致更多的循环,这个序列不应该显示在结果图中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停止响应(不是主要问题!我已经知道如何改进/修复此问题),
匹配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条路径。查询必须快速,并考虑到具体情况