SpringBoot集成neo4j实战

1.图数据库Neo4j介绍

图形数据库也被称为图形数据库管理系统(GDBMS),现发展比较成熟的图数据库有Neo4j、OracleNoSQL、OrientDB、HypherGraphDB和GraphBase等。

1.1 什么是图数据库(graph database)

随着社交、电商、金融、零售、物联网等行业的快速发展。现实社会织起了了一张庞大而复杂的关系网,传统数据库很难处理关系运算。大数据行业需要处理的数据之间的关系随数据量呈几何级数增长,急需一种支持海量复杂数据关系运算的数据库,图数据库应运而生。

世界上很多著名的公司都在使用图数据库,比如:

  • 社交额域:Facebook,Twitter,Linkedin用它来管理社交关系。实现好友推荐。
  • 零售领域:eBay,沃尔玛使用它实现商品实时推荐。给买家更好的购物体验。全融领域:摩根大通。花旗和瑞银等银行在用图数据库做风控处理。
  • 汽车制造领域:沃尔沃,戴姆勒和丰田等顶极汽车制造商依靠图数据库推动创新制造解决方案。
  • 电信额域:Veriz2数据库来管理网络。控制访问井支持客户360。
  • 酒店领域:万豪和雅高酒店等顶级酒店公司依使用图数据库来管理复杂且快速变化的库存图数据库并非指存储图片的数据库。而是以图数据结构存储和查询数据。

图数据库是基于图论实现的一种NoSQL数据库,其数据存储结构和数据查询方式都是以图论为基础的,图数据库主要用于存储更多的连接数据。

1.2 为什么需要图数据库

随着技术的发展,我们对数据的需求已经不再局限于对数据本身的获取了,我们还需要获取数据与数据间的关系(也就是连接数据)。

简单地说,我们可以说图数据库主要用于存储更多的连接数据(因为图结构相比其他数据结构而言,能保存更多的数据间的关系)。

如果我们使用 RDBMS 数据库来存储更多连接的数据,那么它们不能提供用于遍历大量数据的适当性能。 在这些情况下,Graph Database 提高了应用程序性能。

1.3 Neo4j特点和优势

Neo4j的特点

  • SQL就像简单的查询语言Neo4j CQL
  • 它遵循属性图数据模型
  • 它通过使用Apache Lucence支持索引
  • 它支持UNIQUE约束
  • 它包含一个用于执行CQL命令的UI:Neo4j数据浏览器
  • 它支持完整的ACID(原子性,一致性,隔离性和持久性)规则
  • 它采用原生图形库与本地GPE(图形处理引擎)
  • 它支持查询的数据导出到JSON和XLS格式
  • 它提供了REST API,可以被任何编程语言(如Java,Spring,Scala等)访问
  • 它提供了可以通过任何UI MVC框架(如Node JS)访问的Java脚本
  • 它支持两种Java API:Cypher API和Native Java API来开发Java应用程序

Neo4j的优点

  • 它很容易表示连接的数据
  • 检索/遍历/导航更多的连接数据是非常容易和快速的
  • 它非常容易地表示半结构化数据
  • Neo4j CQL查询语言命令是人性化的可读格式,非常容易学习
  • 使用简单而强大的数据模型
  • 它不需要复杂的连接来检索连接的/相关的数据,因为它很容易检索它的相邻节点或关系细节没有连接或索引

1.4 Neo4j - 数据模型

Neo4j图数据库遵循属性图模型来存储和管理其数据。
图形数据库数据模型的主要构建块是:

  • 节点
  • 关系
  • 属性

简单的属性图的例子

在这里插入图片描述

2.安装Neo4j

3.Neo4j常用sql语句

我简单的罗列一下吧,更多操作,可以参考《Neo4j-w3School》
【增】

# 【增】创建一个标签为Person的节点,节点有一个name属性,属性值为'John'
CREATE (n:Person{name:'John'}) RETURN n
#【增】创建了LIKES关系类型,学生->老师,新节点+新关系+无属性关系 
# 如果已经存在LIKES该关系类型已经存在,不会产生新的关系,但是会新建两个空节点(学生节点和老师节点)
CREATE (n:Student)-[relationship:LIKES]->(m:Teacher) 
RETURN LIKES
# 向现有结点添加关系
match (n:Student),(m:Teacher)
where n.name='王二' and m.name='张三' //增加限制,可不加
create (n)-[r:likes]->(m)  
return n,r,m
其中关系类型为:likes

