2. springboot集成neo4j
·
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 {
/**
* @param cypherQuery cypher
* @return 返回值
*/
RelationshipDto selectByCypher (String cypherQuery);
/**
* @param cypherQuery cypher
* @param params params
* @return 返回值
*/
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 {
/**
* 转换数据格式
* @param list 查询结果
* @return D3格式数据
*/
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;
}
}
更多推荐



所有评论(0)