我发现jQAssistant附带的dependency:packageCycles
约束的输出难以解释。具体而言,我热衷于寻找构成循环依赖的类的示例实例。
鉴于我发现了一个包的循环,对于每对辅助包,我需要找到两个连接它们的类。
这是我第一次尝试Cypher查询,但仍然缺少一些相关部分:
MATCH nodes = (p1:Package)-[:DEPENDS_ON]->(p2: Package)-[:DEPENDS_ON*]->(p1)
WHERE p1 <> p2
WITH extract(x IN relationships(nodes) |
(:Type)<--(:Package)-[x]->(:Package)-->(:Type)) AS cs
RETURN cs
具体来说,为了真正连接这两个包,这两种类型应该与DEPENDS_ON
相互关联,如下所示:
(:Type)<--(:Package)-[x]->(:Package)-->(:Type)
| ^
| DEPENDS_ON |
+--------------------------------------+
对于上面的模式,我必须返回两种类型(例如,而不是包)。优选地,单个循环依赖性的输出由限定类名的列表组成(否则多个不可能区分多于一个循环依赖的类链)。
出于这个特定目的,我发现Cypher非常有限,在路径遍历期间支持识别和收集新的图形模式似乎不是最简单的事情。此外,尝试为(:Type)
节点提供名称会导致语法错误。
我也和UNWIND
搞砸了很多,但无济于事。它允许你基于每个元素引入新的MATCH
子句(比如relationships(nodes)
的元素),但我不知道另一种方法来撤消unwind的破坏性影响:周围的列表结构是移除,使得多个循环依赖性的痕迹彼此合并。此外,结果似乎对我有所改变。在下面说的查询在概念上也非常接近我想要实现但不起作用:
MATCH nodes = (p1:Package)-[:DEPENDS_ON]->(p2: Package)-[:DEPENDS_ON*]->(p1)
WHERE p1 <> p2
WITH relationships(nodes) as rel
UNWIND rel AS x
MATCH (t0:Type)<-[:CONTAINS]-(:Package)-[x]->(:Package)-[:CONTAINS]->(t1:Type),
(t0)-[:DEPENDS_ON]->(t1)
RETURN t0.fqn, t1.fqn
我很欣赏jQAssistant中似乎有一些脚本支持。但是,这确实是我的最后手段,因为它的维护肯定比Cypher查询更难。
改写它:给定一个路径,我正在寻找一种方法来识别每个元素的子模式,从该匹配中投射一个节点,并收集结果。 你有什么想法可以用Cypher来实现这个目标吗?
编辑#1:在一个包中,还必须考虑到类型DEPENDS_ON
的入站边缘的目标类可能不是与传出边缘相同的类。换句话说,结果
DEPENDS_ON
类型的边缘): -[:DEPENDS_ON]->(:Type)<-[:CONTAINS]-(:Package)-[:CONTAINS]->(:Type)-[DEPENDS_ON]->
使用下面的图片可能会更清楚一点:
显然&#34; a,b,c&#34;是一个包装周期和&#34; TestA,TestB1,TestB2,TestC&#34;是一种类型级别的跟踪,用于证明包级依赖性。
答案 0 :(得分:0)
以下查询通过向下钻取类型级别来扩展包循环约束:
MATCH
(p1:Package)-[:DEPENDS_ON]->(p2:Package),
path=shortestPath((p2)-[:DEPENDS_ON*]->(p1))
WHERE
p1 <> p2
WITH
p1, p2
MATCH
(p1)-[:CONTAINS]->(t1:Type),
(p2)-[:CONTAINS]->(t2:Type),
(p1)-[:CONTAINS]->(t3:Type),
(t1)-[:DEPENDS_ON]->(t2),
path=shortestPath((t2)-[:DEPENDS_ON*]->(t3))
RETURN
p1.fqn, t1.fqn, EXTRACT(t IN nodes(path) | t.fqn) AS Cycle
我不确定查询在大型项目中的效果如何,我们需要尝试一下。
编辑1:更新了查询以匹配与t1位于同一包中的任何类型t3。
编辑2:答案不正确,请参阅下面的讨论。