图数据库Neo4j的使用(附带源码)

Neo4j安装及简单使用

Neo4j和图数据库简介

neo4j是基于Java语言编写图形数据库。图是一组节点和连接这些节点的关系。图形数据库也被称为图形数据库管理系统或GDBMS。

Neo4j的是一种流行的图形数据库。 其他的图形数据库是Oracle NoSQL数据库,OrientDB,HypherGraphDB,GraphBase,InfiniteGraph,AllegroGraph。

Neo4j图形数据库的主要构建块是:

  • 节点:是图表的基本单位。 它包含具有键值对的属性

  • 关系:连接两个节点,具有方向:单向和双向。每个关系包含“开始节点”或“从节点”和“到节点”或“结束节点”。关系也可以包含属性作为键值对。

  • 属性:是用于描述图节点和关系的键值对。Key =值,其中Key是一个字符串,值可以通过使用任何Neo4j数据类型来表示

  • 标签:将节点分组为集合。将一个公共名称与一组节点或关系相关联。 节点或关系可以包含一个或多个标签。 我们可以为现有节点或关系创建新标签。我们可以从现有节点或关系中删除现有标签。

  • 数据浏览器:用于执行CQL命令并查看输出输出。

Neo4j安装

官网下载最新版 Neo4j 社区版(Community),注意使用Neo4j需要安装java环境,我这里使用3.5.4版本,对应java1.8可以使用。
Neo4j-3.5.4 社区window版和java1.8,网盘资源获取,提取码me9t在这里插入图片描述
下载后解压压缩包文件夹内容如下:
在这里插入图片描述
Neo4j应用程序有如下主要的目录结构:

  • bin目录:用于存储Neo4j的可执行程序;

  • conf目录:用于控制Neo4j启动的配置文件;

  • data目录:用于存储核心数据库文件;

  • plugins目录:用于存储Neo4j的插件;

配置环境变量

在计算机-属性中创建系统环境变量NEO4J_HOME,并把主目录(E:\Program Files (x86)\neo4j-community-3.4.0)设置为变量值。

NEO4J_HOME=E:\Program Files (x86)\neo4j-community-3.4.0

如果没有安装过java的环境,也需要配置java环境变量。

JAVA_HOME=E:\Program Files (x86)\jdk1.8.0_181

再在path中添加Neo4j和java安装目录下的bin文件夹。

%NEO4J_HOME%\bin。
%JAVA_HOME%\bin。

修改Neo4j配置文件

修改neo4j-community-3.5.25\conf下的neo4j.conf配置文件

去掉第54、71、75、79前面的#

# 允许远程访问
dbms.connectors.default_listen_address=0.0.0.0
# 开启bolt服务,默认端口7687
dbms.connector.bolt.listen_address=0.0.0.0:7687
# 开启http服务,默认端口7474
dbms.connector.http.listen_address=0.0.0.0:7474
# 开启https服务,默认端口7473
dbms.connector.https.listen_address=0.0.0.0:7473

Neo4j启动和停止

方法一:通过控制台启动Neo4j程序(win10建议使用)

CMD管理员身份运行(一定要以管理员身份进入CMD,否则会出现警告。警告: This command does not appear to be running with administrative rights. Some commands may fail e.g. Start/Stop)
输入:

neo4j.bat console

方法二:把Neo4j安装为服务(linux建议使用)
安装和卸载服务:

neo4j install-service
neo4j uninstall-service

启动服务,停止服务,重启服务和查询服务的状态:

neo4j start
neo4j stop
neo4j restart
neo4j status

在浏览器中打开http://localhost:7474 默认跳转到 http://localhost:7474/browser,出现Neo4j界面,则安装成功。初始密码:neo4j ,进去之后需要修改密码。
在这里插入图片描述
在这里插入图片描述

切换数据库

每次启动neo4j,它只能读取一个数据库。默认情况下的Graph.db数据库。
方法一:修改配置文件(win10)
使用Neo3.x创建新数据库而不删除现有数据库,所以只需在$NEO4J_HOME\conf的目录编辑neo4j.conf。搜寻dbms.active_database=,其默认值应为graph.db。用其他名称替换它,然后再次启动neo4j。现在,将在该目录名下创建一个新数据库。若要切换回以前的db,请重复这些步骤,只需将新值替换为graph.db在配置文件中。
注意:如果在neo4j启动的时候修改了配置文件,则需要重新启动一次,浏览器页面才会更新。

方法二:建立软连接(linux)
首次修改:

// 请将$NEO4j_HOME改为你的neo4j的安装路径
cd $NEO4j_HOME/data/databases/
// 保存原来数据库
mv graph.db graph1.db
//建立指向新数据库的软件接
ln -s graph2.db graph.db

//重启neo4j
cd $NEO4j_HOME/bin
./neo4j restart

再次修改
倘若我想访问graph3.db,就很简单了

//建立指向新数据库的软件接
ln -s graph3.db graph.db

//重启neo4j
cd $NEO4j_HOME/bin
./neo4j restart

Neo4j的CQL语句

CQL代表Cypher查询语言。 像Oracle数据库具有查询语言SQL,Neo4j具有CQL作为查询语言。
运行Neo4j之后,在软件窗口可以选择数据库创建位置,之后Neo4j就自动为我们创建好了数据库。

Neo4j CQL

  • 它是Neo4j图形数据库的查询语言。
  • 它是一种声明性模式匹配语言
  • 它遵循SQL语法。
  • 它的语法是非常简单且人性化、可读的格式。

