From 0486ef1891275335b883410d5ff8366e5b6d37a8 Mon Sep 17 00:00:00 2001 From: "DESKTOP-DDTUS3E\\yaxin" Date: Thu, 14 Nov 2024 15:16:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=A1=88=E4=BB=B6=E5=9B=BE?= =?UTF-8?q?=E8=B0=B1=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9F=A5=E8=AF=A2=E6=A1=88?= =?UTF-8?q?=E4=BB=B6=E5=9B=BE=E8=B0=B1=E5=85=A8=E9=87=8F=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=92=8C=E5=85=B3=E7=B3=BB=E6=8E=A5=E5=8F=A3=E5=88=9D=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../neo4j/controller/Neo4jController.java | 10 +- .../neo4j/service/Neo4jService.java | 18 ++- .../neo4j/service/impl/Neo4jServiceImpl.java | 112 ++++++++++-------- .../com/supervision/police/vo/GraphReqVO.java | 32 +++++ 4 files changed, 117 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/supervision/police/vo/GraphReqVO.java diff --git a/src/main/java/com/supervision/neo4j/controller/Neo4jController.java b/src/main/java/com/supervision/neo4j/controller/Neo4jController.java index 1df32f4..64efed2 100644 --- a/src/main/java/com/supervision/neo4j/controller/Neo4jController.java +++ b/src/main/java/com/supervision/neo4j/controller/Neo4jController.java @@ -5,8 +5,7 @@ import com.supervision.common.domain.R; import com.supervision.neo4j.domain.CaseNode; import com.supervision.neo4j.domain.Rel; import com.supervision.neo4j.service.Neo4jService; -//import io.swagger.annotations.Api; -//import io.swagger.annotations.ApiOperation; +import com.supervision.police.vo.GraphReqVO; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -85,10 +84,11 @@ public class Neo4jController { /*************************************************************************************/ - @GetMapping("/getNode") - public R getNode(@RequestParam String picType, @RequestParam String caseId) { - return neo4jService.getNode(picType, caseId); + @PostMapping("/getCaseGraph") + public R getCaseGraph(@RequestBody GraphReqVO graphReqVO) { + return neo4jService.getCaseGraph(graphReqVO); } + @GetMapping("/getNodeAndRelationListByCaseId") public R getNodeAndRelationListByCaseId(@RequestParam String picType, @RequestParam String caseId) { return neo4jService.getNodeAndRelationListByCaseId(picType, caseId); diff --git a/src/main/java/com/supervision/neo4j/service/Neo4jService.java b/src/main/java/com/supervision/neo4j/service/Neo4jService.java index 2d59b14..1f38a47 100644 --- a/src/main/java/com/supervision/neo4j/service/Neo4jService.java +++ b/src/main/java/com/supervision/neo4j/service/Neo4jService.java @@ -3,6 +3,7 @@ package com.supervision.neo4j.service; import com.supervision.common.domain.R; import com.supervision.neo4j.domain.CaseNode; import com.supervision.neo4j.domain.Rel; +import com.supervision.police.vo.GraphReqVO; import java.util.List; @@ -33,8 +34,21 @@ public interface Neo4jService { Rel saveRelation(Rel rel); - R getNode(String picType, String caseId); + /** + * 查询案件图谱 + * + * @param graphReqVO 图谱查询请求参数 + * @return 图谱数据 + */ + R getCaseGraph(GraphReqVO graphReqVO); + /** + * 查询案件图谱全量节点和关系 + * + * @param picType 图谱类型 + * @param caseId 案件id + * @return 图谱数据 + */ R getNodeAndRelationListByCaseId(String picType, String caseId); // R test(); @@ -43,5 +57,5 @@ public interface Neo4jService { void createAbstractGraph(String path, String sheetName); - void mockTestGraph(String path, String sheetName, String recordId, String recordSplitId,String caseId); + void mockTestGraph(String path, String sheetName, String recordId, String recordSplitId, String caseId); } diff --git a/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java b/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java index e360c0d..7788c21 100644 --- a/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java +++ b/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java @@ -4,14 +4,15 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil; import com.supervision.common.domain.R; -import com.supervision.common.utils.StringUtils; import com.supervision.neo4j.domain.CaseNode; import com.supervision.neo4j.domain.Rel; import com.supervision.neo4j.dto.WebRelDTO; import com.supervision.neo4j.service.Neo4jService; import com.supervision.neo4j.utils.Neo4jUtils; +import com.supervision.police.vo.GraphReqVO; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.neo4j.driver.Record; import org.neo4j.driver.*; import org.springframework.beans.factory.annotation.Autowired; @@ -50,7 +51,7 @@ public class Neo4jServiceImpl implements Neo4jService { CaseNode res = null; try { Session session = driver.session(); - StringBuffer cql = new StringBuffer(); + StringBuilder cql = new StringBuilder(); Map params = new HashMap<>(); cql.append("CREATE (n:").append(caseNode.getNodeType()).append("{name:$name"); params.put("name", caseNode.getName()); @@ -74,7 +75,7 @@ public class Neo4jServiceImpl implements Neo4jService { Result run = session.run(cql.toString(), params); res = Neo4jUtils.getOneNode(run); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } return res; } @@ -88,13 +89,12 @@ public class Neo4jServiceImpl implements Neo4jService { public void delNode(Long id) { try { Session session = driver.session(); - StringBuffer cql = new StringBuffer(); + StringBuilder cql = new StringBuilder(); cql.append("MATCH (n) where id(n) = ").append(id).append(" DELETE n"); log.info(cql.toString()); Result run = session.run(cql.toString()); while (run.hasNext()) { - Record next = run.next(); - // log.info(next.toString()); + run.next(); } } catch (Exception e) { log.error(e.getMessage(), e); @@ -105,13 +105,12 @@ public class Neo4jServiceImpl implements Neo4jService { public void deleteNoRelationNode(Long id) { try { Session session = driver.session(); - StringBuffer cql = new StringBuffer(); + StringBuilder cql = new StringBuilder(); cql.append("MATCH (n) WHERE n.id = ").append(id).append(" AND NOT (n)--() DELETE n"); log.info(cql.toString()); Result run = session.run(cql.toString()); while (run.hasNext()) { - Record next = run.next(); - // log.info(next.toString()); + run.next(); } } catch (Exception e) { log.error(e.getMessage(), e); @@ -131,11 +130,10 @@ public class Neo4jServiceImpl implements Neo4jService { log.info(cql.toString()); Result run = session.run(cql.toString()); while (run.hasNext()) { - Record next = run.next(); - // log.info(next.toString()); + run.next(); } } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } } @@ -147,7 +145,7 @@ public class Neo4jServiceImpl implements Neo4jService { Result run = session.run("MATCH (n) where id(n) = " + id + Neo4jUtils.NODE_RETURN); node = Neo4jUtils.getOneNode(run); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } return node; } @@ -157,7 +155,7 @@ public class Neo4jServiceImpl implements Neo4jService { List list = new ArrayList<>(); try { Session session = driver.session(); - StringBuffer cql = new StringBuffer(); + StringBuilder cql = new StringBuilder(); cql.append("MATCH (n"); if (StringUtils.isNotEmpty(nodeType)) { cql.append(":"); @@ -185,7 +183,7 @@ public class Neo4jServiceImpl implements Neo4jService { Result run = session.run(cql.toString()); list = Neo4jUtils.getNodeList(run); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } return list; } @@ -195,7 +193,7 @@ public class Neo4jServiceImpl implements Neo4jService { CaseNode node = null; try { Session session = driver.session(); - StringBuffer cql = new StringBuffer(); + StringBuilder cql = new StringBuilder(); Map params = new HashMap<>(); cql.append("MATCH (n"); if (StringUtils.isNotEmpty(nodeType)) { @@ -223,7 +221,7 @@ public class Neo4jServiceImpl implements Neo4jService { Result run = session.run(cql.toString(), params); node = Neo4jUtils.getOneNode(run); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } return node; } @@ -241,7 +239,7 @@ public class Neo4jServiceImpl implements Neo4jService { Result run = session.run(cql, params); rel = Neo4jUtils.getOneRel(run); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } if (rel != null && rel.getId() != null) { return rel; @@ -252,7 +250,6 @@ public class Neo4jServiceImpl implements Neo4jService { @Override public Rel saveRelation(Rel rel) { - Rel res = null; try { Session session = driver.session(); Map params = new HashMap<>(); @@ -264,50 +261,71 @@ public class Neo4jServiceImpl implements Neo4jService { Result run = session.run(cql, params); rel = Neo4jUtils.getOneRel(run); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } return rel; } @Override - public R getNode(String picType, String caseId) { + public R getCaseGraph(GraphReqVO graphReqVO) { Map map = new HashMap<>(); List list = new ArrayList<>(); List> nodes = new ArrayList<>(); try { Session session = driver.session(); + StringBuilder relQuery = new StringBuilder("MATCH (n)-[rel]->(m) " + + "WHERE n.picType = $picType " + + "AND n.caseId = $caseId "); Map params = new HashMap<>(); - params.put("picType", picType); - params.put("caseId", caseId); - Result run = session.run("MATCH (n)-[rel]->(r) where n.picType = r.picType = $picType and n.caseId = r.caseId = $caseId" + - " RETURN id(rel) as id, n.name as source, id(n) as sourceId, type(rel) as name, r.name as target, id(r) as targetId", params); + params.put("picType", graphReqVO.getPicType()); + params.put("caseId", graphReqVO.getCaseId()); + if (StringUtils.isNotEmpty(graphReqVO.getQueryStr())) { + params.put("queryStr", graphReqVO.getQueryStr()); + relQuery.append("AND (n.name CONTAINS $queryStr OR type(rel) CONTAINS $queryStr OR m.name CONTAINS $queryStr) "); + } + if (graphReqVO.getNodeLabels() != null && !graphReqVO.getNodeLabels().isEmpty()) { + params.put("nodeLabels", graphReqVO.getNodeLabels()); + relQuery.append("AND (ANY(label IN $nodeLabels WHERE label IN labels(n)) " + + "OR ANY(label IN $nodeLabels WHERE label IN labels(m))) "); + } + if (graphReqVO.getRelTypes() != null && !graphReqVO.getRelTypes().isEmpty()) { + params.put("relTypes", graphReqVO.getRelTypes()); + relQuery.append("AND ANY(type IN $relTypes WHERE type = type(rel)) "); + } + relQuery.append("RETURN id(rel) as id, n.name as source, id(n) as sourceId, n.name as sourceName, type(rel) as relName, m.name as target, id(m) as targetId, m.name as targetName"); + log.info("relQuery:{}", relQuery); + Result run = session.run(relQuery.toString(), params); while (run.hasNext()) { Record record = run.next(); - //long id = record.get("id").asLong(); - //String source = record.get("source").asString(); + // 组织边 long sourceId = record.get("sourceId").asLong(); - String name = record.get("name").asString(); - //String target = record.get("target").asString(); + String relName = record.get("relName").asString(); long targetId = record.get("targetId").asLong(); - list.add(new WebRelDTO(sourceId, targetId, name)); - } - Result node = session.run("MATCH (n) where n.picType = $picType and n.caseId = $caseId RETURN id(n) as id, n.name as name", params); - while (node.hasNext()) { - Record record = node.next(); - String name = record.get("name").asString(); - long idLong = record.get("id").asLong(); - Map nodeMap = new HashMap<>(); - nodeMap.put("name", name); - nodeMap.put("entityName", name); - nodeMap.put("id", String.valueOf(idLong)); - nodes.add(nodeMap); + list.add(new WebRelDTO(sourceId, targetId, relName)); + + // 组织节点 + Map sourceNodeMap = new HashMap<>(); + sourceNodeMap.put("name", record.get("sourceName").asString()); + sourceNodeMap.put("id", String.valueOf(sourceId)); + nodes.add(sourceNodeMap); + Map targetNodeMap = new HashMap<>(); + targetNodeMap.put("name", record.get("targetName").asString()); + targetNodeMap.put("id", String.valueOf(targetId)); + nodes.add(targetNodeMap); } } catch (Exception e) { - e.printStackTrace(); + log.error("查询失败", e); } + // 根据节点ID去重 + List> distinctNodes = new ArrayList<>(nodes.stream() + .collect(Collectors.toMap( + node -> node.get("id"), // 以 ID 为唯一键 + node -> node, // 保留整个 Map 作为值 + (existing, replacement) -> existing)) // 如果有重复 ID,保留第一个 + .values()); // 节点和关系合并 - Map nodeRecordMap = electNodeRecord(nodes); + Map nodeRecordMap = electNodeRecord(distinctNodes); list = mergerWebRel(list, nodeRecordMap); nodes = mergeNode(nodes, nodeRecordMap); @@ -359,7 +377,7 @@ public class Neo4jServiceImpl implements Neo4jService { * 推选出代表节点信息 * * @param nodes key: name ,entityName,id 节点信息 - * @return + * @return key: name ,value: NodeMapRecord */ private Map electNodeRecord(List> nodes) { Map nodeRecordMap = new HashMap<>(); @@ -385,15 +403,13 @@ public class Neo4jServiceImpl implements Neo4jService { * * @param nodes key: name ,entityName,id * @param nodeRecordMap 代表节点信息 - * @return + * @return 合并后的节点信息 */ private List> mergeNode(List> nodes, Map nodeRecordMap) { return nodes.stream().map(map -> { Map nodeMap = new HashMap<>(); nodeMap.put("name", map.get("name")); - nodeMap.put("entityName", map.get("entityName")); - NodeMapRecord nodeMapRecord = nodeRecordMap.get(map.get("name")); if (null == nodeMapRecord) { log.warn("mergeNode:节点信息异常,nodeRecordMap中不存在节点名称为:{}的NodeMapRecord", map.get("name")); @@ -414,7 +430,7 @@ public class Neo4jServiceImpl implements Neo4jService { * * @param webRelDTOList 关系信息 * @param nodeRecordMap 代表节点信息 - * @return + * @return 合并后的关系信息 */ private List mergerWebRel(List webRelDTOList, Map nodeRecordMap) { diff --git a/src/main/java/com/supervision/police/vo/GraphReqVO.java b/src/main/java/com/supervision/police/vo/GraphReqVO.java new file mode 100644 index 0000000..9bf968e --- /dev/null +++ b/src/main/java/com/supervision/police/vo/GraphReqVO.java @@ -0,0 +1,32 @@ +package com.supervision.police.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 图谱查询请求参数 + */ +@Data +public class GraphReqVO { + /** + * 案件id + */ + private String caseId; + /** + * 图类型 + */ + private String picType; + /** + * 查询字符串 + */ + private String queryStr; + /** + * 节点标签(如:行为人) + */ + private List nodeLabels; + /** + * 关系类型(如:购买) + */ + private List relTypes; +}