谈到数据库,大多数开发工程师首先会想到常用到的 Oracle、MySQL 这类关系型数据,以及 MongoDB、Redis 这类 Nosql 数据库。下面这张图是 2020 年 3 月数据库排行榜(https://db-engines.com/en/ranking),我们可以发现一个名叫 Neo4j 的数据库排名 21,而且是 Graph 类型的图形数据库。

1Neo4j 数据库排行.jpg

下面我们从三个方面来了解下 Neo4j 数据库的特性。

​ 1、Neo4j 是什么

​ 2、Neo4j 能做什么

​ 3、怎么做

2neo4j.png

一、Neo4j 是什么

Neo4j 是一个高性能的 Nosql 图形数据库,用于存储丰富的关系数据,Neo4j 是目前最流行的图形数据库,支持完整的事务,其查询语言 cypher 已经成为事实上的标准。

Neo4j 在一台机器上可以处理数十亿节点/关系/属性的图,相对于关系数据库来说,图数据库善于处理大量复杂、互连接、低结构化的数据,这些数据变化迅速,需要频繁的查询——在关系数据库中,这些查询会导致大量的表连接,因此会产生性能上的问题。

Neo4j 重点解决了拥有大量连接的传统 RDBMS 在查询时出现的性能衰退问题。通过围绕图进行数据建模,Neo4j 会以相同的速度遍历节点与边,其遍历速度与构成图的数据量没有任何关系。

Neo4j 支持 restfulApi 和 bolt 协议交互。

Neo4j 分为社区版和企业版,社区版免费但不支持集群( 官网版本详细对比https://neo4j.com/subscriptions/#editions)。

官网上列出了一些正在使用 Neo4j 的公司:

3whouse.png

4whouse.png

二、关系型数据库难以处理的关系

以 MySQL 为例,当我们处理人员与部门关系的时候,通常的表结构会是下面这样:

create table user(
 id 
 name
 dept_id
);

create table dept(
 id
 dept_name
 parent_id
);

user表

5user表.png

dept表

6dept表.png

当我们需要在前端页面展示小陈同学的部门路径树时,我们后台可以这样做:

1. 查询用户的一级部门ID
	
		select dept_id from user where name = ‘小陈’;

2. 查询一级部门 parent_id 递归向上查询父部门
		
		while (parent_id != null) {
				select id, dept_name from dept where id = parent_id;
				parent_id = id;
		}

这好像并没有什么难度。

7soeasy.png

我们再来看另外一个例子,明星关系的数据库设计:

create table star(
 id 
 name
 fee 
);

create table relation(
 id
 from_star_id 
 to_star_id 
 relation_desc 
);

star表

8start表.png

relation表

9relation表.png

当我们需要查询陈老师和王老师之间是否有关系时,要怎么 select 呢?

此时会发现并不好实现。

10hard.png

三、无处不在的关系

1、社交软件的用户推荐、人脉探索,处处都是关系。

11社交软件.png

2、大佬们的关系图谱,根据六度人脉理论,我们通过几层关系,也许可以要到雷军的微信号呢。

12大佬关系.png

四、Neo4j基础操作

上述的场景就非常符合 Neo4j 的特性,可以解决复杂「关系」的查询。

Neo4j 中的数据有几类对象组成,如下图所示:

  1. Node 节点
  2. Relation 关系
  3. Label 标签
  4. Property 属性

13基础属性.png

我们先来看下 Neo4j 的常用命令和基础语法 CQL。

1    CREATE	
2    MATCH
3    RETURN
4    WHERE
5    DELETE
6    REMOVE
7    ORDER BY
8    SET
//创建一个用户节点
create (n:User{name:'小陈',age:28})

//创建一个部门节点
create (n:Dept {name:'后台研发部',dept_desc:'xxxx'}) 

//创建用户与部门的关系
match (n:User),(t:Dept) where n.name='小陈' and t.name='后台研发部' create (n)-[r:in]->(t)

//创建部门间的关系
match (n:Dept),(t:Dept) where n.name='后台研发部' and t.name='租住O2O中心' create (n)-[r:belong_to]->(t)

match (n:Dept),(t:Dept) where n.name='租住O2O中心' and t.name='研发中心' create (n)-[r:belong_to]->(t)

match (n:Dept),(t:Dept) where n.name='研发中心' and t.name='北京分公司' create (n)-[r:belong_to]->(t)

//查询用户与部门所有的关系
match (n:User),(t:Dept) return n,t 

match p=((n:User)-[*]->(t:Dept)) return t

查一下用户的部门路径树:

match p=((n:User)-[*]->(t:Dept)) return t;

14查询部门.png

下面再演示一个复杂一点的场景,从明星网上爬出一部分明星关系,存到Neo4j数据库中。

整体看下明星之间的关系图:

MATCH (n:Person) RETURN n

15明星关系.png

我们举几个例子来看下 Neo4j 对复杂关系的查询

1、查询陈冠希和谢霆锋之间的关系

MATCH p=((f:Person {name:"陈冠希"})-[*2..3]-(t:Person {name:"谢霆锋"})) return p

16陈谢关系.png

2、查询陈冠希的前女友是谁

MATCH p=((f:Person {name:"陈冠希"})-[r:前女友]->(t:Person)) return p

17陈前友.png

3、查询陈冠希的情敌的前女友是谁

MATCH p=((f:Person {name:"陈冠希"})-[r:情敌]-()-[x:前女友]->(t:Person)) return p

18陈敌前友.png

4、查询蔡依林和赵本山有没有关系

MATCH p=allshortestpaths((f:Person {name:"蔡依林"})-[*]-(t:Person {name:"赵本山"})) return p

19蔡山关系.png

五、总结

上面简单演示了 Neo4j 可以处理的场景,当然我们的常用的应用系统的权限也可以使用 Neo4j 来存储,不论是普通的 CRM 系统,还是维护权限较多的网盘系统、风控系统,用Neo4j都可以轻松应对。

Neo4j 是一个年轻的 Nosql 数据库,在性能和适用场景上有着巨大的优势,我们期待它之后更强劲的表现,说不定未来去 Oracle 的时候,我们会选择 Neo4j。