问题描述
我想显示一个树状的子图,显示从单个节点开始的所有路径.大多数连接都是双向的(目前可能将2条边改为1条边,以实现更好的性能),并且我有不同类型的关系.但是有一个特殊的节点和关系序列导致了更多的循环,并且该序列不应该显示在结果图中.
I want to Display a tree-like subgraph showing all paths starting from a single node. Most connections are bidirectional(2 edges at the moment probably change to 1 edge instead for better performance) and I have different types of relationships. But theres one special sequence of nodes and relations leading into even more loops and this sequence shouldn't be displayed in the resulting graph.
MATCH p=(n)-[r*0..4]-(m) WHERE n.CAT='a1' RETURN p
该查询几乎可以解决问题,但是我找不到/创建正确的查询以将序列排除在图形之外.深度仍然受到限制,因为深度为[r*0..9]
的neo4j Web应用程序停止响应(不是主要问题!我已经知道如何改进/修复此问题),并且花了一段时间才停止数据库.序列正在创建最不需要的排列以及大量可能的路径和循环.没有办法更改节点之间的关系(除了使用1边而不是2边,实际上是双向的,但是据我所知,该操作应该仍然相同且不那么复杂,请改正我是否知道我错了),因为与另一个起始节点的关系可能是需要的.
This Query is nearly solving the problem, but I couldnt find/create the correct query to leave the sequence out of the graph. The depth is still limited because with depth [r*0..9]
neo4j web app stopped responding (not the main problem! I already know how to improve/fix this) and it took a while to stop the database. The Sequence is creating the most unwanted permutations and tons of possible paths and loops. There is no way to change the relations(except using 1 edge instead of 2, practically its bidirectional but as far as i know the operation should still be the same and less complex, correct me know if I'm wrong) between the nodes because with another starting node the relation is potentially needed.
序列:
(x)-[:relation2]-(y)-[:relation2]-(z)
和x,y,z
在CAT='variable'
处均具有相同的属性值.它始终是相同的关系和相同的属性.值和节点各不相同.
and x,y,z
all having the same propertie value at CAT='variable'
. It's always the same relation and the same propertie. The values and the nodes vary.
所有节点都是潜在的起始节点.
All nodes are potential starting nodes.
此外,查询必须非常快速地处理长路径(不同长度)有时会分裂的情况.排除了大部分序列后,将忽略大多数拆分.深度必须是无限的.一旦查询忽略序列并且不走"该路径,结果路径将始终结束.
Also the query has to be very very fast dealing with long paths(different lenghts) splitting sometimes. Most splits will be ignored with the sequence exlcuded. The depth has to be unlimited. The resulting paths will always end as soon the query ignores the sequence and doesnt "go" this path.
为防止误解:
x,y,z1和z3共享相同的属性CAT(category)='a'和z2.CAT ='b'.
x,y,z1 and z3 are sharing the same property CAT(category)='a'and z2.CAT='b' for example.
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
x.CAT = y.CAT = z1.CAT = z3.CAT != z2.CAT
查询的性能非常重要,也是执行此操作的原因,但是首先,我需要简单"的解决方案来完成该项目.
Performance of the query is very important and the reason for me doing this, but first I need "simple" solution to progress on this project.
非常感谢.
推荐答案
要不遍历两个节点,应将NODE_PATH用作唯一性规则(在密码中,这是RELATIONSHIP_PATH唯一性,以避免图形循环).
To not traverse twice a node, you should use the NODE_PATH as uniqueness rule (in cypher, it's a RELATIONSHIP_PATH uniqueness to avoid graph cycle).
正如@Tezra和@logisima指出,遍历API是关键.但是它并没有做到独一无二或如此复杂.最终打印出我想要的结果:
As @Tezra and @logisima pointed out the Traversal API is the key. But its not done with uniqueness or anything this complex. This finally printed out the results i was looking for:
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及时将我带到正确的轨道上)
(special thanks to @Tezra bringing me on the right track on time)
使用apoc的解决方案也应该是可行的,并且还可以避免将图形重新放入neo4j的问题.
A solution with apoc should also be possible and also avoid the problem of getting the graph back into neo4j.
这篇关于Neo4j密码查询从一个节点开始显示树状子图,而没有特定的关系和节点序列(尽可能有效)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!