整体效果概览

Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)METHOD_CALLSMETHOD_CALLSMETHOD_CALLSMETHOD_CALLSMETHOD_CALLSMETHOD_CALLSMETHOD_CALLSBELO…BELONG_APPBELONG_APPBELONG_APPBELONG_APP appC,m… appD,m… appD,m… appA,m… appB,m… appB appD appC appA

核心实体定义

ChainMethod-接口方法

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@NodeEntity(label = "ChainMethod") @Data public class Neo4jChainMethodEntity implements Serializable { /** * appName + methodName * * 测试下来有一个非常神奇的问题:如果一个属性以 xxxId 结尾,似乎会导致节点显示为空。 */ @Id private String methodFullName; @Property private String methodName; /** * @see com.github.houbb.method.chain.neo4j.constant.MethodTypeEnum */ @Property private String methodType; @Property private String appName; @Relationship(type = RelationshipTypeConst.BELONG_APP, direction = Relationship.OUTGOING) private Neo4jChainAppEntity chainApp; public Neo4jChainMethodEntity(String methodName, String methodType, String appName) { this.methodName = methodName; this.methodType = methodType; this.appName = appName; this.methodFullName = InnerAppMethodUtil.buildFullName(appName, methodName); this.chainApp = new Neo4jChainAppEntity(appName); } }

ChainApp-应用

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
@NodeEntity(label = "ChainApp") @Data public class Neo4jChainAppEntity implements Serializable { @Id private String appName; public Neo4jChainAppEntity(String appName) { this.appName = appName; } }

关系

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/** * method 方法名称 */ @RelationshipEntity(type = RelationshipTypeConst.METHOD_CALLS) @Data public class Neo4jChainMethodRelationshipEntity implements Serializable { /** * 当前调用关系的唯一标识 * * 如何保证唯一呢? * * md5(tid+startMethod+endMethod)? */ @Id private String methodRelationId; /** * 链路唯一标识 traceId */ @Index @Property private String tid; /** * 链路哈希 */ @Property @Index private String chainHash; /** * 开始节点 */ @StartNode private Neo4jChainMethodEntity startMethod; /** * 结束节点 */ @EndNode private Neo4jChainMethodEntity endMethod; public Neo4jChainMethodRelationshipEntity(String tid, Neo4jChainMethodEntity startMethod, Neo4jChainMethodEntity endMethod) { this.tid = tid; this.startMethod = startMethod; this.endMethod = endMethod; } }

链路初始化

初始化

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/** * 数据初始化 * * methodA1 -WEB * methodB1 -DUBBO * methodC1 -DUBBO * methodD1 -DUBBO */ @Test public void initMethodRelationshipTest() { Neo4jChainMethodEntity methodA1 = new Neo4jChainMethodEntity("methodA1", MethodTypeEnum.WEB.getCode(), "appA"); Neo4jChainMethodEntity methodB1 = new Neo4jChainMethodEntity("methodB1", MethodTypeEnum.DUBBO.getCode(), "appB"); Neo4jChainMethodEntity methodC1 = new Neo4jChainMethodEntity("methodC1", MethodTypeEnum.DUBBO.getCode(), "appC"); Neo4jChainMethodEntity methodD1 = new Neo4jChainMethodEntity("methodD1", MethodTypeEnum.DUBBO.getCode(), "appD"); Neo4jChainMethodEntity methodD2 = new Neo4jChainMethodEntity("methodD2", MethodTypeEnum.SERVICE.getCode(), "appD"); // 保存方法信息 chainMethodRepository.save(methodA1); chainMethodRepository.save(methodB1); chainMethodRepository.save(methodC1); chainMethodRepository.save(methodD1); chainMethodRepository.save(methodD2); // 第一个调用链路 final String tidFirst = "T0001"; //A=>B Neo4jChainMethodRelationshipEntity relationshipFirstA = new Neo4jChainMethodRelationshipEntity(tidFirst, methodA1, methodB1); //A=>C Neo4jChainMethodRelationshipEntity relationshipFirstB = new Neo4jChainMethodRelationshipEntity(tidFirst, methodA1, methodC1); //B=>D Neo4jChainMethodRelationshipEntity relationshipFirstC = new Neo4jChainMethodRelationshipEntity(tidFirst, methodB1, methodD1); List<Neo4jChainMethodRelationshipEntity> chainListFirst = Arrays.asList(relationshipFirstA, relationshipFirstB, relationshipFirstC); chainMethodRelationshipService.batchAdd(chainListFirst); // 第二个调用链路 final String tidSecond = "T0002"; //A=>B Neo4jChainMethodRelationshipEntity relationshipSecondA = new Neo4jChainMethodRelationshipEntity(tidSecond, methodA1, methodB1); //A=>C Neo4jChainMethodRelationshipEntity relationshipSecondB = new Neo4jChainMethodRelationshipEntity(tidSecond, methodA1, methodC1); //C=>D Neo4jChainMethodRelationshipEntity relationshipSecondC = new Neo4jChainMethodRelationshipEntity(tidSecond, methodC1, methodD1); //D1=>D2 Neo4jChainMethodRelationshipEntity relationshipSecondD = new Neo4jChainMethodRelationshipEntity(tidSecond, methodD1, methodD2); List<Neo4jChainMethodRelationshipEntity> chainListSecond = Arrays.asList(relationshipSecondA, relationshipSecondB, relationshipSecondC, relationshipSecondD); chainMethodRelationshipService.batchAdd(chainListSecond); }

对应的链路效果

Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)CHAIN_CALLSCHAIN_CALLSCHAIN_CALLSCHAIN_CALLSCHAIN_CALLSCHAIN_CALLSCHAIN_CALLS appA,m… appC,m… appB,m… appD,m… appD,m… appD,m… appA,m… appC,m… appB,m…