我们可以通过Neo4j的图形化界面进行输入,在数据浏览器中的美元提示符下键入命令进行操控数据库。
在这里插入图片描述

1、创建节点

CREATE (dept:Dept { deptno:10,dname:"Accounting",location:"Hyderabad" })

2、查询节点

MATCH (dept: Dept)
RETURN dept.deptno,dept.dname

3、使用现有节点创建关系

MATCH (cust:Customer),(cc:CreditCard) 
CREATE (cust)-[r:DO_SHOPPING_WITH{shopdate:"12/12/2014",price:55000}]->(cc) 
RETURN r 

4、使用新节点创建关系

CREATE (video1:YoutubeVideo1{title:"Action Movie1",updated_by:"Abc",uploaded_date:"10/10/2010"})
-[movie:ACTION_MOVIES{rating:1}]->
(video2:YoutubeVideo2{title:"Action Movie2",updated_by:"Xyz",uploaded_date:"12/12/2012"}) 

5、查询关系

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie

6、根据条件查询

MATCH (emp:Employee) 
WHERE emp.name = 'Abc'
RETURN emp

7、删除节点(只能删除没有关系的节点)

MATCH (e: Employee) DELETE e

8、删除关系(可以连着节点一起删除)

MATCH (cc: CreditCard)-[rel]-(c:Customer) 
DELETE cc,c,rel

9、删除节点或关系的属性和标签

MATCH (book { id:122 })
REMOVE book.price
RETURN book

10、修改添加节点或关系属性

MATCH (book:Book)
SET book.title = 'superstar'
RETURN book

11、排序

MATCH (emp:Employee)
RETURN emp.empid,emp.name,emp.salary,emp.deptno
ORDER BY emp.name

12、联合查询(必须两个查询命令属性相同)

MATCH (cc:CreditCard) RETURN cc.id,cc.number
UNION
MATCH (dc:DebitCard) RETURN dc.id,dc.number

13、过滤或限制查询返回的行数

MATCH (emp:Employee) 
RETURN emp
LIMIT 2

14、跳过多少行返回数据

MATCH (emp:Employee) 
RETURN emp
SKIP 2

15、不存在进行创建,存在不创建

MERGE (gp2:GoogleProfile2{ Id: 201402,Name:"Nokia"})

16、null值查询(新建时不输入任何属性也会出现null值)

MATCH (e:Employee) 
WHERE e.id IS NULL
RETURN e.id,e.name,e.sal,e.deptno

17、批量查询in

MATCH (e:Employee) 
WHERE e.id IN [123,124]
RETURN e.id,e.name,e.sal,e.deptno

18、字符串函数(大写:UPPER,小写:LOWER,截取:SUBSTRING,替换:REPLACE)

MATCH (e:Employee) 
RETURN e.id,UPPER(e.name),e.sal,e.deptno

19、聚合函数(总行数:COUNT,最大值:MAX,最小值:MIN,求和:SUM,平均值:AVG)

MATCH (e:Employee) RETURN COUNT(*)

20、关系函数(关系启点:STARTNODE,关系终点:ENDNODE,关系id:ID,关系类型:TYPE)

MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN STARTNODE(movie)

21、创建普通索引

CREATE INDEX ON :Customer (name)

22、创建唯一索引

CREATE CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE

23、删除普通索引

DROP INDEX ON :Customer (name)

24、删除唯一索引

DROP CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE

25、修改密码

:server change-password

26、case表达式(选择语句)

MATCH(n)
RETURN  
CASE n.eyes
    WHEN 'blue' THEN 1
    WHEN 'brown' THEN 2
    ELSE 3 
END
AS result

27、深度匹配 (路径长度匹配)

(a)-[*2..4]->(b)  // 匹配路径长度为 2 到4 之间 的路径
(a)-[*2..]->(b) // 匹配路径长度大于2的路径
(a)-[*..2]->(b) // 匹配路径长度小于2的路径
(a)-[*]->(b) // 匹配任意长度的路径
match(n) -[r:TYPE*minHops..maxHops]->(m) return r

28、最短路径匹配 shortestPath() 函数

match (martin:Person {name:"name1"}),(oliver:Perspn{name:"name2"}),p = shortestPath((martin)-[*..15]-(oliver)) 
return p

29、所有最短路径 allShortestPaths()

match (martin:Person {name:"name1"}),(oliver:Perspn{name:"name2"}),p= allShortestPaths((martin)-[*]-(oliver)) 
return p

导入csv文件

首先从MySQL数据库导出csv文件,复制到import文件夹E:\Program Files (x86)\neo4j-community-3.4.0\import里,然后执行下列语句:

//导入节点 电影类型  == 注意类型转换
LOAD CSV WITH HEADERS  FROM "file:///genre.csv" AS line
MERGE (p:Genre{gid:toInteger(line.gid),name:line.gname})
	

//导入节点 演员信息	
LOAD CSV WITH HEADERS FROM 'file:///person.csv' AS line
MERGE (p:Person { pid:toInteger(line.pid),birth:line.birth,
death:line.death,name:line.name,
biography:line.biography,
birthplace:line.birthplace})


// 导入节点 电影信息
LOAD CSV WITH HEADERS  FROM "file:///movie.csv" AS line  
MERGE (p:Movie{mid:toInteger(line.mid),title:line.title,introduction:line.introduction,
rating:toFloat(line.rating),releasedate:line.releasedate})