【删】

#【删】删除姓名为王二的结点
MATCH (n:Person{name:'王二'}) delete n;
# 如果n有关联结点,就无法删除,如果你非要删除,可以使用强制删除
MATCH (n:Person{name:'王二'}) detach  delete n;

#【删】删除所有王二节点的相关关系
MATCH (n:Person{name:'王二'})-[r]-()
DELETE r
#【删】删除节点的所有的向外关系
MATCH (n:Person{name:'王二'})-[r]->()
DELETE r
#【删】删除节点的所有向内关系
MATCH ()-[r]->(n:Person{name:'王二'})
DELETE r
#【删】删除王二节点的所有的LIKES类型的关系
MATCH (n:Person{name:'王二'})-[r:LIKES]-()
DELETE r
#【删】删除王二的地址字段
MATCH (n:Person{name:'王二'})
REMOVE n.address
#【删】删除所有节点和关系
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
DELETE n,r

【改】

#修改节点属性
#【改】修改王二的名字
MATCH (n:Person{name:'王二'})
SET n.name='王八'
#修改节点的标签
#【改】修改王二的Person标签改为Animal
MATCH (n:Person{name:'王二'})
REMOVE n:Person
SET n:Animal
# 修改关系的类型
#【改】修改王二学生对张三老师的LIKES为HATES
MATCH (n:Person)-[r:LIKES]-(m:老师)
WHERE n.姓名='王二' and m.姓名='张三'
CREATE (n)-[r2:HATES]->(m)
DELETE r

【查】

# 查找节点及相关信息
# 查找姓名为王二的学生
match (n:Student) where n.姓名='王二' return n
#查询"王二"节点的所有标签
MATCH (a:Student) where a.姓名='王二' RETURN labels(a)
# 获取“王二”节点的所有属性值
MATCH (a:Student) where a.姓名='王二' RETURN properties(a)
# 获取“王二”节点的所有属性键
MATCH (a:Student) where a.姓名='王二' RETURN keys(a)
# 查找王二所有有关系的老师的姓名
MATCH (n:Student { 姓名 : '王二' })-->(m:老师) 
RETURN m.姓名
# 查找王二所有喜欢的老师的姓名
MATCH (n:学生 { 姓名 : '张三' })-[r:LIKES]->(m:老师)
RETURN m.姓名
# 查询王二喜欢或不喜欢的老师的姓名
MATCH (n:学生 { 姓名 : '张三' })-[r:LIKES|DISLIKES]->(m:老师)
RETURN m.姓名
注意:​{}修饰和where子句修饰是一个意思,只是两种表示形式的问题
# 查找关系 
#获取节点间关系
//查询王二和张三老师间的关系类型 (LIKES)
match(a) where a.姓名='张三' match(b) where b.姓名='王二' match p=(a)-[r]->(b) return type(r)
# 查找关系的所有属性值
//获取“王二”节点的所有属性值 (程度:非常喜欢)
match(a) where a.姓名='张三' match(b) where b.姓名='王二' match p=(a)-[r]->(b) return properties(r)
# 查找节点下的所有属性键
//获取“王二”节点的所有属性键 (程度)
match(a) where a.姓名='张三' match(b) where b.姓名='王二' match p=(a)-[r]->(b) return keys(r)

我上面简单的罗列了一些常用的增删改查操作,想要深入了解,建议自己先去学习一下。

4.SpringBoot集成neo4j

4.1 添加依赖

  <!--集成neo4j-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-neo4j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

我的SpringBoot版本为:2.3.5.RELEASE

在这里插入图片描述

4.2 在application.properties中配置连接信息

#集成neo4j
##配置地址
spring.data.neo4j.uri=bolt://192.168.1.2:7687
## 账号
spring.data.neo4j.username=neo4j
## 密码
spring.data.neo4j.password=123456

下面我们通过创建两个节点,建立节点之间的联系,然后修改节点的标签以及属性值,删除等操作来带大家看看我们的项目里是如何操作图数据库的。

5.实战

5.1 新增实体类

import lombok.Data;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;

import java.io.Serializable;

@Data
@NodeEntity("Person")
public class Person implements Serializable {
    @Id
    @GeneratedValue //设置主键自增
    private Long id;
    @Property
    private String name;

