提交 ac993532 作者: 王佳庆

合并分支 'neo4j' 到 'event_fusion'

Neo4j

查看合并请求 !4
......@@ -220,6 +220,13 @@
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>3.1.1</version>
</dependency>
<!-- neo4j 驱动 -->
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>4.1.2</version>
</dependency>
</dependencies>
<build>
......
package com.zzsn.event.neo4j.config;
import org.neo4j.driver.AuthToken;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author kongliufeng
* @create 2022-03-13
*/
@Configuration
public class Neo4jConfig {
@Value("${neo4j.username:neo4j}")
private String username;
@Value("${neo4j.password:zzsn9988}")
private String password;
@Value("${neo4j.url:bolt://server-1-95-128-5.ciglobal.cn:6595}")
private String url;
@Bean("neo4jDriver")
public Driver driver(){
AuthToken basic = AuthTokens.basic(username, password);
// Driver driver = GraphDatabase.driver("bolt://114.115.132.141:7687", basic);
Driver driver = GraphDatabase.driver(url, basic);
return driver;
}
// @Bean("neo4jDriver996")
// public Driver oldDriver(){
// AuthToken basic = AuthTokens.basic("neo4j", "123456");
// Driver driver = GraphDatabase.driver("bolt://server-1-95-14-24.ciglobal.cn:7687", basic);
// return driver;
// }
}
package com.zzsn.event.neo4j.controller;
import com.zzsn.event.constant.Result;
import com.zzsn.event.neo4j.service.AtlasService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@Api(tags = "图谱查询")
@RestController
@RequestMapping("/atlas")
public class AtlasController {
@Autowired
AtlasService atlasService;
@RequestMapping("/test")
public Result<?> test(String sql ,String databaseName){
return atlasService.test(sql,databaseName);
}
@RequestMapping("/test1")
public Result<?> test1(String name ,String databaseName){
return atlasService.test1(name,databaseName);
}
@GetMapping("/getAtlasBysubjectId")
public Result<?> getAtlasBysubjectId(String subjectId){
return atlasService.getAtlasBysubjectId(subjectId);
}
@GetMapping("/getAtlasBysubjectIdAndName")
public Result<?> getAtlasBysubjectIdAndName(String subjectId,String name){
return atlasService.getAtlasBysubjectIdAndName(subjectId,name);
}
}
package com.zzsn.event.neo4j.service;
import cn.hutool.core.util.StrUtil;
import com.zzsn.event.constant.Result;
import com.zzsn.event.neo4j.util.Neo4jUtil;
import com.zzsn.event.neo4j.vo.GraphInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Struct;
@Slf4j
@Service
public class AtlasService {
@Autowired
Neo4jUtil neo4jUtil;
public Result<?> test(String sql , String databaseName) {
GraphInfo nodeAndLink = neo4jUtil.getNodeAndLink(sql,databaseName);
return Result.OK(nodeAndLink);
}
public Result<?> test1(String name, String databaseName) {
StringBuilder a = new StringBuilder("MATCH p=(n)-[r]->(m) ") ;
if (StrUtil.isNotBlank(name)){
a.append("WHERE n.entity_id =~ '.*"+name+".*' " +
" OR m.entity_id =~ '.*"+name+".*' " +
" OR TYPE(r) =~ '.*"+name+".*' " );
}
a.append("RETURN p, n, m ");
a.append("LIMIT 200");
GraphInfo nodeAndLink = neo4jUtil.getNodeAndLink(a.toString(),databaseName);
return Result.OK(nodeAndLink);
}
public Result<?> getAtlasBysubjectId(String subjectId) {
GraphInfo nodeAndLink = neo4jUtil.getNodeAndLink("MATCH p=(n)-->(m) RETURN p,n,m LIMIT 200","lgRAGSJ"+subjectId);
return Result.OK(nodeAndLink);
}
public Result<?> getAtlasBysubjectIdAndName(String subjectId, String name) {
GraphInfo nodeAndLink = neo4jUtil.getNodeAndLink(
"MATCH (n)-[r]->(m) " +
"WHERE n.entity_id =~ '.*"+name+".*' OR " +
"m.entity_id =~ '.*"+name+".*' OR " +
"TYPE(r) =~ '.*"+name+".*' " +
"RETURN r, n, m LIMIT 200"
,"lgRAGSJ"+subjectId);
return Result.OK(nodeAndLink);
}
public Result<?> getAtlasBysubjectIdAndNamePath(String subjectId, String name) {
GraphInfo nodeAndLink = neo4jUtil.getNodeAndLink(
"MATCH p=(n)-[r]->(m) " +
"WHERE n.name =~ '.*"+name+".*' " +
" OR m.name =~ '.*"+name+".*' " +
" OR TYPE(r) =~ '.*"+name+".*' " +
"RETURN p, n, m " +
"LIMIT 200"
,"lgRAGSJ"+subjectId);
return Result.OK(nodeAndLink);
}
}
package com.zzsn.event.neo4j.util;
import com.zzsn.event.neo4j.vo.GraphInfo;
import com.zzsn.event.neo4j.vo.LinkData;
import com.zzsn.event.neo4j.vo.NodeData;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.driver.*;
import org.neo4j.driver.internal.types.InternalTypeSystem;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Path;
import org.neo4j.driver.types.Relationship;
import org.neo4j.driver.types.Type;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author kongliufeng
* @create 2022-03-13
*/
@Slf4j
@Component
public class Neo4jUtil {
@Resource
public Driver neo4jDriver;
/**
* 执行 Cypher 查询并返回处理后的记录列表
*/
public List<Record> executeCypher(String cypherSql, String databaseName) {
List<Record> resultList = new ArrayList<>();
try (Session session = neo4jDriver.session(SessionConfig.builder()
.withDatabase(databaseName)
.build())) {
Result result = session.run(cypherSql);
// 在会话关闭前将结果转换为列表
while (result.hasNext()) {
resultList.add(result.next());
}
} catch (Exception e) {
e.printStackTrace();
log.error("执行 Cypher 查询失败: " + e.getMessage());
}
return resultList;
}
/**
* @description 获取执行结果,指定数据库名称,需要在会话关闭前立即消费数据
*
* @author kongliufeng
* @Date 2022-03-13
*/
public Result executeCypherSql(String cypherSql, String databaseName) {
Result run = null;
try (Session session = neo4jDriver.session(SessionConfig.builder()
.withDatabase(databaseName)
.build())) {
System.out.println(cypherSql);
run = session.run(cypherSql);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
}
return run;
}
/**
* @description 获取执行结果
*
* @author kongliufeng
* @Date 2022-03-13
*/
public Result executeCypherSql(String cypherSql){
Result run = null;
try(Session session = neo4jDriver.session()){
System.out.println(cypherSql);
run = session.run(cypherSql);
}catch (Exception e){
e.printStackTrace();
log.error(e.getMessage());
}
return run;
}
public int getCountTotal(String sql) {
int total = 0;
try(Session session = neo4jDriver.session()){
System.out.println(sql);
Result result = session.run(sql);
if(result.hasNext()){
List<Record> records = result.list();
for (Record record : records) {
total = record.values().get(0).asInt();
}
}
}catch (Exception e){
e.printStackTrace();
log.error(e.getMessage());
}
return total;
}
/**
* 用于第五版显示
* match (n:{name=''}) return n
* 获取指定节点
* @author kongliufeng
* @data 2019-12-10 下午1:50:18
*/
public GraphInfo getNodeAndLink(String cypherSql) {
Result result = executeCypherSql(cypherSql);
GraphInfo graphInfo = new GraphInfo();
if (result == null || !result.hasNext()) {
return graphInfo;
}
// 使用Set避免重复节点和关系
Set<Node> nodes = new HashSet<>();
Set<Relationship> relationships = new HashSet<>();
while (result.hasNext()) {
Record record = result.next();
// 处理记录中的每个字段
for (String key : record.keys()) {
Value value = record.get(key);
processValue(value, nodes, relationships);
}
}
graphInfo.setNodes(convertNodes(nodes));
graphInfo.setLinks(convertRelationships(relationships));
Set<String> collect = graphInfo.getNodes().stream().map(NodeData::getLabels).flatMap(Set::stream).collect(Collectors.toSet());
List<HashMap<String,String>> labels = new ArrayList<>();
for (String label : collect) {
HashMap<String, String> map = new HashMap<>();
map.put("name", label);
labels.add(map);
}
graphInfo.setLabels(labels);
return graphInfo;
}
/**
* 可传库名
* match (n:{name=''}) return n
* 获取指定节点
* @author kongliufeng
* @data 2019-12-10 下午1:50:18
*/
public GraphInfo getNodeAndLink(String cypherSql,String databaseName) {
// Result result = executeCypherSql(cypherSql,databaseName);
List<Record> records = executeCypher(cypherSql, databaseName);
GraphInfo graphInfo = new GraphInfo();
if (records == null || records.isEmpty()) {
return graphInfo;
}
// 使用Set避免重复节点和关系
Set<Node> nodes = new HashSet<>();
Set<Relationship> relationships = new HashSet<>();
records.forEach(record -> {
// 处理记录中的每个字段
for (String key : record.keys()) {
Value value = record.get(key);
processValue(value, nodes, relationships);
}
});
graphInfo.setNodes(convertNodes(nodes));
graphInfo.setLinks(convertRelationships(relationships));
Set<String> collect = graphInfo.getNodes().stream().map(NodeData::getLabels).flatMap(Set::stream).collect(Collectors.toSet());
List<HashMap<String,String>> labels = new ArrayList<>();
for (String label : collect) {
HashMap<String, String> map = new HashMap<>();
map.put("name", label);
labels.add(map);
}
graphInfo.setLabels(labels);
return graphInfo;
}
private List<NodeData> convertNodes(Set<Node> nodes) {
List<NodeData> nodeList = new ArrayList<>();
for (Node node : nodes) {
NodeData nodeData = new NodeData();
nodeData.setId(node.id());
Set<String> list = new HashSet<>();
for (String item : node.labels()) {
list.add(item);
}
nodeData.setLabels(list);
nodeData.setName(node.asMap().get("entity_id").toString());
nodeData.setProperties(node.asMap());
nodeList.add(nodeData);
}
return nodeList;
}
private List<LinkData> convertRelationships(Set<Relationship> relationships) {
List<LinkData> linkList = new ArrayList<>();
for (Relationship rel : relationships) {
LinkData linkData = new LinkData();
linkData.setId(rel.id());
linkData.setType(rel.type());
linkData.setSourceId(rel.startNodeId());
linkData.setTargetId(rel.endNodeId());
linkData.setProperties(rel.asMap());
linkData.setName(rel.asMap().get("keywords").toString());
linkList.add(linkData);
}
return linkList;
}
private void processValue(Value value, Set<Node> nodes, Set<Relationship> relationships) {
Type type = value.type();
if (type.equals(Types.NODE)) {
nodes.add(value.asNode());
} else if (type.equals(Types.RELATIONSHIP)) {
relationships.add(value.asRelationship());
} else if (type.equals(Types.PATH)) {
Path path = value.asPath();
path.nodes().forEach(nodes::add);
path.relationships().forEach(relationships::add);
} else if (type.equals(Types.LIST)) {
// 递归处理列表中的元素
value.values().forEach(v -> processValue(v, nodes, relationships));
} else if (type.equals(Types.MAP)) {
// 处理Map中的值
value.asMap().values().forEach(v -> processValue(Values.value(v), nodes, relationships));
}
}
// 静态类型常量
private static class Types {
static final Type NODE = InternalTypeSystem.TYPE_SYSTEM.NODE();
static final Type RELATIONSHIP = InternalTypeSystem.TYPE_SYSTEM.RELATIONSHIP();
static final Type PATH = InternalTypeSystem.TYPE_SYSTEM.PATH();
static final Type LIST = InternalTypeSystem.TYPE_SYSTEM.LIST();
static final Type MAP = InternalTypeSystem.TYPE_SYSTEM.MAP();
}
}
package com.zzsn.event.neo4j.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author kongliufeng
* @create 2022-03-26
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GraphInfo {
List<HashMap<String,String>> labels = new ArrayList<>();
private List<LinkData> links = new ArrayList<>();
private List<NodeData> nodes = new ArrayList<>();
}
package com.zzsn.event.neo4j.vo;
import lombok.Data;
import java.util.Map;
/**
* @author kongliufeng
* @create 2022-03-24
*/
@Data
public class LinkData {
/**
* id
*/
private Long id;
/**
* 关系名称
*/
private String name;
/**
* 类型
*/
private String type;
/**
* 开始节点id
*/
private Long sourceId;
/**
* 结束节点id
*/
private Long targetId;
/**
* 连线附加属性
*/
private Map<String, Object> properties;
}
package com.zzsn.event.neo4j.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author kongliufeng
* @create 2022-03-26
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NodeData {
/**
* 节点id
*/
private Long id;
/**
* 节点名称
*/
private String name;
/**
* 节点类型
*/
private Set<String> labels;
/**
* 节点附加属性
*/
private Map<String, Object> properties;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论