// 导入关系 actedin  电影是谁参演的 1对多
LOAD CSV WITH HEADERS FROM "file:///person_to_movie.csv" AS line 
match (from:Person{pid:toInteger(line.pid)}),(to:Movie{mid:toInteger(line.mid)})  
merge (from)-[r:actedin{pid:toInteger(line.pid),mid:toInteger(line.mid)}]->(to)
	
//导入关系  电影是什么类型 == 1对多
LOAD CSV WITH HEADERS FROM "file:///movie_to_genre.csv" AS line
match (from:Movie{mid:toInteger(line.mid)}),(to:Genre{gid:toInteger(line.gid)})  
merge (from)-[r:is{mid:toInteger(line.mid),gid:toInteger(line.gid)}]->(to)

Neo4j - Java简介

Neo4j提供JAVA API以编程方式执行所有数据库操作。

它支持两种类型的API:

  • Neo4j的原生的Java API
  • Neo4j Cypher Java API

Neo4j原生Java API是一种低级别的纯JAVA API,用于执行数据库操作。 Neo4j Cypher Java API是简单而强大的JAVA API,用于执行所有CQL命令以执行数据库操作。

Neo4j Java架构

下图显示了Neo4j JAVA API应用程序的体系结构
在这里插入图片描述
客户端程序使用Neo4j Java API之一来在Neo4j数据库上交互和执行数据库操作。

Neo4j - 原生Java API

使用idea创建SpringBoot的项目。

1、引入依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chengkun</groupId>
    <artifactId>springboot-neo4j</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-neo4j</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <!-- 集成springboot web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 集成springboot test组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 集成lombok 框架 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <!-- 服务器开发需要的jar包 -->
            <groupId>org.neo4j.driver</groupId>
            <artifactId>neo4j-java-driver</artifactId>
            <version>1.5.0</version>
        </dependency>
        <dependency>
            <!-- 嵌入式开发需要的jar包 -->
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j</artifactId>
            <version>3.5.4</version>
        </dependency>
        <!-- 文件上传组件 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>[1.3.3,)</version>
        </dependency>
        <!--阿里巴巴 fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.56</version>
        </dependency>
        <!-- 引入Spring封装的jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- 引入mysql数据库连接驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- 引入 Druid 数据源依赖:https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.xmlunit</groupId>
            <artifactId>xmlunit-core</artifactId>
        </dependency>
        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- google java lib -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>[24.1.1,)</version>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <id>base</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <package.environment>base</package.environment>
            </properties>
        </profile>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <package.environment>dev</package.environment>
            </properties>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <package.environment>test</package.environment>
            </properties>
        </profile>
    </profiles>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <mainClass>com.chengkun.neo4j.SpringbootNeo4jApplication</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>
                                ${project.build.directory}\lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                    <encoding>utf8</encoding>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/**</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.tld</include>
                    <include>**/*.doc</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <!--不对excel模板过滤-->
                    <include>**/*.xlsx</include>
                    <include>**/*.xls</include>
                </includes>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.yml</exclude>
                    <exclude>**/*.xml</exclude>
                    <exclude>**/*.tld</exclude>
                    <exclude>**/*.doc</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

</project>

2、配置文件application.yml

server:
  port: 8080
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 5
      min-idle: 5
      max-active: 20
      max-wait: 60000
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 1 FROM DUAL
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall,lombok
      max-pool-prepared-statement-per-connection-size: 20
      use-global-data-source-stat: true
      connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  #easypoi配置
  main:
    allow-bean-definition-overriding: true
#mybatis配置
mybatis:
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: classpath*:com/chengkun/**/*Mapper.xml
  type-aliases-package: com.chengkun.entity
#日志
logging:
  config: classpath:logback-spring.xml
#########其他配置##########
##主要用于加载接口程序需要的配置信息到内存中使用 product为加载生产配置 可配置test,product,dev
environment:  dev
# 开启swagger
swagger:
  enabled:  true
# neo4j数据库地址
neo4j:
  db_neo4j: D:\neo4j-community-3.5.4-windows\data\databases\graph.db

3、创建节点标签枚举:

package com.chengkun.neo4j.entity;

import org.neo4j.graphdb.Label;

/**
 * 自定义节点标签
 *
 * @author chengkun
 * @version v1.0
 * @create 2021/3/29 14:59
 **/
public enum MyLabel implements Label {
    JAVA, SCALA, SQL, NEO4J;
}

4、创建关系类型枚举

package com.chengkun.neo4j.entity;

import org.neo4j.graphdb.RelationshipType;

/**
 * 自定义关系类型
 *
 * @author chengkun
 * @version v1.0
 * @create 2021/3/29 15:00
 **/
public enum MyRelationshipType implements RelationshipType {
    JVM_LANGIAGES, NON_JVM_LANGIAGES;
}

5、noe4j参数实体类

package com.chengkun.neo4j.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author chengkun
 * @version v1.0
 * @create 2021/3/29 19:09
 **/
@Data
@ApiModel(description = "neo4j参数实体类")
public class Code {
    @ApiModelProperty(value = "id")
    private String id;
    @ApiModelProperty(value = "节点")
    private String node;
    @ApiModelProperty(value = "关系")
    private String relation;
    @ApiModelProperty(value = "属性")
    private String property;
    @ApiModelProperty(value = "节点标签")
    private String label;
    @ApiModelProperty(value = "边起点id")
    private String nodeFromId;
    @ApiModelProperty(value = "边起点标签")
    private String nodeFromLabel;
    @ApiModelProperty(value = "边终点id")
    private String nodeToId;
    @ApiModelProperty(value = "边终点标签")
    private String nodeToLabel;
    @ApiModelProperty(value = "条件语句")
    private String where;
    @ApiModelProperty(value = "修改语句")
    private String update;
    @ApiModelProperty(value = "返回结果")
    private String result;

}