    public Person(String name) {
        this.name = name;
    }
}

我来解释一下上面的注解:

  • @Node表示会创建一个标签,标签名称为Person

5.2 新建持久化类(PersonRepository)

这个类就是我们的dao层,也就是我们和数据库交互的地方

import com.example.neo4j.po.Person;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRepository extends Neo4jRepository<Person, Long> {

}

5.3 测试

下面我们去实际新增一个结点试一下

新增

@RestController
@Slf4j
public class PersonController {
    @Autowired
    PersonRepository personRepository;

    @GetMapping("createNode")
    public Object createNode(@RequestParam(value = "nodeName") String nodeName) {
        Person person=new Person(nodeName);
        return personRepository.save(person);

    }
}

然后我们测试一下

在这里插入图片描述

再看看我们数据库里有没有新增成功

在这里插入图片描述

接下来试试删除

删除

   @GetMapping("deleteNodeById")
    public Object deleteNodeById(@RequestParam(value = "nodeId") Long nodeId) {
        personRepository.deleteById(nodeId);
        return "删除成功";
    }

这是通过id删除,id来自于哪儿呢,我们在数据库里就可以看到

在这里插入图片描述

当然,我们也可以通过name去删除,不过呢需要我们自己去写sql

import com.example.neo4j.po.Person;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRepository extends Neo4jRepository<Person, Long> {
    @Query(value = "MATCH (n:Person {name:$name}) delete n")
    public void deleteByName(String name);

}
    @GetMapping("deleteNodeByName")
    public Object deleteNodeByName(@RequestParam(value = "name") String name) {
        personRepository.deleteByName(name);
        return "删除成功";
    }

自己可以新增几个结点然后测试一下,我就不再截图演示了。

修改

在PersonRepository新增方法:

@Query(value = "MATCH (n:Person {name:$name})set n.name=$newName")
    public void updateNameByName(String name, String newName);

在这里插入图片描述

    @GetMapping("updateNodeByName")
    public Object updateNode(@RequestParam(value = "newName") String newName,
                             @RequestParam(value = "name") String name) {
        personRepository.updateNameByName(name, newName);
        return "编辑成功";
    }

先看看数据库里的数据:

在这里插入图片描述

我们接下来就是需要将杨戬1改为杨戬
测试地址:http://localhost:8080/updateNodeByName?newName=杨戬1&name=杨戬

在这里插入图片描述

可以看到杨戬1已经改成杨戬了

查询

    @GetMapping("getById")
    public Object getById(@RequestParam(value = "id") Long id) {
        Optional<Person> person = personRepository.findById(id);
        Person person1=person.orElse(null);

        return person1;
    }

在这里插入图片描述

当然还有更复杂的查询操作,我们可以通过CQL进行编写,本文只是入门带大家简单了解一下,所以就不在深入去写

我们目前在数据库里看到的是孤零零的点,我们接下来就需要给这些点之间创建联系。

建立联系

我们还是以杨戬为例,我们在创建一个结点:玉鼎真人,同时和杨戬建立师徒关系
1.创建关系结点(PersonRelationShip)

import lombok.Data;
import org.neo4j.ogm.annotation.*;
import java.io.Serializable;

@Data
@RelationshipEntity(type = "PersonRelationShip")
public class PersonRelationShip implements Serializable {
    @Id
    @GeneratedValue //设置主键自增
    private Long id;
    @StartNode
    private Person parent;
    @EndNode
    private Person child;
    @Property
    private String relation;

    public PersonRelationShip(String name) {
        this.name = name;
    }
}

由parent->child
2.创建关系类型(PersonRelationShipRepository)

import com.example.neo4j.po.PersonRelationShip;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRelationShipRepository extends Neo4jRepository<PersonRelationShip, Long> {

}

3.测试

package com.example.neo4j.controller;

import com.example.neo4j.po.Person;
import com.example.neo4j.po.PersonRelationShip;
import com.example.neo4j.repository.PersonRelationShipRepository;
import com.example.neo4j.repository.PersonRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
@Slf4j
public class PersonController {
    @Autowired
    PersonRepository personRepository;
    @Autowired
    PersonRelationShipRepository personRelationShipRepository;
    @GetMapping("createRalation")
    public Object createRalation() {
        Person person1 = new Person("杨戬");
        Person person2 = new Person("玉鼎真人");
        personRepository.save(person1);
        personRepository.save(person2);
        PersonRelationShip personRelationShip = new PersonRelationShip(person1, person2, "师徒");
        return personRelationShipRepository.save(personRelationShip);
    }
}

