这个问题是How to identify all classes implementing a specific interface that do NOT extend some base class?的继续。
那里接受的答案建议使用:
MATCH
(i:Interface {name:'Action'} )<-[:IMPLEMENTS|EXTENDS*1..10]- (class),
(abstractAction:Class {name:'AbstractAction'})
where not (class)-->(abstractAction)
RETURN class
效果很好,并给出了符合该条件的类的列表。
我唯一的问题是:Action
接口的名称是(惊奇)不明确的。绝对的类名com.whatever.foo.bar.Action
将是。但是,当我将查询更改为使用{name:'com.whatever.foo.bar.Action'}
时,将得到一个空结果。
然后我尝试了{package:'com.whatever.foo.bar' name:'Action'}
,但这是行不通的:
查询中的一个属性名称在数据库中不可用,请确保您没有拼写错误,或者在应用程序中运行此语句时该标签可用(缺少的属性名称为:包)
有没有一种方法可以将搜索结果减少到我真正关心的 操作界面?
答案 0 :(得分:3)
有一个fqn
节点属性-全限定名。
因此正确的查询应为:
MATCH
(i:Interface {fqn:'com.whatever.foo.bar.Action'} )<-[:IMPLEMENTS|EXTENDS*1..10]- (class),
(abstractAction:Class {fqn:'com.whatever.foo.bar.AbstractAction'})
where not (class)-->(abstractAction)
RETURN class
此查询产生笛卡尔乘积,这意味着它的性能不是很高。
此问题更详细地解决了该问题:Why does neo4j warn: "This query builds a cartesian product between disconnected patterns"?
由于此查询仅用于分析目的,而不是针对生产系统执行,因此我将忽略该提示。
答案 1 :(得分:2)
假定您要查找实现com.whatever.foo.bar.Action
且未扩展com.whatever.foo.bar.AbstractAction
的所有类,则查询应如下所示:
MATCH
(class:Type:Class)-[:EXTENDS|IMPLEMENTS*]->(:Type:Interface{fqn:"com.whatever.foo.bar.Action"})
WHERE NOT
(class)-[:EXTENDS*]->(:Type:Class{fqn:"com.whatever.foo.bar.AbstractAction"})
RETURN
class
(恕我直言,这很自我表达)
两个提示:
Type
标签的索引fqn属性(使用完全限定的类名)来查找Java类型(class)-->(abstractAction)
而不是(class)-[:EXTENDS*]->(abstractAction)
,因为类节点可能有许多传出关系(例如DEPENDS_ON,ANNOTATED_BY)都将被遍历通过查询答案 2 :(得分:1)
仔细研究“工作”查询的结果图,可以发现简单的答案,因为可以简单地使用fileName
属性:
MATCH
(i:Interface {name:"Action", fileName:"/com/whatever/foo/bar/Action.class"} )<-[:IMPLEMENTS]- (c)
RETURN c