6、初始化neo4j数据库bean

package com.chengkun.neo4j.config;

import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.File;

/**
 * @author chengkun
 * @version v1.0
 * @create 2021/3/29 15:16
 **/
@Configuration
public class Neo4jConfig {

    @Value(value = "${neo4j.db_neo4j}")
    private String dbNoe4j;

    @Value(value = "${neo4j.neo4j_url}")
    private String noe4jUrl;

    @Value(value = "${neo4j.username}")
    private String username;

    @Value(value = "${neo4j.password}")
    private String password;

    //使用内嵌式数据库
    @Bean
    public GraphDatabaseService getGraphDatabaseService() {
        GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
        GraphDatabaseService db = dbFactory.newEmbeddedDatabase(new File(dbNoe4j));
        return db;
    }

    //使用服务器式数据库
    @Bean
    public Driver getDrive() {
        return GraphDatabase.driver(noe4jUrl, AuthTokens.basic(username, password));
    }
}

7、创建neo4j操作Controller

package com.chengkun.neo4j.controller;

import com.chengkun.neo4j.entity.Code;
import com.chengkun.neo4j.entity.MyLabel;
import com.chengkun.neo4j.entity.MyRelationshipType;
import io.swagger.annotations.*;
import lombok.extern.log4j.Log4j2;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.Record;
import org.neo4j.driver.v1.Session;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.graphdb.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

import static org.neo4j.driver.v1.Values.parameters;

/**
 * @author chengkun
 * @version v1.0
 * @create 2021/3/29 15:32
 **/
@Api(tags = "neo4j增删改查")
@RestController
@Log4j2
@RequestMapping("/neo4j")
public class Neo4jController {

    @Autowired
    private GraphDatabaseService graphDB; //使用内嵌式数据库

    @Autowired
    private Driver driver; //使用服务器式数据库(推荐)

    @ApiOperation(value = "创建数据(使用内嵌式数据库)")
    @GetMapping(value = "/create", produces = "application/text;charset=UTF-8")
    public String create() {
        Transaction tx = graphDB.beginTx();
        try {
            Node java = graphDB.createNode(MyLabel.JAVA);
            java.setProperty("id", 1);
            java.setProperty("name", "java");
            Node c = graphDB.createNode(MyLabel.C);
            c.setProperty("id", 2);
            c.setProperty("name", "c");
            Node python = graphDB.createNode(MyLabel.PYTHON);
            python.setProperty("id", 3);
            python.setProperty("name", "python");
            Node scala = graphDB.createNode(MyLabel.SCALA);
            scala.setProperty("id", 4);
            scala.setProperty("name", "scala");
            Node mysql = graphDB.createNode(MyLabel.MYSQL);
            mysql.setProperty("id", 5);
            mysql.setProperty("name", "mysql");
            Node neo4j = graphDB.createNode(MyLabel.NEO4J);
            neo4j.setProperty("id", 6);
            neo4j.setProperty("name", "neo4j");
            Relationship javaMysql = java.createRelationshipTo(mysql, MyRelationshipType.JVM_LANGIAGES);
            javaMysql.setProperty("id", 1);
            javaMysql.setProperty("name", "java连接mysql");
            Relationship cMysql = c.createRelationshipTo(mysql, MyRelationshipType.NON_JVM_LANGIAGES);
            cMysql.setProperty("id", 2);
            cMysql.setProperty("name", "c连接mysql");
            Relationship pythonMysql = python.createRelationshipTo(mysql, MyRelationshipType.NON_JVM_LANGIAGES);
            pythonMysql.setProperty("id", 3);
            pythonMysql.setProperty("name", "python连接mysql");
            Relationship javaNeo4j = java.createRelationshipTo(neo4j, MyRelationshipType.JVM_LANGIAGES);
            javaNeo4j.setProperty("id", 4);
            javaNeo4j.setProperty("name", "java连接neo4j");
            Relationship scalaNeo4j = scala.createRelationshipTo(neo4j, MyRelationshipType.NON_JVM_LANGIAGES);
            scalaNeo4j.setProperty("id", 5);
            scalaNeo4j.setProperty("name", "scala连接neo4j");
            tx.success();
        } finally {
            tx.close();
        }
        return "创建成功";
    }

    @ApiOperation(value = "根据id查询节点(使用内嵌式数据库)")
    @GetMapping(value = "/getNode", produces = "application/text;charset=UTF-8")
    public String getNode(@RequestParam("id") Integer id) {
        Transaction tx = graphDB.beginTx();
        Node node;
        try {
            node = graphDB.findNode(MyLabel.JAVA, "id", id); //这里类型必须与保存的类型一致
            System.out.println(node.getId());
            System.out.println(node.getLabels());
            System.out.println(node.getAllProperties());
            tx.success();
        } finally {
            tx.close();
        }
        return "查询成功";
    }

    @ApiOperation(value = "查看所有(使用内嵌式数据库)")
    @GetMapping(value = "/findAll", produces = "application/text;charset=UTF-8")
    public String findAll() {
        Transaction tx = graphDB.beginTx();
        try {
            for (Node node : graphDB.getAllNodes()) {
                System.out.println(node.getId());
                System.out.println(node.getLabels());
                System.out.println(node.getAllProperties());
                for (Relationship relationship : node.getRelationships()) {
                    System.out.println(relationship.getId());
                    System.out.println(relationship.getType());
                    System.out.println(relationship.getAllProperties());
                }
            }
            tx.success();
        } finally {
            tx.close();
        }
        return "查询成功";
    }


