如何将包裹纳入查询?

时间:2019-06-19 12:19:03

标签: java jqassistant

这个问题是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'},但这是行不通的:

  

查询中的一个属性名称在数据库中不可用,请确保您没有拼写错误,或者在应用程序中运行此语句时该标签可用(缺少的属性名称为:

有没有一种方法可以将搜索结果减少到我真正关心的 操作界面?

3 个答案:

答案 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

此查询产生笛卡尔乘积,这意味着它的性能不是很高。

下图显示了针对我的一个项目的查询的执行计划: enter image description here

此问题更详细地解决了该问题: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类型
  • 您应该始终限定关系,即代替EXTENDS或IMPLEMENTS来使用(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