清空

  [sql]
1
2
MATCH (n) DETACH DELETE n;

查询

作为入口:

  [sql]
1
2
3
match p=(startM)-[r:METHOD_CALLS]->(endM) where (r.endMethodFullName='appD,methodD1') return startM, r, endM

作为出口:

  [sql]
1
2
3
match p=(startM)-[r:METHOD_CALLS]->(endM) where (r.startMethodFullName='appD,methodD1') return startM, r, endM

必须要有方向性。


  [sql]
1
2
3
match p=(startM)-[r:METHOD_CALLS]->(endM) where (r.startMethodFullName='appD,methodD1') return r

过滤

  [sql]
1
2
3
4
MATCH p=(startM)-[r:METHOD_CALLS]->(endM) where r.tid='T0001' RETURN startM, r, endM LIMIT 1000

根据节点直接查询

neo4j 如何查询一个节点关联的所有边信息

  [sql]
1
2
3
MATCH (n)-[r]-(m) WHERE n.methodFullName = 'appB,methodB1' RETURN r

neo4j 如何查询一个节点所有 income 进入边的信息,且 这个边的类别是 METHOD_CALLS

要查询一个节点所有入边的信息,且这些边的类别是METHOD_CALLS,你可以使用Cypher查询语言。以下是如何查询一个节点所有METHOD_CALLS类别的入边的示例:

假设你有一个节点,它的ID为node_id,你想查询所有指向这个节点的METHOD_CALLS类别的入边。你可以使用以下Cypher查询:

  [cypher]
1
2
3
MATCH (n)<-[r:METHOD_CALLS]-(m) WHERE n.methodFullName = 'appB,methodB1' RETURN r

这个查询做了以下几件事情:

  1. MATCH (n)<-[r:METHOD_CALLS]-(m):这一部分会匹配所有节点n和节点m之间的METHOD_CALLS类别的入边rn是指定节点,m是指向节点,r是边的变量名。

  2. WHERE ID(n) = node_id:这一部分用于筛选出与特定节点ID匹配的n。替换node_id为你要查询的节点的实际ID。

  3. RETURN r:最后,这一部分会返回与选定节点相关的所有METHOD_CALLS类别的入边r

通过运行这个Cypher查询,你将得到与指定节点相关的所有METHOD_CALLS类别的入边信息。

查询作为出的边

  [sql]
1
2
3
4
MATCH (n)-[r:METHOD_CALLS]->(m) WHERE n.methodFullName = 'appB,methodB1' RETURN n,r,m LIMIT 1000

小结

基本的关系创建实例。

参考资料