    @ApiOperation(value = "删除节点以及关联的边(使用内嵌式数据库)")
    @GetMapping(value = "/deleteNode", produces = "application/text;charset=UTF-8")
    public String deleteNode(@RequestParam("id") Integer id) {
        Transaction tx = graphDB.beginTx();
        try {
            Node scala = graphDB.findNode(MyLabel.SCALA, "id", id);
            Iterable<Relationship> relationships = scala.getRelationships(MyRelationshipType.NON_JVM_LANGIAGES);
            //删除边
            for (Relationship relationship : relationships) {
                relationship.delete();
            }
            //删除节点
            scala.delete();
            System.out.println("delete ok");
            tx.success();
        } finally {
            tx.close();
        }
        return "删除成功";
    }

    @ApiOperation(value = "修改节点以及关联的边(使用内嵌式数据库)")
    @GetMapping(value = "/updateNode", produces = "application/text;charset=UTF-8")
    public String updateNode(@RequestParam("id") Integer id) {
        Transaction tx = graphDB.beginTx();
        try {
            Node c = graphDB.findNode(MyLabel.C, "id", id);
            Iterable<Relationship> relationships = c.getRelationships(Direction.OUTGOING, MyRelationshipType.NON_JVM_LANGIAGES);
            //修改边
            for (Relationship relationship : relationships) {
                relationship.setProperty("type", "c->out->other");
            }
            //修改节点
            c.setProperty("type", "c语言");
            System.out.println("update ok");
            tx.success();
        } finally {
            tx.close();
        }
        return "修改成功";
    }

    @ApiOperation(value = "删除所有(使用内嵌式数据库)")
    @GetMapping(value = "/deleteAll", produces = "application/text;charset=UTF-8")
    public String deleteAll() {
        Transaction tx = graphDB.beginTx();
        try {
            for (Node node : graphDB.getAllNodes()) {
                for (Relationship relationship : node.getRelationships()) {
                    relationship.delete();
                }
                node.delete();
            }
            tx.success();
        } finally {
            tx.close();
        }
        return "删除所有";
    }

    @ApiOperation(value = "创建数据(使用服务器式数据库)")
    @GetMapping(value = "create1", produces = "application/text;charset=UTF-8")
    public String create1() {

        try {
            Session session = driver.session();

            session.run("CREATE (a:Person {id: {id}, name: {name}, title: {title}})",
                    parameters("id", 1, "name", "Arthur001", "title", "King001"));

            StatementResult result = session.run("MATCH (a:Person) WHERE a.name = {name} RETURN a.id as id,a.name AS name, a.title AS title",
                    parameters("name", "Arthur001"));

            while (result.hasNext()) {
                Record record = result.next();
                System.out.println(record.get("id").asInt() + " " + record.get("title").asString() + " " + record.get("name").asString());
            }

            session.close();
            System.out.println("使用服务器式数据库创建数据成功");
        } catch (Exception e) {
            log.info("使用服务器式数据库创建数据失败");
            return "使用服务器式数据库创建数据失败";
        }
        return "使用服务器式数据库创建数据成功";
    }


    @ApiOperation(value = "修改数据(使用服务器式数据库)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "修改节点id"),
            @ApiImplicitParam(name = "name", value = "修改后的名称"),
    })
    @GetMapping(value = "update", produces = "application/json;charset=UTF-8")
    public void update(@RequestParam("id") Integer id, @RequestParam("name") String name) {
        try {
            Session session = driver.session();
            StatementResult result = session.run("MATCH (a:Person) WHERE a.id={id}  SET a.name = {name} RETURN a.id as id,a.name AS name, a.title AS title",
                    parameters("id", id, "name", name));

            while (result.hasNext()) {
                Record record = result.next();
                System.out.println(record.get("id").asInt() + " " + record.get("title").asString() + " " + record.get("name").asString());
            }

            session.close();
            System.out.println("使用服务器式数据库修改数据成功");
        } catch (Exception e) {
            log.info("使用服务器式数据库修改数据失败");
        }
    }

    @ApiOperation(value = "添加关系(使用服务器式数据库)")
    @PostMapping(value = "relate", produces = "application/json;charset=UTF-8")
    public void relate(@RequestBody Code code) {

        try {
            Session session = driver.session();

            session.run("MATCH (a:" + code.getNodeFromLabel() + "), (b:" + code.getNodeToLabel() + ") " +
                    "WHERE a.id = " + code.getNodeFromId() + " AND b.id = " + code.getNodeToId()
                    + " CREATE (a)-[:" + code.getRelation() + "]->(b)");

            session.close();
            System.out.println("使用服务器式数据库添加边成功");
        } catch (Exception e) {
            log.info("使用服务器式数据库添加边失败");
        }
    }

    @ApiOperation(value = "删除数据(使用服务器式数据库)")
    @GetMapping(value = "delete", produces = "application/text;charset=UTF-8")
    public String delete(@RequestParam("id") Integer id) {
        try {
            Session session = driver.session();
            session.run("match (n:Person) where n.id = {id} delete n",
                    parameters("id", id));

            session.close();
            System.out.println("使用服务器式数据库删除数据成功");
        } catch (Exception e) {
            log.info("使用服务器式数据库删除数据失败");
            return "使用服务器式数据库删除数据失败";
        }
        return "使用服务器式数据库删除数据成功";
    }

    @ApiOperation(value = "删除关系(使用服务器式数据库)")
    @PostMapping(value = "deleteRelate", produces = "application/json;charset=UTF-8")
    public void deleteRelate(@RequestBody Code code) {
        try {
            Session session = driver.session();
            //不知道为什么执行报错
//            session.run("MATCH (a:{NodeFromLabel})-[r:{relation}]->(b:{nodeToLabel}) WHERE a.id={nodeFromId} and b.id={nodeToId} DELETE r",
//                    parameters("NodeFromLabel", code.getNodeFromLabel(), "relation", code.getRelation(), "nodeToLabel", code.getNodeToLabel(), "nodeFromId", code.getNodeFromId(), "nodeToId", code.getNodeToId()));
            session.run("MATCH (a:" + code.getNodeFromLabel() + ")-[r:" + code.getRelation() + "]->(b:" + code.getNodeToLabel() + ") WHERE a.id = " + code.getNodeFromId() + " and b.id = " + code.getNodeToId() + " DELETE r");

            session.close();
            System.out.println("使用服务器式数据库删除数据成功");
        } catch (Exception e) {
            log.info("使用服务器式数据库删除数据失败");
        }
    }

    @ApiOperation(value = "查询数据(使用服务器式数据库)")
    @GetMapping(value = "search", produces = "application/json;charset=UTF-8")
    public List<String> search() {
        List<String> resultList = new ArrayList<>();
        try {
            Session session = driver.session();
            StatementResult result = session.run("match (n) return n.id as id,n.name as name");

            while (result.hasNext()) {
                Record record = result.next();
                resultList.add(record.get("id").toString() + " " + record.get("name").toString());
            }
            session.close();
            System.out.println("使用服务器式数据库查询数据成功");
        } catch (Exception e) {
            log.info("使用服务器式数据库查询数据失败");
        }
        return resultList;
    }


}