在这里插入图片描述

在这里插入图片描述

这种方式只能在创建新节点的时候才能建立联系,接下来我们通过sql来对已有的结点创建联系
我们在创建一个结点:玉皇大帝,然后和杨戬建立舅舅关系
我们在PersonRepository中新增一个方法

import com.example.neo4j.po.PersonRelationShip;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRepository extends Neo4jRepository<PersonRelationShip, Long> {
@Query("MATCH (a:Person{name:$from})" +
            "MATCH (b:Person{name:$to}) " +
            "CREATE (a) - [r:西游人物关系{relation:$relation}] -> (b)")
    void relevance(String from, String relation, String to);

}
    @GetMapping("createRalationExit")
    public Object createRalationExit(@RequestParam(value = "from") String from,
                                     @RequestParam(value = "relation") String relation,
                                     @RequestParam(value = "to") String to) {
        personRepository.relevance(from, relation, to);
        return "关系建立成功";
    }

访问:http://localhost:8080/createRalationExit?from=杨戬&to=玉皇大帝&relation=舅舅

在这里插入图片描述

可以看到关系已经建立成功

相信你读到此处已经有所收获,欢迎在下方评论区讨论。

原文地址:https://blog.csdn.net/zhiyikeji

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读752次。关系型数据库关系型数据库是一个结构化的数据库,创建在关系模型(二维表模型)基础上,一般面向于记录SQL语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型数据库中数据的检索和操作主流的关系数据库包括Oracle、Mysql、SQL Server、Microsoft Access、DB2等非关系型数据库NoSQL(nOSQL=Not Only SQL),意思是“不仅仅是SQL”,是非关系型数据库的总称。除了主流的关系型数据库外的数据库,都认为是非关系型主流的NoSQ.._redis是非关系型数据库吗
文章浏览阅读687次,点赞2次,收藏5次。商城系统中,抢购和秒杀是很常见的营销场景,在一定时间内有大量的用户访问商场下单,主要需要解决的问题有两个:1. 高并发对数据库产生的压力;2. 竞争状态下如何解决商品库存超卖;高并发对数据库产生的压力对于第一个问题,使用缓存来处理,避免直接操作数据库,例如使用 Redis。竞争状态下如何解决商品库存超卖对于第二个问题,需要重点说明。常规写法:查询出对应商品的库存,判断库存数量否大于 0,然后执行生成订单等操作,但是在判断库存是否大于 0 处,如果在高并发下就会有问题,导致库存_php库存结余并发
文章浏览阅读1.4k次。MongoTemplate开发spring-data-mongodb提供了MongoTemplate和MongoRepository两种方式访问MongoDB,MongoRepository的方式访问较为简单,MongoTemplate方式较为灵活,这两种方式在Java对于MongoDB的运用中相辅相成。_springboot插入指定的mongodb数据库
文章浏览阅读887次,点赞10次,收藏19次。1.背景介绍1. 背景介绍NoSQL数据库是一种非关系型数据库,它的特点是可以存储非结构化的数据,并且可以处理大量的数据。HBase是一个分布式、可扩展的列式存储系统,它是基于Google的Bigtable设计的。HBase是一个开源的NoSQL数据库,它的核心功能是提供高性能的随机读写访问。在本文中,我们将对比HBase与其他NoSQL数据库,例如Redis、MongoDB、Cass...
文章浏览阅读819次。MongoDB连接失败记录_edentialmechanisn-scram-sha-1
文章浏览阅读470次。mongodb抽取数据到ES,使用ELK内部插件无法获取数据,只能试试monstache抽取mongodb数据,但是monstache需要mongodb replica set 模式才能采集数据。############monstache-compose文件。#replicas set 启动服务。# 默认备份节点不能读写,可以设置。# mydb指的是需要同步的数据库。#登录主mongodb初始化rs。#primary 创建用户。# ip地址注意要修改。# ip地址注意要修改。_monstache csdn
文章浏览阅读913次,点赞4次,收藏5次。storage:fork: trueadmin登录切换数据库注意: use 代表创建并使用,当库中没有数据时默认不显示这个库删除数据库查看表清单> show tables # 或者 > show collections表创建db.createCollection('集合名称', [options])table1字段类型描述capped布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。_mongodb5
文章浏览阅读862次。Centos7.9设置MongoDB开机自启(超全教程,一条龙)_mongodb centos开机启动脚本
文章浏览阅读1.3k次,点赞6次,收藏21次。NoSQL数据库使用场景以及架构介绍
文章浏览阅读856次,点赞21次,收藏20次。1.背景介绍1. 背景介绍NoSQL数据库是一种非关系型数据库,它的设计目标是为了解决传统关系型数据库(如MySQL、Oracle等)在处理大量不结构化数据方面的不足。NoSQL数据库可以处理大量数据,具有高性能、高可扩展性和高可用性。但是,与关系型数据库不同,NoSQL数据库没有固定的模式,数据结构也不一定是表格。在NoSQL数据库中,数据存储和查询都是基于键值对、列族、图形等不同的...
文章浏览阅读416次。NoSQL定义:非关系型、分布式、开放源码和具有横向扩展能力的下一代数据库。由c++编写的开源、高性能、无模式的基于分布式文件存储的文档型数据库特点:高性能、高可用性、高扩展性、丰富的查询支持、可替换已完场文档某个指定的数据字段应用场景:社交场景:使用mongodb存储用户信息游戏场景:用户信息,装备积分物流场景:订单信息,订单状态场景操作特点:数据量大;读写操作频繁;价值较低的数据,对事物性要求不高开源、c语言编写、默认端口号6379、key-value形式存在,存储非结构化数据。_nosql
文章浏览阅读1.5k次,点赞3次,收藏2次。Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket. at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:110) at redis.clients.jedis.Connection.connect(Conne_redis.clients.jedis.exceptions.jedisconnectionexception: failed to create so
文章浏览阅读6.5k次,点赞3次,收藏12次。readAnyDatabase(在所有数据库上都有读取数据的权限)、readWriteAnyDatabase(在所有数据库上都有读写数据的权限)、userAdminAnyDatabase(在所有数据库上都有管理user的权限)、dbAdminAnyDatabase(管理所有数据库的权限);:clusterAdmin(管理机器的最高权限)、clusterManager(管理和监控集群的权限)、clusterMonitor(监控集群的权限)、hostManager( 管理Server);_mongodb创建用户密码并授权
文章浏览阅读593次。Redis是一个基于内存的键值型NoSQL数据库,在实际生产中有着非常广泛的用处_搭建本地redis
文章浏览阅读919次。Key 的最佳实践[业务名]:[数据名]:[id]足够简短:不超过 44 字节不包含特殊字符Value 的最佳实践:合理的拆分数据,拒绝 BigKey选择合适数据结构Hash 结构的 entry 数量不要超过 1000(默认是 500,如果达到上限则底层会使用哈希表而不是 ZipList,内存占用较多)设置合理的超时时间批量处理的方案:原生的 M 操作Pipeline 批处理注意事项:批处理时不建议一次携带太多命令。Pipeline 的多个命令之间不具备原子性。_redis高级实战
文章浏览阅读1.2k次。MongoDB 递归查询_mongodb数据库 递归
文章浏览阅读1.2k次。通过实际代码例子介绍:如何通过MongoTemplate和MongoRepository操作数据库数据_springboot操作mongodb
文章浏览阅读687次,点赞7次,收藏2次。首先欢迎大家阅读此文档,本文档主要分为三个模块分别是:Redis的介绍及安装、RedisDesktopManager可视化工具的安装、主从(哨兵)模式的配置。_redis 主从配置工具
文章浏览阅读764次。天下武功,无坚不摧,唯快不破!我的名字叫 Redis,全称是 Remote Dictionary Server。有人说,组 CP,除了要了解她外,还要给机会让她了解你。那么,作为开发工程师的你,是否愿意认真阅读此心法抓住机会来了解我,运用到你的系统中提升性能。我遵守 BSD 协议,由意大利人 Salvatore Sanfilippo 使用 C 语言编写的一个基于内存实现的键值型非关系(NoSQL)..._redis 7.2 源码
文章浏览阅读2k次。MongoDB 的增删改查【1】_mongodb $inc