Neo4j
是一个高性能的,
NOSQL
图形数据库,它将结构化数据存储在网络上而不是表中。它是一个
嵌入式的
、
基于磁盘的
、具备
完全的事务
特性的
Java
持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。
Neo4j
也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中——但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。
一、基本概念
1.1 什么是图数据库
图数据库名字的由来其实与其在底层的存储方式有关,Neo4j底层会以图的方式把用户定义的节点以及关系存储起来,通过这种方式,可是高效的实现从某个节点开始,通过节点与节点间关系,找出两个节点间的联系。
从这段描述中可以猜得到,在Neo4j中最重要的两个元素就是节点和关系。说到节点和关系,就必须引出一个非常重要的概念,属性图模型(Property Graph Model)。如下所示:
上图中定义了两个节点,恩比德和蕾哈娜,类别分别是球员和歌手,分别拥有身高,国籍以及生日,血型属性。两个节点之间通过一个“喜欢”关系关联,“喜欢”关系拥有自己的一个属性“自从”,属性值为2014年。
1.2 Neo4j数据库的优势
1.3 Neo4j安装及实践
为了方便大家搭建环境,本文还是会用Docker来运行一个包含Neo4j的容器,Docker下载安装参考 这里 。在下文中会根据之前引用的恩比德大帝的例子来介绍Cypher语句。
从Docker Hub上pull一个Neo4j的镜像
docker pull neo4j
启动一个Neo4j的容器, 需要在你的Home目录下建立一个/neo4j/data文件夹
docker run --publish=7474:7474 --publish=7687:7687 --volume=$HOME/neo4j/data:/data neo4j
在浏览器中访问loalhost:7474可以看到如下的UI界面,输入默认用户名和密码neo4j即可连接到neo4j数据库。
1.5.1 标签(Label)
在Neo4j
中,一个节点可以有一个以上的标签,从现实世界的角度去看,一个标签可以认为节点的某个类别,比如BOOK
、MOVIE
等等。
1.5.2 节点(Node)
节点是指一个实实在在的对象,这个对象可以有好多的标签,表示对象的种类,也可以有好多的属性,描述其特征,节点与节点之间还可以形成多个有方向(或者没有方向)的关系。
1.5.3 关系(Relationship)
用来描述节点与节点之间的关系,这也是图数据与与普通数据库最大的区别,正是因为有这些关系的存在,才可以描述那些我们普通行列数据库所很难表示的网状关系,比如我们复杂的人际关系网,所谓的六度理论,就可以很方便的用图数据库进行模拟,比如我们大脑神经元之间的连接方式,都是一张复杂的网。
有一点需要重点注意,关系可以拥有属性。
1.5.4 属性(Property)
描述节点的特性,采用的是Key-Value
结构,可以随意设定来描述节点的特征。
二、查询语法(CQL)
关键字作用
1. 基本查找match return
neo4j
使用的查询语法是Cypher
语法与我们常用的SQL查询语法不一样,但是在初步的学习之后,觉得他们之间使用的思路有很多重叠的地方,整个语句的执行流程也和SQL有比较多相似的地方。
# 创建两个节点,一个子节点(Mask),一个父节点(Old_mask),他们之间是属于父子关系
# 其中create表示新建
# p 表示这个节点的别名
# PERSON 表示节点p的标签PERSON的属性
# {} 大括号中间的键值对,表示p这个节点作为PERSON这个标签类别所拥有的属性
# -[r:SON_OF]-> 表示节点p指向节点f,他们之间的关系是SON_OF,这个关系的别名是r,r可以拥有属于自己的属性
# return 表示执行这段语句之后,需要返回的对象,return p,r,f 表示返回 节点p,节点f,以及他们之间的关系r
create(p:PERSON {name:"Mask",age:30,heigh:180,weight:80})-[r:SON_OF]->(f:PERSON {name:"OLD_Mask",age:55,heigh:160,weight:60}) return p,r,f
# return 后面的别名p还可以利用as 设置指定的返回值名称,如 p as userName
match (p:PERSON {name:"Mask"})-[r]-(n) return p,r,n
命令执行结果:
where
关键字类似于SQL
里面的where
关键字,可以通过运算符== >= ...
来过滤一些查询条件。
3. 对查找结果进行排序order by,并限制返回条数 limit
order by
关键字与SQL
里面是一样的操作,后面跟上需要根据排序的关键字,limit
的操作是指定输出前几条
# 这里利用order by来指定返回按照Person.name来排序
# limit 表示只返回前3条数据
match(p:Person) return p order by p.name limit 3
查找结果:
4. 删除节点delete命令
删除节点的操作也是通过dlete来操作,如果被删除的节点存在Relationship,那么单独删除该节点的操作会不成功,所以如果想删除一个已经存在关系的节点,需要同时将关系进行删除。
删除一个不存在Relationship节点,会报错:
# 删除指定条件的节点
# 先通过匹配关键字match找到匹配元素,然后通过delete关键字指定删除
match(p:PERSON {name:"teacher_wange"}) delete p
# 删除节点和节点相关的关系
match (p:Person {name:"lisi"})-[r]-() delete p,r
5. 删除属性remove命令
remove命令是用来删除节点或者关系的属性
删除属性前的节点:
6. neo4j的字符串函数
upper
,lower
,substring
,replac
四种字符串的操作,其中upper
与lower
在将来的版本中会被修改为toupper
/tolower
大写转换操作结果:
7. 聚合函数AGGREGATION
常用的聚合函数有COUNT
、MAX
、MIN
、AVG
、SUM
等五种。
match(p:Person) return p.name as name,p.age as age,count(p) as count,max(p.age) as maxAge,min(p.age) as minAge,avg(p.age) as avgAge,sum(p.age) as sumAge
聚合函数操作结果:
# 先获取关系,然后通过关系函数来获取关系的id、type、起始节点、终止节点等等信息
match ()-[r:SON_OF]-() return startnode(r).name as start_node, endnode(r).name as end_node,id(r) as relationship_id ,type(r) as realtionship_type
关系查询结果:
Label接口,表示标签,实现这个接口的类,就可以当标签使用;
Relationship接口,别是关系,实现这个接口的类,就可以表示关系;
通过GraphDatabaseFactory
这个类的实例化对象可以获取GraphDatabaseService
实例;
GraphDatabaseService
实例对象,可以获取一个操作事务,通过这个事务可以实现任何操作异常的回滚,操作成功需要调用tx.success()
方法;
GraphDatabaseService
对象可以创建节点node
;
节点node
可以设置属性setProperty(key,value)
;
节点node
可以创建关系Relationship
,Relationship
也可以通过setProperty(key,value)
来设置属性;
枚举标签Label
package com.tp.ne4oj.java.examples;
import org.neo4j.graphdb.Label;
public enum Tutorials implements Label {
JAVA,SCALA,SQL,NEO4J;
枚举关系Realationship
package com.tp.neo4j.java.examples;
import org.neo4j.graphdb.RelationshipType;
public enum TutorialRelationships implements RelationshipType{
JVM_LANGIAGES,NON_JVM_LANGIAGES;
获取操作对象
GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
GraphDatabaseService db= dbFactory.newEmbeddedDatabase("C:/TPNeo4jDB");
启动neo4j数据库事务
try (Transaction tx = graphDb.beginTx()) {
// Perform DB operations
tx.success();
package com.tp.neo4j.java.examples;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
public class Neo4jJavaAPIDBOperation {
public static void main(String[] args) {
GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
GraphDatabaseService db= dbFactory.newEmbeddedDatabase("C:/TPNeo4jDB");
try (Transaction tx = db.beginTx()) {
Node javaNode = db.createNode(Tutorials.JAVA);
javaNode.setProperty("TutorialID", "JAVA001");
javaNode.setProperty("Title", "Learn Java");
javaNode.setProperty("NoOfChapters", "25");
javaNode.setProperty("Status", "Completed");
Node scalaNode = db.createNode(Tutorials.SCALA);
scalaNode.setProperty("TutorialID", "SCALA001");
scalaNode.setProperty("Title", "Learn Scala");
scalaNode.setProperty("NoOfChapters", "20");
scalaNode.setProperty("Status", "Completed");
Relationship relationship = javaNode.createRelationshipTo
(scalaNode,TutorialRelationships.JVM_LANGIAGES);
relationship.setProperty("Id","1234");
relationship.setProperty("OOPS","YES");
relationship.setProperty("FP","YES");
tx.success();
System.out.println("Done successfully");
3.2 Cypher执行引擎,让Java执行原生CQL语句
package com.tp.neo4j.java.cql.examples;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
public class JavaNeo4jCQLRetrivalTest {
public static void main(String[] args) {
// 1\. 获取graphDB
GraphDatabaseFactory graphDbFactory = new GraphDatabaseFactory();
GraphDatabaseService graphDb = graphDbFactory.newEmbeddedDatabase("C:/TPNeo4jDB");
// 2\. 获取Cypher执行引擎
ExecutionEngine execEngine = new ExecutionEngine(graphDb);
ExecutionResult execResult = execEngine.execute("MATCH (java:JAVA) RETURN java");
// 3\. 获取执行结果
String results = execResult.dumpToString();
System.out.println(results);
3.3 Spring Data neo4j 的操作
操作思路:
创建一个与图数据库存储数据对应的实体类entity
,并进行必要的注解;
dao
层接口继承Spring data Neo4j
类GraphRepository
、GraphTemplate
、CrudRepository
、PaginationAndSortingRepository
,这个和springDataJPA也比较类似;
基本导包操作,pom.xml
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion> 4.0.0 </modelVersion>
<groupId> com.tp.neo4j </groupId>
<artifactId> springdata-neo4j </artifactId>
<version> 1.0 </version>
<dependencies>
<dependency>
<groupId> org.springframework.data </groupId>
<artifactId> spring-data-neo4j </artifactId>
<version> 3.1.2.RELEASE </version>
</dependency>
<dependency>
<groupId> org.neo4j </groupId>
<artifactId> neo4j-kernel </artifactId>
<version> 2.1.3 </version>
</dependency>
<dependency>
<groupId> javax.transaction </groupId>
<artifactId> jta </artifactId>
<version> 1.1 </version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>