注意:
1、使用内嵌式数据库,neo4j界面启动时会锁住整个数据库,这时候java就无法连接这个据库
2、使用服务器形式数据库,可以跟界面进行联调,它比嵌入式配置更安全,推荐使用这种

Neo4j与Spring数据

Spring DATA Neo4J - 架构

下图显示了Spring DATA Neo4j模块的体系结构
在这里插入图片描述

Spring DATA Neo4j存储库
它提供了不同的API来支持不同的场景

  • Neo4jRepository
  • CrudRepository
  • PaginationAndSortingRepository

这些是Java类。 每个具有执行Neo4j数据库操作的特定目的,继承关系是:Neo4jRepository->PaginationAndSortingRepository->CrudRepository

S.No.Spring 数据 Neo4j 类用法
1Neo4jRepository它用于执行Basic Neo4j DB操作。
2CrudRepository它用于使用Cypher查询语言(CQL)执行Neo4j CRUD操作。
3PaginationAndSortingRepository它用于执行Neo4j CQL查询结果的分页和排序。。

Spring Data Neo4j - API

1、添加Spring Data Neo4j相关依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

2、application.yml添加Neo4j环境配置

spring:
  neo4j:
    uri: bolt://localhost:7687
    authentication:
      username: neo4j
      password: neo4j

3、Neo4j中要定义节点,使用Spring Data Neo4j的注解@NodeEntity,标记该类为节点,节点名称为 Student

package com.chengkun.neo4j.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.neo4j.ogm.annotation.*;

import java.util.ArrayList;
import java.util.List;


/**
 * @author chengkun
 * @version v1.0
 * @create 2021/3/30 21:46
 **/
@Data
@NodeEntity("Student")
public class Student{
    /**
     * neo4j 生成的id
     */
    @Id
    @GeneratedValue
    private Long id;
    /**
     * 属性,name
     */
    @Property("name")
    private String name;

    /**
     * 属性,age
     */
    @Property("age")
    private Integer age;

    /**
     * 关系,定义为友谊 指向别人
     */
    @JsonIgnore // 禁止json序列化无限遍历
    @Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.OUTGOING)
    private List<FriendshipRelation> friendshipRelationOutList;

    /**
     * 关系,定义为友谊 指向自己
     */
    @JsonIgnore
    @Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.INCOMING)
    private List<FriendshipRelation> friendshipRelationInList;

    /**
     * 添加友谊的关系
     *
     * @param friendshipRelation
     */
    public void addOutRelation(FriendshipRelation friendshipRelation) {
        if (this.friendshipRelationOutList == null) {
            this.friendshipRelationOutList = new ArrayList<>();
        }
        this.friendshipRelationOutList.add(friendshipRelation);
    }

    /**
     * 添加友谊的关系
     *
     * @param friendshipRelation
     */
    public void addInRelation(FriendshipRelation friendshipRelation) {
        if (this.friendshipRelationInList == null) {
            this.friendshipRelationInList = new ArrayList<>();
        }
        this.friendshipRelationInList.add(friendshipRelation);
    }

}

4、Neo4j也要定义关系,使用Spring Data Neo4j的注解@RelationshipEntity,标记其为关系,关系名为 FRIENDSHIP_RELATION,在里面定义StartNode和EndNode

package com.chengkun.neo4j.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.Setter;
import org.neo4j.ogm.annotation.*;


/**
 * 关系不能有toString方法
 *
 * @author chengkun
 * @version v1.0
 * @create 2021/3/30 22:01
 **/
@Getter
@Setter
@RelationshipEntity(type = "FRIENDSHIP_RELATION")
public class FriendshipRelation {
    @Id
    @GeneratedValue
    private Long id;

    @Property("name")
    private String name;

    @StartNode
    private Student from;

    @EndNode
    private Student to;

}

