如何将包包含到查询中?

How to include package into query?

此问题是 的延续。

那里接受的答案建议使用:

MATCH 
   (i:Interface {name:'Action'}  )<-[:IMPLEMENTS|EXTENDS*1..10]- (class), 
   (abstractAction:Class {name:'AbstractAction'}) 
   where not (class)-->(abstractAction)   
RETURN class

效果很好,并给出了符合该条件的 classes 的列表。

我遇到的唯一问题是:该接口的名称 Action 是(令人惊讶的)模棱两可。绝对 class 名称 com.whatever.foo.bar.Action 将是。但是当我将查询更改为使用 {name:'com.whatever.foo.bar.Action'} 时,我得到一个空结果。

然后我尝试了 {package:'com.whatever.foo.bar' name:'Action'},但这不起作用:

One of the property names in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing property name is: package)

有没有办法将搜索结果减少到 我真正关心的 操作界面?

仔细查看 "working" 查询的结果图可以发现简单的答案,因为可以简单地使用 fileName 属性:

MATCH 
 (i:Interface {name:"Action", fileName:"/com/whatever/foo/bar/Action.class"}  )<-[:IMPLEMENTS]- (c) 
RETURN c

有一个 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

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

下图显示了我的一个项目的查询执行计划:

这个问题更详细地处理了那个问题:

由于此查询仅用于分析目的而不是针对生产系统执行,因此我会忽略该提示。

假设您要查找所有 class 实现 com.whatever.foo.bar.Action 且不扩展 com.whatever.foo.bar.AbstractAction 的所有 classes,您的查询应如下所示:

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

(恕我直言,这相当 self-expressive)

两个提示:

  • 查找 Java 类型应始终使用 Type 标签的索引 fqn 属性 完成,该标签采用完全限定的 class 名称
  • 您应该始终限定关系,即不要使用 (class)-->(abstractAction),而是使用 (class)-[:EXTENDS*]->(abstractAction),因为除了 EXTENDS 或 IMPLEMENTS 之外,class 节点可能有许多传出关系(例如 DEPENDS_ON, ANNOTATED_BY) 都将被查询遍历