赞
踩
图形数据库也被称为图形数据库管理系统(GDBMS),现发展比较成熟的图数据库有Neo4j、OracleNoSQL、OrientDB、HypherGraphDB和GraphBase等。
随着社交、电商、金融、零售、物联网等行业的快速发展。现实社会织起了了一张庞大而复杂的关系网,传统数据库很难处理关系运算。大数据行业需要处理的数据之间的关系随数据量呈几何级数增长,急需一种支持海量复杂数据关系运算的数据库,图数据库应运而生。
世界上很多著名的公司都在使用图数据库,比如:
图数据库是基于图论实现的一种NoSQL数据库,其数据存储结构和数据查询方式都是以图论为基础的,图数据库主要用于存储更多的连接数据。
随着技术的发展,我们对数据的需求已经不再局限于对数据本身的获取了,我们还需要获取数据与数据间的关系(也就是连接数据)。
简单地说,我们可以说图数据库主要用于存储更多的连接数据(因为图结构相比其他数据结构而言,能保存更多的数据间的关系)。
如果我们使用 RDBMS 数据库来存储更多连接的数据,那么它们不能提供用于遍历大量数据的适当性能。 在这些情况下,Graph Database 提高了应用程序性能。
Neo4j图数据库遵循属性图模型来存储和管理其数据。
图形数据库数据模型的主要构建块是:
简单的属性图的例子
我简单的罗列一下吧,更多操作,可以参考《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)
我上面简单的罗列了一些常用的增删改查操作,想要深入了解,建议自己先去学习一下。
<!--集成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
#集成neo4j
##配置地址
spring.data.neo4j.uri=bolt://192.168.1.2:7687
## 账号
spring.data.neo4j.username=neo4j
## 密码
spring.data.neo4j.password=123456
下面我们通过创建两个节点,建立节点之间的联系,然后修改节点的标签以及属性值,删除等操作来带大家看看我们的项目里是如何操作图数据库的。
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; } }
我来解释一下上面的注解:
这个类就是我们的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> {
}
下面我们去实际新增一个结点试一下
@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/updateNodeByNamenewName=杨戬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/createRalationExitfrom=杨戬&to=玉皇大帝&relation=舅舅
可以看到关系已经建立成功
相信你读到此处已经有所收获,欢迎在下方评论区讨论。
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。