package com.supervision.neo4j.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; 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 lombok.Data; import lombok.extern.slf4j.Slf4j; import org.neo4j.cypherdsl.core.Case; import org.neo4j.driver.*; import org.neo4j.driver.Record; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; /** * @author qmy * @since 2023-10-26 */ @Slf4j @Service public class Neo4jServiceImpl implements Neo4jService { private final Driver driver; @Autowired private Neo4jServiceImpl(Driver driver) { this.driver = driver; } @Override public CaseNode save(CaseNode caseNode) { if (StringUtils.isEmpty(caseNode.getName()) || StringUtils.isEmpty(caseNode.getNodeType())) { throw new RuntimeException("未传节点名称或节点类型或图谱类型!"); } List byName = findByName(caseNode.getCaseId(), caseNode.getRecordId(), caseNode.getNodeType(), caseNode.getName(), caseNode.getPicType()); if (byName != null && !byName.isEmpty()) { throw new RuntimeException("名称已存在!"); } CaseNode res = null; try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); Map params = new HashMap<>(); cql.append("CREATE (n:").append(caseNode.getNodeType()).append("{name:$name"); params.put("name", caseNode.getName()); if (StringUtils.isNotEmpty(caseNode.getRecordId())) { cql.append(", recordSplitId:$recordSplitId"); params.put("recordSplitId", caseNode.getRecordSplitId()); } if (StringUtils.isNotEmpty(caseNode.getRecordId())) { cql.append(", recordId:$recordId"); params.put("recordId", caseNode.getRecordId()); } if (StringUtils.isNotEmpty(caseNode.getCaseId())) { cql.append(", caseId:$caseId"); params.put("caseId", caseNode.getCaseId()); } if (StringUtils.isNotEmpty(caseNode.getPicType())) { cql.append(", picType:$picType"); params.put("picType", caseNode.getPicType()); } cql.append("})").append(Neo4jUtils.NODE_RETURN); Result run = session.run(cql.toString(), params); res = Neo4jUtils.getOneNode(run); } catch (Exception e) { e.printStackTrace(); } return res; } /** * 删除节点,注意,删除节点的时候,要先把边删除掉,不然会报错 * * @param id 点的ID */ @Override public void delNode(Long id) { try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); 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()); } } catch (Exception e) { log.error(e.getMessage(), e); } } @Override public void deleteNoRelationNode(Long id) { try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); 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()); } } catch (Exception e) { log.error(e.getMessage(), e); } } /** * 删除边 * * @param relId 边ID */ public void deleteRel(Long relId) { try { Session session = driver.session(); StringBuilder cql = new StringBuilder(); cql.append("MATCH ()-[r]->() WHERE id(r) = ").append(relId).append(" DELETE r"); log.info(cql.toString()); Result run = session.run(cql.toString()); while (run.hasNext()) { Record next = run.next(); // log.info(next.toString()); } } catch (Exception e) { e.printStackTrace(); } } @Override public CaseNode findById(Long id) { CaseNode node = null; try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); cql.append("MATCH (n) where id(n) = ").append(id).append(Neo4jUtils.NODE_RETURN); Result run = session.run(cql.toString()); node = Neo4jUtils.getOneNode(run); } catch (Exception e) { e.printStackTrace(); } return node; } @Override public List findByName(String caseId, String recordId, String nodeType, String name, String picType) { List list = new ArrayList<>(); try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); cql.append("MATCH (n"); if (StringUtils.isNotEmpty(nodeType)) { cql.append(":"); cql.append(nodeType); } cql.append(") where 1 = 1"); if (StringUtils.isNotEmpty(caseId)) { cql.append(" and n.caseId = "); cql.append(caseId); } if (StringUtils.isNotEmpty(recordId)) { cql.append(" and n.recordId = "); cql.append(recordId); } if (StringUtils.isNotEmpty(name)) { cql.append(" and n.name = '"); cql.append(name); cql.append("'"); } if (StringUtils.isNotEmpty(picType)) { cql.append(" and n.picType = "); cql.append(picType); } cql.append(Neo4jUtils.NODE_RETURN); Result run = session.run(cql.toString()); list = Neo4jUtils.getNodeList(run); } catch (Exception e) { e.printStackTrace(); } return list; } @Override public CaseNode findOneByName(String caseId, String recordId, String nodeType, String name, String picType) { CaseNode node = null; try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); Map params = new HashMap<>(); cql.append("MATCH (n"); if (StringUtils.isNotEmpty(nodeType)) { cql.append(":"); cql.append(nodeType); } cql.append(") where 1 = 1"); if (StringUtils.isNotEmpty(caseId)) { cql.append(" and n.caseId = $caseId"); params.put("caseId", caseId); } if (StringUtils.isNotEmpty(recordId)) { cql.append(" and n.recordId = $recordId"); params.put("recordId", recordId); } if (StringUtils.isNotEmpty(name)) { cql.append(" and n.name = $name"); params.put("name", name); } if (StringUtils.isNotEmpty(picType)) { cql.append(" and n.picType = $picType"); params.put("picType", picType); } cql.append(Neo4jUtils.NODE_RETURN); Result run = session.run(cql.toString(), params); node = Neo4jUtils.getOneNode(run); } catch (Exception e) { e.printStackTrace(); } return node; } @Override public Rel findRelation(Rel rel) { try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); Map params = new HashMap<>(); cql.append("MATCH (a)-[rel:").append(rel.getName()).append("]->(b) where id(a) = $sourceId and id(b) = $targetId") .append(Neo4jUtils.REL_RETURN); params.put("sourceId", rel.getSourceId()); params.put("targetId", rel.getTargetId()); Result run = session.run(cql.toString(), params); rel = Neo4jUtils.getOneRel(run); } catch (Exception e) { e.printStackTrace(); } if (rel != null && rel.getId() != null) { return rel; } else { return null; } } @Override public Rel saveRelation(Rel rel) { Rel res = null; try { Session session = driver.session(); StringBuffer cql = new StringBuffer(); Map params = new HashMap<>(); cql.append("MATCH (a), (b) where id(a) = $sourceId and id(b) = $targetId CREATE(a)-[rel:").append(rel.getName()) .append("]->(b) ").append(Neo4jUtils.REL_RETURN); params.put("sourceId", rel.getSourceId()); params.put("targetId", rel.getTargetId()); Result run = session.run(cql.toString(), params); rel = Neo4jUtils.getOneRel(run); } catch (Exception e) { e.printStackTrace(); } return rel; } @Override public R getNode(String picType, String caseId) { Map map = new HashMap<>(); List list = new ArrayList<>(); List> nodes = new ArrayList<>(); try { Session session = driver.session(); 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); 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(); 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); } } catch (Exception e) { e.printStackTrace(); } map.put("list", list); map.put("nodes", nodes); return R.ok(map); } // @Override // public R test() { // Session session = driver.session(); // Map params = new HashMap<>(); // params.put("lawActor", "行为人"); // params.put("lawParty", "aaaaaa"); // Result run = session.run("MATCH (m:LawActor), (n:FictionalOrgan) where m.name=$lawActor OPTIONAL MATCH (m)-[r:`冒充`]->(n) RETURN id(m) as startId, id(n) as endId, id(r) as relId, m.recordId as recordId, m.recordsId as recordsId", params); // while (run.hasNext()) { // Record record = run.next(); // // String id = Neo4jUtils.valueTransportString(record.get("startId")); // String endId = Neo4jUtils.valueTransportString(record.get("endId")); // String relId = Neo4jUtils.valueTransportString(record.get("relId")); // System.out.println("************" + id); // System.out.println("************" + endId); // System.out.println("************" + relId); // } // return R.ok("222"); // } @Override public void createAbstractGraph(String path, String sheetName) { // 首先从数据库中读到数据 ExcelReader reader = ExcelUtil.getReader(path, sheetName); List abstractGraphExcelHeaders = reader.readAll(AbstractGraphExcelHeader.class); Map nodeMap = new HashMap<>(); Map relMap = new HashMap<>(); for (AbstractGraphExcelHeader abstractGraphExcelHeader : abstractGraphExcelHeaders) { // from if (!nodeMap.containsKey(abstractGraphExcelHeader.getFrom())) { CaseNode caseNode = new CaseNode(abstractGraphExcelHeader.getFrom(), abstractGraphExcelHeader.getFrom(), "0"); log.info("点:{}插入成功", abstractGraphExcelHeader.getFrom()); CaseNode save = save(caseNode); nodeMap.put(abstractGraphExcelHeader.getFrom(), save); } // to if (!nodeMap.containsKey(abstractGraphExcelHeader.getTo())) { CaseNode caseNode = new CaseNode(abstractGraphExcelHeader.getTo(), abstractGraphExcelHeader.getTo(), "0"); CaseNode save = save(caseNode); log.info("点:{}插入成功", abstractGraphExcelHeader.getTo()); nodeMap.put(abstractGraphExcelHeader.getTo(), save); } // relation if (!relMap.containsKey(abstractGraphExcelHeader.getFrom() + "->" + abstractGraphExcelHeader.getRelation() + "->" + abstractGraphExcelHeader.getTo())) { Rel rel = new Rel(nodeMap.get(abstractGraphExcelHeader.getFrom()).getId(), abstractGraphExcelHeader.getRelation(), nodeMap.get(abstractGraphExcelHeader.getTo()).getId(), "0"); saveRelation(rel); log.info("关系:{}插入成功", (abstractGraphExcelHeader.getFrom() + "->" + abstractGraphExcelHeader.getRelation() + "->" + abstractGraphExcelHeader.getTo())); relMap.put(abstractGraphExcelHeader.getFrom() + "->" + abstractGraphExcelHeader.getRelation() + "->" + abstractGraphExcelHeader.getTo(), rel); } } } public void deleteAbstractGraph() { Session session = driver.session(); // 首先查出来所有的抽象节点 Result run = session.run("MATCH (n) WHERE n.picType = '0' OPTIONAL MATCH (n)-[r]-() RETURN id(n) as nodeId, id(r) as relId"); Set nodeIdSet = new HashSet<>(); HashSet relIdSet = new HashSet<>(); while (run.hasNext()) { Record record = run.next(); String nodeId = Neo4jUtils.valueTransportString(record.get("nodeId")); nodeIdSet.add(nodeId); String relId = Neo4jUtils.valueTransportString(record.get("relId")); relIdSet.add(relId); } // 删除边 for (String s : relIdSet) { long relId = Long.parseLong(s); deleteRel(relId); log.info("删除边:{} 成功", relId); } // 删除节点 for (String s : nodeIdSet) { long nodeId = Long.parseLong(s); delNode(nodeId); log.info("删除节点:{} 成功", nodeId); } } @Data private static class AbstractGraphExcelHeader { private String from; private String relation; private String to; } @Data private static class MockDataGraphExcelHeader { private String fromType; private String from; private String relation; private String to; private String toType; } @Override public void mockTestGraph(String path, String sheetName, String recordId, String recordSplitId, String caseId) { // 首先从数据库中读到数据 ExcelReader reader = ExcelUtil.getReader(path, sheetName); List mockDataGraphExcelList = reader.readAll(MockDataGraphExcelHeader.class); Map nodeMap = new HashMap<>(); Map relMap = new HashMap<>(); for (MockDataGraphExcelHeader mockData : mockDataGraphExcelList) { // from if (!nodeMap.containsKey(mockData.getFrom())) { CaseNode caseNode = new CaseNode(mockData.getFrom(), mockData.getFromType(), recordSplitId, recordId, caseId, "1"); log.info("点:{}插入成功", mockData.getFrom()); CaseNode save = save(caseNode); nodeMap.put(mockData.getFrom(), save); } // to if (!nodeMap.containsKey(mockData.getTo())) { CaseNode caseNode = new CaseNode(mockData.getTo(), mockData.getToType(), recordSplitId, recordId, caseId, "1"); CaseNode save = save(caseNode); log.info("点:{}插入成功", mockData.getTo()); nodeMap.put(mockData.getTo(), save); } // relation if (!relMap.containsKey(mockData.getFrom() + "->" + mockData.getRelation() + "->" + mockData.getTo())) { Rel rel = new Rel(nodeMap.get(mockData.getFrom()).getId(), mockData.getRelation(), nodeMap.get(mockData.getTo()).getId(), "1"); saveRelation(rel); log.info("关系:{}插入成功", (mockData.getFrom() + "->" + mockData.getRelation() + "->" + mockData.getTo())); relMap.put(mockData.getFrom() + "->" + mockData.getRelation() + "->" + mockData.getTo(), rel); } } } }