springboot集成neo4j搭建知识图谱后端项目(一)
springboot集成neo4j搭建知识图谱后端项目(一)
- 1.概述
- 2.安装neo4j
- 3.项目搭建
- 3.1.引入pom依赖
- 3.2.添加application.yml配置
- 3.3.添加Neo4jConfig.java配置
- 3.4.添加Neo4jService接口
- 3.5.添加Neo4jServiceImpl实现类
- 3.7.调用
- 4.总结
1.概述
getee项目开源地址:springboot集成neo4j搭建知识图谱后端项目
本文主要实现springboot集成neo4j,实现动态创建neo4j节点以及关系。数据同时存储在postgresql数据库以及neo4j。
2.安装neo4j
使用docker-compose安装neo4j,可以参考这篇文章docker-compose安装neo4j。
3.项目搭建
本项目springboot版本为2.7.18。
3.1.引入pom依赖
org.springframework.boot spring-boot-starter-data-neo4j 2.7.18 org.neo4j.driver neo4j-java-driver 4.4.12
3.2.添加application.yml配置
spring: # Neo4j数据源 neo4j: uri: bolt://192.168.80.196:7687 authentication: username: neo4j password: 123456 # postgresql数据源 datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://${ENV_DB_IP:127.0.0.1}:${ENV_DB_PORT:5432}/${ENV_DB_NAME:test}?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true&stringtype=unspecified username: postgres password: postgres
3.3.添加Neo4jConfig.java配置
package com.example.graph.config; import lombok.Data; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * neo4j连接配置 */ @Configuration @ConfigurationProperties(prefix = "spring.neo4j") @Data public class Neo4jConfig { private String uri; private Authentication authentication; // 创建 Neo4j Driver @Bean public Driver createDriver() { return GraphDatabase.driver(uri, AuthTokens.basic(authentication.getUsername(), authentication.getPassword())); } // 嵌套类,用于映射 authentication 配置 @Data public static class Authentication { private String username; private String password; } }
3.4.添加Neo4jService接口
package com.example.graph.service; import com.example.graph.entity.Entity; import com.example.graph.entity.EntityAttribute; import com.example.graph.vo.NodeRelationVO; import org.neo4j.driver.Record; import org.neo4j.driver.types.Node; import java.util.List; public interface Neo4jService { /** * 新增节点 * * @param entity */ void createNode(Entity entity); /** * 修改节点 * * @param id * @param nodeLabel * @param attributeList */ void updateNode(String id, String nodeLabel, List attributeList); /** * 删除节点 * * @param id id * @param nodeLabel 节点类型 */ void deleteNodeById(String id, String nodeLabel); Node findNodeById(String nodeLabel, String id); /** * 用自定义id属性来创建关系 * * @param fromNode * @param toNode * @param relationship */ void createRelationship(Node fromNode, Node toNode, String relationship); List selectNodeRelationByPath(String nodeId, String nodeLabel, Integer path); void deleteAll(); }
3.5.添加Neo4jServiceImpl实现类
package com.example.graph.service.impl; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.BeanUtils; import com.example.graph.entity.Entity; import com.example.graph.entity.EntityAttribute; import com.example.graph.service.Neo4jService; import com.example.graph.vo.NodeRelationVO; import com.example.graph.vo.NodeVO; import com.example.graph.vo.RelationShipVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.neo4j.driver.Driver; import org.neo4j.driver.Record; import org.neo4j.driver.Result; import org.neo4j.driver.Session; import org.neo4j.driver.types.Node; import org.neo4j.driver.types.Relationship; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; @Slf4j @Service @RequiredArgsConstructor public class Neo4jServiceImpl implements Neo4jService { private final Driver neo4jDriver; @Override public void createNode(Entity entity) { try (Session session = neo4jDriver.session()) { StringBuilder cypherQuery = new StringBuilder("CREATE (n:" + entity.getLabel() + " {"); cypherQuery.append("id: \"").append(entity.getId()).append("\"").append(", "); entity.getAttributeList().stream().forEach(attribute -> { cypherQuery.append(attribute.getLabel()).append(": \"").append(attribute.getValue()).append("\"").append(", "); }); cypherQuery.delete(cypherQuery.length() - 2, cypherQuery.length()); cypherQuery.append("})"); session.run(cypherQuery.toString()); log.info("createNode执行cql={}", cypherQuery); } } @Override public void updateNode(String id, String nodeLabel, List attributeList) { try (Session session = neo4jDriver.session()) { StringBuilder cypherQuery = new StringBuilder("MATCH (n:" + nodeLabel + " {id: \"" + id + "\"}) SET "); attributeList.stream().forEach(attribute -> { cypherQuery.append("n.").append(attribute.getLabel()).append(" = \"").append(attribute.getValue()).append("\", "); }); cypherQuery.delete(cypherQuery.length() - 2, cypherQuery.length()); cypherQuery.append(" RETURN n"); session.run(cypherQuery.toString()); log.info("updateNode执行cql={}", cypherQuery); } } @Override public void deleteNodeById(String id, String nodeLabel) { try (Session session = neo4jDriver.session()) { String cql = StrUtil.format("MATCH (n:{}) WHERE n.id = '{}' DETACH DELETE n", nodeLabel, id); session.run(cql); log.info("deleteNodeById执行cql={}", cql); } } @Override public Node findNodeById(String nodeLabel, String id) { try (Session session = neo4jDriver.session()) { String cql = StrUtil.format("MATCH (n:{} {id: '{}' }) RETURN n", nodeLabel, id); Result result = session.run(cql); while (result.hasNext()) { Record record = result.next(); Node node = record.get("n").asNode(); return node; } return null; } } @Override public void createRelationship(Node fromNode, Node toNode, String relationship) { String fromNodeLabel = fromNode.labels().iterator().next(); Map fromNodeMap = fromNode.asMap(); String toNodeLabel = toNode.labels().iterator().next(); Map toNodeMap = toNode.asMap(); try (Session session = neo4jDriver.session()) { String cypherQuery = "MATCH (a:" + fromNodeLabel + " {id: \"" + fromNodeMap.get("id") + "\"}), " + "(b:" + toNodeLabel + " {id: \"" + toNodeMap.get("id") + "\"}) " + "CREATE (a)-[r:" + relationship + "]->(b)"; session.run(cypherQuery); log.info("createRelationship执行cql={}", cypherQuery); } } /** * 查询与a节点存在关系、且距离为1的所有节点 * MATCH (a:student {id: '7'})-[r]-(b) RETURN a, r, b; * * @param nodeId 节点id * @param nodeLabel 节点标签 */ @Override public List selectNodeRelationByPath(String nodeId, String nodeLabel, Integer path) { try (Session session = neo4jDriver.session()) { String cql = StrUtil.format("MATCH (a:{} {id: '{}'})-[r]-(b) RETURN a, r, b", nodeLabel, nodeId); if (path > 1) { cql = StrUtil.format("MATCH (a:{} {id: '{}'})-[r*1..{}]-(b) RETURN a, r, b", nodeLabel, nodeId, path); } Result result = session.run(cql); List list = new ArrayList(); while (result.hasNext()) { Record record = result.next(); Node nodeA = record.get("a").asNode(); Relationship relationship = record.get("r").asRelationship(); Node nodeB = record.get("b").asNode(); NodeRelationVO nodeRelationVO = new NodeRelationVO(); NodeVO fromNodeVO = new NodeVO(); fromNodeVO.setNodeId(nodeA.id()); fromNodeVO.setNodeLabel(nodeA.labels().iterator().next()); fromNodeVO.setNodeProperties(nodeA.asMap()); RelationShipVO relationShipVO = new RelationShipVO(); relationShipVO.setRelationType(relationship.type()); relationShipVO.setRelationProperties(relationship.asMap()); relationShipVO.setStartNodeId(relationship.startNodeId()); relationShipVO.setEndNodeId(relationship.endNodeId()); NodeVO toNodeVO = new NodeVO(); toNodeVO.setNodeId(nodeB.id()); toNodeVO.setNodeLabel(nodeB.labels().iterator().next()); toNodeVO.setNodeProperties(nodeB.asMap()); nodeRelationVO.setNodeA(fromNodeVO); nodeRelationVO.setRelationShipVO(relationShipVO); nodeRelationVO.setNodeB(toNodeVO); list.add(nodeRelationVO); } log.info("selectNodeRelation执行cql={}", cql); return list; } } @Override public void deleteAll() { try (Session session = neo4jDriver.session()) { String cql = StrUtil.format("MATCH (n) DETACH DELETE n"); session.run(cql); log.info("deleteAll执行cql={}", cql); } } }
3.7.调用
在其他类注入,然后调用方法即可
@Autowired private Neo4jServiceImpl neo4jService;
4.总结
本文主要是采用拼接cql的方式,来实现对neo4j的一些基础操作。
存在问题:可能会存在cql注入风险,后续需要优化。
(图片来源网络,侵删)(图片来源网络,侵删)(图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。