注意:
JSON序列化注意事项:这里的关系里面有节点,节点里面有关系,造成循环依赖,在序列化中会造成栈溢出,就需要使用@JsonIgnoreProperties或@JsonIgnore进行序列化属性忽略

  • @JsonIgnore:添加到字段上是直接忽略该字段,序列化后就没有该字段,如,在Student的两个关系字段上表示不进行序列化关系字段
 /**
     * 关系,定义为友谊 指向别人
     */
    @JsonIgnore // 禁止json序列化无限遍历
    @Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.OUTGOING)
    private List<FriendshipRelation> friendshipRelationOutList;

    /**
     * 关系,定义为友谊 指向自己
     */
    @JsonIgnore
    @Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.INCOMING)
    private List<FriendshipRelation> friendshipRelationInList;
  • @JsonIgnoreProperties:添加在字段上,并标注不进行序列化的字段,如,在Student的两个关系字段上,并添加忽略序列化的属性,该字段上是FriendshipRelation,所以应该表示FriendshipRelation类不需要序列化的属性,@JsonIgnoreProperties({“from”,
    “to”})
/**
     * 关系,定义为友谊 指向别人
     */
    @JsonIgnoreProperties({"from", "to"}) // 禁止json序列化无限遍历
    @Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.OUTGOING)
    private List<FriendshipRelation> friendshipRelationOutList;

    /**
     * 关系,定义为友谊 指向自己
     */
    @JsonIgnoreProperties({"from", "to"})
    @Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.INCOMING)
    private List<FriendshipRelation> friendshipRelationInList;

5、StudentRepository为数据库操作,因为后面有删除关系,所以需要@Transactional

package com.chengkun.neo4j.repository;

import com.chengkun.neo4j.entity.FriendshipRelation;
import com.chengkun.neo4j.entity.Student;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author chengkun
 * @version v1.0
 * @create 2021/3/31 9:30
 **/
@Transactional
@Repository
public interface StudentRepository extends Neo4jRepository<Student, Long> {

    /**
     * 通过name查找学生node
     *
     * @param name
     * @return
     */
    Student findByName(String name);

    /**
     * 根据name获取学生 out 友谊关系
     *
     * @param name
     * @return
     */
    @Query("match p=(a:Student)-[r:FRIENDSHIP_RELATION]->(b:Student) where a.name = {0} return p")
    List<FriendshipRelation> outFriendship(String name);

    /**
     * 根据name获取学生 in 友谊关系
     *
     * @param name
     * @return
     */
    @Query("match p=(a:Student)<-[r:FRIENDSHIP_RELATION]-(b:Student) where a.name={0} return p")
    List<FriendshipRelation> inFriendship(String name);

    /**
     * 根据name获取学生 both 友谊关系
     *
     * @param name
     * @return
     */
    @Query("match p=(a:Student) <- [r:FRIENDSHIP_RELATION] ->(b:Student) <- [rr:FRIENDSHIP_RELATION] -> (c:Student) where b.name = {0} return p")
    List<FriendshipRelation> bothFriendship(String name);

}

6、创建SpringDataDeo4jController进行测试

package com.chengkun.neo4j.controller;

import com.chengkun.neo4j.entity.FriendshipRelation;
import com.chengkun.neo4j.entity.Student;
import com.chengkun.neo4j.repository.StudentRepository;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author chengkun
 * @version v1.0
 * @create 2021/3/31 10:21
 **/
@Api(tags = "spring-data-neo4j增删改查")
@RestController
@Log4j2
@RequestMapping("/spring-data-neo4j")
public class SpringDataDeo4jController {

    @Autowired
    private StudentRepository studentRepository;

    @ApiOperation(value = " 保存单个节点(使用spring-data-neo4j)")
    @PostMapping(value = "/saveStudentNode", produces = "application/text;charset=UTF-8")
    public String saveStudentNode(String name, int age) {
        Student student = new Student();
        student.setName(name);
        student.setAge(age);
        studentRepository.save(student);
        return "创建成功";
    }

    @ApiOperation(value = "保存批量节点(使用spring-data-neo4j)")
    @GetMapping(value = "saveAllStudentNode", produces = "application/text;charset=UTF-8")
    public String saveAllStudentNode() {
        Student student1 = new Student();
        student1.setName("张三");
        student1.setAge(18);
        Student student2 = new Student();
        student2.setName("李四");
        student2.setAge(19);
        Student student3 = new Student();
        student3.setName("王五");
        student3.setAge(18);
        Student student4 = new Student();
        student4.setName("赵六");
        student4.setAge(20);
        List<Student> list = Lists.newArrayList(student1, student2, student3, student4);
        studentRepository.saveAll(list);
        return "创建成功";
    }

    @ApiOperation(value = "根据name查询学生(使用spring-data-neo4j)")
    @PostMapping(value = "/findStudentByName", produces = "application/json;charset=UTF-8")
    @ApiImplicitParam(name = "name", value = "学生名称")
    public Student findStudentByName(@RequestParam("name") String name) {
        Student student = studentRepository.findByName(name);
        return student;
    }

