整体效果概览
核心实体定义
ChainMethod-接口方法
@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-应用
@NodeEntity(label = "ChainApp")
@Data
public class Neo4jChainAppEntity implements Serializable {
@Id
private String appName;
public Neo4jChainAppEntity(String appName) {
this.appName = appName;
}
}
关系
/**
* 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;
}
}
链路初始化
初始化
/**
* 数据初始化
*
* 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);
}
对应的链路效果
清空
MATCH (n)
DETACH DELETE n;
查询
作为入口:
match p=(startM)-[r:METHOD_CALLS]->(endM)
where (r.endMethodFullName='appD,methodD1')
return startM, r, endM
作为出口:
match p=(startM)-[r:METHOD_CALLS]->(endM)
where (r.startMethodFullName='appD,methodD1')
return startM, r, endM
必须要有方向性。
match p=(startM)-[r:METHOD_CALLS]->(endM)
where (r.startMethodFullName='appD,methodD1')
return r
过滤
MATCH p=(startM)-[r:METHOD_CALLS]->(endM)
where r.tid='T0001'
RETURN startM, r, endM
LIMIT 1000
根据节点直接查询
neo4j 如何查询一个节点关联的所有边信息
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查询:
MATCH (n)<-[r:METHOD_CALLS]-(m)
WHERE n.methodFullName = 'appB,methodB1'
RETURN r
这个查询做了以下几件事情:
-
MATCH (n)<-[r:METHOD_CALLS]-(m)
:这一部分会匹配所有节点n
和节点m
之间的METHOD_CALLS
类别的入边r
。n
是指定节点,m
是指向节点,r
是边的变量名。 -
WHERE ID(n) = node_id
:这一部分用于筛选出与特定节点ID匹配的n
。替换node_id
为你要查询的节点的实际ID。 -
RETURN r
:最后,这一部分会返回与选定节点相关的所有METHOD_CALLS
类别的入边r
。
通过运行这个Cypher查询,你将得到与指定节点相关的所有METHOD_CALLS
类别的入边信息。
查询作为出的边
MATCH (n)-[r:METHOD_CALLS]->(m)
WHERE n.methodFullName = 'appB,methodB1'
RETURN n,r,m
LIMIT 1000
小结
基本的关系创建实例。