springboot集成neo4j搭建知识图谱后端项目(一)

06-01 1322阅读

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注入风险,后续需要优化。

      springboot集成neo4j搭建知识图谱后端项目(一)
      (图片来源网络,侵删)
      springboot集成neo4j搭建知识图谱后端项目(一)
      (图片来源网络,侵删)
      springboot集成neo4j搭建知识图谱后端项目(一)
      (图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码