    @ApiOperation(value = "修改学生名称(使用spring-data-neo4j)")
    @GetMapping(value = "/updateStudentByName", produces = "application/json;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "修改前学生名称"),
            @ApiImplicitParam(name = "updateName", value = "修改后学生名称"),
    })
    public Student updateStudentByName(String name, String updateName) {
        Student student = studentRepository.findByName(name);
        student.setName(updateName);
        studentRepository.save(student);
        return student;
    }

    @ApiOperation(value = "根据名称删除学生(使用spring-data-neo4j)")
    @GetMapping(value = "/deleteStudentByName", produces = "application/json;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "修改前学生名称"),
    })
    public Student deleteStudentByName(String name) {
        Student student = studentRepository.findByName(name);
        studentRepository.delete(student);
        return student;
    }

    @ApiOperation(value = "删除所有学生(使用spring-data-neo4j)")
    @GetMapping(value = "/deleteAllStudent", produces = "application/text;charset=UTF-8")
    public String deleteAllStudent() {
        studentRepository.deleteAll();
        return "删除成功";
    }

    @ApiOperation(value = "查询全部(使用spring-data-neo4j)")
    @GetMapping(value = "/findAll", produces = "application/json;charset=UTF-8")
    public List<Student> findAll() {
        List<Student> studentNodeList = Lists.newArrayList(studentRepository.findAll());
        return studentNodeList;
    }

    /**
     * 分页查询
     */
    @ApiOperation(value = "分页查询(使用spring-data-neo4j)")
    @GetMapping(value = "/pageFindAll", produces = "application/json;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "第几页"),
            @ApiImplicitParam(name = "size", value = "每页条数"),
    })
    public Page<Student> pageFindAll(int page, int size) {
        // page从0开始
        Pageable pageable = PageRequest.of(page - 1, size);
        Page<Student> studentNodePage = studentRepository.findAll(pageable);
        return studentNodePage;
    }

    @ApiOperation(value = "保存友谊关系(使用spring-data-neo4j)")
    @GetMapping(value = "/saveFriendShip", produces = "application/text;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "studentFromName", value = "关系起点名称"),
            @ApiImplicitParam(name = "studentToName", value = "关系终点名称"),
    })
    public String saveFriendShip(String studentFromName, String studentToName) {
        Student studentFrom = studentRepository.findByName(studentFromName);
        Student studentTo = studentRepository.findByName(studentToName);
        FriendshipRelation studentFromToRelation = new FriendshipRelation();
        studentFromToRelation.setName("友谊关系");
        // 添加from
        studentFromToRelation.setFrom(studentFrom);
        //添加to
        studentFromToRelation.setTo(studentTo);
        //只需要在from节点保存关系即可
        studentFrom.addOutRelation(studentFromToRelation);
        studentRepository.save(studentFrom);
        return "保存成功";
    }


    @ApiOperation(value = "保存双向友谊关系(使用spring-data-neo4j)")
    @GetMapping(value = "/saveBrotherFriendShip", produces = "application/text;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name1", value = "学生名称1"),
            @ApiImplicitParam(name = "name2", value = "学生名称2"),
    })
    public String saveBrotherFriendShip(String name1, String name2) {
        Student studentFrom = studentRepository.findByName(name1);
        Student studentTo = studentRepository.findByName(name2);
        FriendshipRelation studentFromToRelation = new FriendshipRelation();
        studentFromToRelation.setName("友谊关系");
        // 添加from
        studentFromToRelation.setFrom(studentTo);
        //添加to
        studentFromToRelation.setTo(studentTo);
        //from->to
        studentFrom.addOutRelation(studentFromToRelation);

        FriendshipRelation studentToFromRelation = new FriendshipRelation();
        studentToFromRelation.setName("友谊关系");
        // 添加from
        studentToFromRelation.setFrom(studentTo);
        //添加to
        studentToFromRelation.setTo(studentFrom);
        //to->from
        studentFrom.addInRelation(studentToFromRelation);
        studentRepository.save(studentFrom);
        return "保存成功";
    }

    @ApiOperation(value = "根据名称查询in关系(使用spring-data-neo4j)")
    @GetMapping(value = "/inFriendshipByName", produces = "application/json;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "学生名称"),
    })
    public List<FriendshipRelation> inFriendshipByName(@RequestParam("name") String name) {
        List<FriendshipRelation> friendshipRelations = studentRepository.inFriendship(name);
        return friendshipRelations;
    }

    @ApiOperation(value = "根据名称查询out关系(使用spring-data-neo4j)")
    @GetMapping(value = "/outFriendshipByName", produces = "application/json;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "学生名称"),
    })
    public List<FriendshipRelation> outFriendshipByName(String name) {
        List<FriendshipRelation> friendshipRelations = studentRepository.outFriendship(name);
        return friendshipRelations;
    }

    @ApiOperation(value = "获取兄弟关系(使用spring-data-neo4j)")
    @GetMapping(value = "/getBrotherFriendShip", produces = "application/json;charset=UTF-8")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "学生名称"),
    })
    public List<FriendshipRelation> getBrotherFriendShip(String name) {
        List<FriendshipRelation> friendshipRelations = studentRepository.bothFriendship(name);
        return friendshipRelations;
    }
}

在这里插入图片描述
总结:

  1. java连接嵌入式数据库,因为是内嵌的,在操作数据库时无法查询数据界面,不太方便,操作使用有点类似jpa。
  2. java连接服务式数据库,需要使用驱动进行连接,完全使用cql语句进行操作,需要打开neo4j的bolt连接端口7687,操作有点类似mybatis。
  3. 使用Spring Data Neo4j连接数据库,支持cql和内置方法,相当于上面两种混合型,需要注意版本问题,这个是Spring Boot的老问题,每个版本差距还是很大的。

源码地址:springboot-neo4j

参考网址:
Neo4j安装及简单使用
W3Cschool-neo4j教程
Neo4j的使用与Java调用实例
Spring Data Neo4j 使用
Sping Data Neo4j官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值