1. 框架搭建
springboot集成知识图谱neo4j
1.1 jar
< dependencies>
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter< / artifactId>
< exclusions>
< exclusion>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- logging< / artifactId>
< / exclusion>
< / exclusions>
< / dependency>
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- web< / artifactId>
< / dependency>
< ! -- neo4j -- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- data- neo4j< / artifactId>
< / dependency>
< dependency>
< groupId> org. neo4j< / groupId>
< artifactId> neo4j- ogm- http- driver< / artifactId>
< version> 3.2 .39 < / version>
< / dependency>
< ! -- 配置 log4j2-- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- log4j2< / artifactId>
< / dependency>
< ! -- xml和properties支持 -- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- configuration- processor< / artifactId>
< optional> true < / optional>
< / dependency>
< ! -- 验证 -- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- validation< / artifactId>
< / dependency>
< ! -- lombok -- >
< dependency>
< groupId> org. projectlombok< / groupId>
< artifactId> lombok< / artifactId>
< version> 1.18 .24 < / version>
< scope> provided< / scope>
< / dependency>
< ! -- 工具类 -- >
< dependency>
< groupId> org. apache. commons< / groupId>
< artifactId> commons- lang3< / artifactId>
< version> 3.12 .0 < / version>
< / dependency>
< dependency>
< groupId> org. apache. commons< / groupId>
< artifactId> commons- collections4< / artifactId>
< version> 4.4 < / version>
< / dependency>
< dependency>
< groupId> commons- io< / groupId>
< artifactId> commons- io< / artifactId>
< version> 2.11 .0 < / version>
< / dependency>
< dependency>
< groupId> commons- beanutils< / groupId>
< artifactId> commons- beanutils< / artifactId>
< version> 1.9 .4 < / version>
< / dependency>
< dependency>
< groupId> com. google. guava< / groupId>
< artifactId> guava< / artifactId>
< version> 31.1 - jre< / version>
< / dependency>
< ! -- swagger-- >
< dependency>
< groupId> com. github. xiaoymin< / groupId>
< artifactId> knife4j- spring- boot- starter< / artifactId>
< version> 3.0 .3 < / version>
< / dependency>
< ! -- 常用的编码方法的工具类包 -- >
< dependency>
< groupId> commons- codec< / groupId>
< artifactId> commons- codec< / artifactId>
< version> 1.15 < / version>
< / dependency>
< ! -- log4j-- >
< dependency>
< groupId> log4j< / groupId>
< artifactId> log4j< / artifactId>
< version> 1.2 .17 < / version>
< scope> test< / scope>
< / dependency>
< dependency>
< groupId> org. apache. logging. log4j< / groupId>
< artifactId> log4j- web< / artifactId>
< version> 2.18 .0 < / version>
< / dependency>
< ! -- validation -- >
< dependency>
< groupId> javax. validation< / groupId>
< artifactId> validation- api< / artifactId>
< version> 2.0 .1 . Final< / version>
< / dependency>
< ! -- fastjson -- >
< dependency>
< groupId> com. alibaba. fastjson2< / groupId>
< artifactId> fastjson2< / artifactId>
< version> 2.0 .16 < / version>
< / dependency>
< / dependencies>
1.2 配置
spring:
neo4j:
uri: bolt://127.0.0.1:7687
security:
encrypted: false
authentication:
username: neo4j
password: neo4j
2 三种集成方式
2.1 默认接口
使用spring-data提供的接口,返回 @Node 注解的 Bean
2.1.1 定义节点
@Data
@Node ( "User" )
public class UserNode {
@Id
private String userId;
@Relationship ( type = "UserCard" , direction = Direction . OUTGOING)
private Set < CardRelation > cardRelation = new HashSet < > ( ) ;
public UserNode ( String cusNo) {
this . userId = cusNo;
}
}
@Data
@Node ( "Card" )
public class CardNode {
@Id
private String card;
public CardNode ( String card) {
this . card = card;
}
}
2.1.2 定义关系
@Data
@RelationshipProperties
public class CardRelation {
@RelationshipId
private Long id;
private String key;
private LocalDateTime time;
@TargetNode
private CardNode cardNode;
public CardRelation ( String key, LocalDateTime time, CardNode cardNode) {
this . key = key;
this . time = time;
this . cardNode = cardNode;
}
}
2.1.3 常用接口
2.2 自定义 CypherCql 接口
@Repository
public interface UserRepository extends Neo4jRepository < User , String > {
@Query ( value = "MATCH p=(s:User)-[r]->(t) RETURN p LIMIT $limit" )
List < PathValue > list ( Integer limit) ;
}
2.3 动态拼接 CypherCql
2.3.1 拼接Cql
public RelationshipDto listByCusNo ( UserVo vo) {
String cypher = "MATCH p=(s:User)-[r]-(t) where 1=1 {{where}} RETURN p LIMIT $limit" ;
StringBuilder query = new StringBuilder ( ) ;
String userId = vo. getUser ( ) ;
if ( StringUtils . isNotBlank ( cusNo) ) {
query. append ( " and s.userId='" ) . append ( userId) . append ( "'" ) ;
}
LocalDateTime time = vo. getTime ( ) ;
if ( null != time) {
query. append ( " and r.time >= localdatetime('" ) . append ( time) . append ( "') " ) ;
}
cypher = StringUtils . replace ( cypher, "{{where}}" , query. toString ( ) ) ;
Map < String , Object > params = Maps . newHashMap ( ) ;
params. put ( "limit" , vo. getLimit ( ) ) ;
log. info ( "cypher:{}" , cypher) ;
return neo4jService. selectByCypher ( cypher, params) ;
}
2.3.2 neo4jTemplate 封装
接口
public interface Neo4jService {
RelationshipDto selectByCypher ( String cypherQuery) ;
RelationshipDto selectByCypher ( String cypherQuery, Map < String , Object > params) ;
}
实现类
@Slf4j
@Service
public class Neo4jServiceImpl implements Neo4jService {
@Resource
private Neo4jTemplate neo4jTemplate;
@Override
public RelationshipDto selectByCypher ( String cypherQuery) {
Map < String , Object > map = Maps . newHashMap ( ) ;
return this . selectByCypher ( cypherQuery, map) ;
}
@Override
public RelationshipDto selectByCypher ( String cypherQuery, Map < String , Object > params) {
PreparedQuery < PathValue > condition = PreparedQuery . queryFor ( PathValue . class )
. withCypherQuery ( cypherQuery)
. withParameters ( params)
. build ( ) ;
List < PathValue > list = neo4jTemplate. toExecutableQuery ( condition) . getResults ( ) ;
return Neo4jUtil . switchD3 ( list) ;
}
}
工具类 转换D3格式数据
public class Neo4jUtil {
public static RelationshipDto switchD3 ( List < PathValue > list) {
RelationshipDto dto = new RelationshipDto ( ) ;
Map < Long , Map < String , Object > > nodeMap = Maps . newHashMap ( ) ;
Map < Long , RelationshipDto. EdgeInfo > relationMap = Maps . newHashMap ( ) ;
if ( CollectionUtils . isNotEmpty ( list) ) {
for ( PathValue value : list) {
Path path = value. asPath ( ) ;
for ( Path. Segment segment : path) {
Node start = segment. start ( ) ;
Map < String , Object > startMap = Maps . newHashMap ( start. asMap ( ) ) ;
startMap. put ( Constant . NEO4J_ID, start. id ( ) ) ;
startMap. put ( Constant . NEO4J_LABELS, start. labels ( ) ) ;
nodeMap. putIfAbsent ( start. id ( ) , startMap) ;
Node end = segment. end ( ) ;
Map < String , Object > endMap = Maps . newHashMap ( end. asMap ( ) ) ;
endMap. put ( Constant . NEO4J_ID, end. id ( ) ) ;
endMap. put ( Constant . NEO4J_LABELS, end. labels ( ) ) ;
nodeMap. putIfAbsent ( end. id ( ) , endMap) ;
Relationship relationship = segment. relationship ( ) ;
Map < String , Object > relMap = Maps . newHashMap ( relationship. asMap ( ) ) ;
relMap. put ( Constant . NEO4J_ID, relationship. id ( ) ) ;
relMap. put ( Constant . NEO4J_LABELS, start. labels ( ) ) ;
RelationshipDto. EdgeInfo edgeInfo = new RelationshipDto. EdgeInfo ( start. id ( ) , end. id ( ) , relMap) ;
relationMap. putIfAbsent ( relationship. id ( ) , edgeInfo) ;
}
}
dto. setNodes ( Lists . newArrayList ( nodeMap. values ( ) ) ) ;
dto. setEdges ( Lists . newArrayList ( relationMap. values ( ) ) ) ;
}
return dto;
}
}
D3 Bean
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RelationshipDto {
private List < Map < String , Object > > nodes;
private List < EdgeInfo > edges;
@Data
@AllArgsConstructor
public static class EdgeInfo {
private Long source;
private Long target;
private Map < String , Object > properties;
}
}