图数据库 
在关系数据库中,数据及其联系被分散存储到许多基本表中,这导致难以发现数据之间
的关联关系,也难以进行知识发现和知识推理。为了对现实世界中事物间的关系进行建模, 
图数据库应运而生,它被越来越多地用来描述体量巨大的实体及其联系,尤其是近年来知识
图谱和属性网络的研究,图数据库被用来存储实体及其关系,为知识推理提供了强有力的支
持。Neo4j是当前较流行的图数据库,支持事务特性和分布式集群架构,并提供了功能强大
的查询语言和图分析算法。本章将主要介绍图基本概念、图数据模型、Neo4j概述和Neo4j 
查询语言等内容。
5.1 图的基本概念
图是一种数据结构,能够对一组实体及其关系建模,其中实体是图中的节点,关系是图
中的边。本节将围绕这两个基本概念对图的相关概念进行介绍,这些内容对于理解图数据
库非常重要。
5.1.1 节点
节点(Node)也称顶点(Vertex),是图的基本元素之一。节点的总数量称为图的阶。现
实世界能够相互区别的事物都可以表示为图的节点,如作者、论文、客户、商品、公司和城市
等。例如,图5-1(a)所示的论文发表关系图包括作者和论文两类节点,每个作者节点代表一
个实体,每个论文节点也代表一个实体,且这些实体可以相互区别。图5-1(b)所示的病毒
传播关系图,每个感染者都是一个实体。
节点一般具有一个或多个标签,用来表示节点的类型,图5-1(a)的节点“刘英”的标签是
“作者”,节点“论文1”的标签是“论文”。节点也可以有一组属性,作者节点可以有姓名、性
别、职称、工作单位、研究领域等属性。
5.1.2 边
边(Edge)是实体之间的关系(联系)。与某节点相连的边的数量称为该节点的度数,图
中边的总数量称为图的尺寸。在图5-1(a)中,作者“刘英”发表了“论文1”,那么在节点“刘
英”和节点“论文1”之间就存在一条边。通过“边”能够直观地表达实体之间的关系。
边可以有类型、属性、权重、方向等其他辅助信息。首先,边是有类型的,如发表关系、购
买关系、合作关系等,代表关系的类型;其次,边也可以有属性,如发表关系中作者排序、是否
5

边也可以有权重,权重是关系重要性的度量,如距
如果所有边都有方向,则称为有向图,如果所有边
边的起始节点称为头节点,结束节点称为尾节点。
是一个有向图。

2 无向图和有向图

而有些关系却是隐含的。比如两个作者共同发
那么这两个作者和这篇论文都有一条边。根据这两个边,通过知识推理可以
也就是这两个作者之间也存在一条边。基于已有关系预测可
反映在图上就是节点间关系的“补全”,这是图的一个重

到另一个节点(结束节点)途径的所有节点组成的
包含开始节点和结束节点)。路径长度是指序列中边的个数。如果路径中第一个节点
(或“环”)。如果路径中各节点都不重复,那么
除第一个节点和最后一个节点,若回路中的其他节点互

简单环”)。
则称这两个顶点是连通的。例
但从N1 到N3 存在两条路径,分别是
因此称N1 和N3 之间是连通的。

110
图5-1 两个关系图示例
通信作者等都可以作为边的属性;再次, 
离、成本、时间等;最后,边还可以有方向, 
都没有方向,则称为无向图。在有向图中, 
图5-2(a)是一个无向图,而图5-2(b) 
图5-
现实中,有些关系是以显式方式存在的, 
表了一篇论文, 
得知这两个作者是合作关系, 
能存在关系的过程称为“链接预测”, 
要应用。
5.1.3路径
路径(Path)是从一个节点(开始节点)
序列(
和最后一个节点相同,那么此路径称为“回路”
此路径又被称为“简单路径”;同样, 
不重复,则此回路被称为“简单回路”(或“ 
如果图中从一个节点到另一个节点至少存在一条路径, 
如图5-3(a)中,虽然节点N1 和N3 没有直接关联, 
N1-N2-N3 和N1-N4-N3, 

1 11 
图5-3 连通图与强连通图
在无向图中,如果任意两个顶点之间都存在一条路径,则称该无向图为连通图。在有向
图中,对任意两个节点Ni和Nj,满足从Ni到Nj 以及从Nj 到Ni都连通,也就是都含有至
少一条通路,则称该有向图为强连通图。图5-3(b)就是一个强连通图,任意两个节点之间
都存在一个通路。
5.1.4 遍历
图的遍历(Traversal)是从指定的节点出发按照某种策略沿着边访问所有节点,使每个
节点仅被访问一次,这个过程称为图的遍历。遍历过程中得到的节点序列称为遍历序列。
根据遍历策略方法的不同,分为深度优先搜索(DFS)和广度优先搜索(BFS)。
深度优先搜索是从某个节点出发,首先访问该节点,然后依次从它的各个未被访问的邻
接点出发深度优先搜索遍历图,直至图中所有和该节点有路径相通的节点都被访问到;若此
时尚有其他节点未被访问到,则另选一个未被访问的节点作起始点,重复上述过程,直至图
中所有节点都被访问到为止。图5-2(a)按深度优先策略遍历的一个序列是:1-2-3-6-5-4。
广度优先搜索是从图中某节点出发,在访问了该节点之后,依次访问该节点的所有邻接
点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得先被访问的节点的邻接点先
于后被访问的节点的邻接点被访问,直至图中所有已被访问的节点的邻接点都被访问到;如
果此时图中尚有节点未被访问,则需要另选一个未曾被访问过的节点作为新的起始点,重复
上述过程,直至图中所有节点都被访问到为止。图5-2(a)按宽度优先策略遍历的一个序列
是:1-2-3-4-6-5。
图数据库(如Neo4j)提供了一套高效的遍历算法(API),可以指定遍历规则,然后自动
按照遍历规则进行遍历,并返回遍历结果。
5.2 图数据模型
图数据库(GraphDatabase)是基于图论开发的一种NoSQL数据库,无论是数据存储, 
还是数据操作,都以图论为基础,通过直观的方式建模客观事物之间的复杂关系。图中的基
本元素包括节点和边,分别对应现实世界中的实体和关系(也称为联系)。图数据库的基本
任务是对图中的节点和关系进行创建、读取、更新、删除、查询和分析等。
图数据模型定义了图中节点和关系的建模、存储和实现方法。常用的图数据模型包括
三种:属性图模型、三元组模型和超图模型。

1 12 
5.2.1 属性图模型
属性图模型是一种常用且比较直观的图数据模型,本章介绍的Neo4j图数据库就采用
了该模型。属性图的主要特点如下。
(1)属性图由节点和关系(联系)组成。
(2)节点可以有多个属性和属性值(键值对)。
(3)节点可以有一个或多个标签。
(4)关系只有一个类型,并总是从一个开始节点指向一个结束节点。
(5)关系也可以有多个属性和属性值(键值对)。
属性图能够比较方便地存储图数据。图5-4是由电影、演员、导演等实体及其关系构成
的一个图,节点就是各类实体,边就是实体间的关系。
图5-4 电影关系属性图模型
采用属性图模型,可以通过以下方式对图5-4所示的属性图进行存储。
(1)节点集合
节点N ={n1,n2,n3,n4}。
(2)关系集合
关系E={e1,e2,e3,e4},其中e1=(n1,n2),e2=(n1,n2),e3=(n3,n2),e4= 
(n4,n2)。
(3)节点标签集合
Label(n1)=Director,Label(n2)=Movie,Label(n3)=Actor,Label(n4)=Actor。
(4)关系类型集合
Type(e1)=directs,Type(e2)=acts_in,Type(e3)=acts_in,Type(e4)=acts_in。
(5)属性集合
Attr(n1,name)=J' amesCameron', Attr(n1,birthDate)=1954-08-16, 
Attr(n1,networth)=1.79E9, Attr(n2,name)=' Titanic(1997film)', 
Attr(n2,length)=195, Attr(n2,budget)=2.0E8 
Attr(n3,name)= 'LeonardoDiCaprio', Attr(n3,birthDate)=1974-11-11 
Attr(n4,name)= ' KateWinslet', Attr(n3,birthDate)=1975-10-05 
Attr(e2,role)=S' teerageDancer', Attr(e3,role)=J' ackDawson', 
Attr(e4,role)=' RoseDeWitt'。

5.2 
三元组模型
2.
三元组模型是另外一种重要的图数据模型,包含主谓宾的数据结构。通过三元组表达
实体与实体之间的关系,或者属性与属性值之间的关系,有以下两种形式。

.(实体,关系,实体):该三元组表达了实体与实体的关系,分别称为头实体和尾
实体; 
.(实体,属性,属性值): 该三元组表达了实体与属性之间的关系。
图5-5 电影关系三元组模型

图5-4的属性图模型可以转换为图5-5所示的三元组模型,按以下三元组方式存储。
(1)(_n,f:r), 

JamesCamerordtype,Directo

(2)(James_Cameron,name,JamesCameron), 

(3)(James_Cameron,birthDate,1954-08-16), 

(4)(Jame_Crn,ntrh,1.

sameoewot79E9), 

(5)(James_Cameron,directs,Titanic), 

(6)(James_Cameron,acts_in,Titanic), 

(7)(tnc,dte,Moi

Tiairf:ypve), 

(8)(Titanic,length,195), 

(9)(Titanic,name,Titanic(1997film)), 

(10)(tnc,udgt,0E8), 

Tiaibe2.

(11)(Leonardo_DiCaprio,name,LeonardoDiCaprio), 

(12)(Leonardo_DiCaprio,birthDate,1974-11-11), 

LeonardoDiCaprirdtypcto

(13)(_o,f:e,Ar)
,
(14)(Leonardo_DiCaprio,acts_in,Titanic)
,
(15)(Kate_Winslet,name,KateWinslet)
,
(16)(Kate_Winslet,birthDate,1975-10-05)
,
(17)(t_nlt,dte,Aco


KaeWiserf:yptr)
,
(18)(Kate_Winslet,acts_in,Titanic)
。


2.超图模型
5.3 
超图是一种广义的图数据模型,它允许一条边关联任意数量的节点,无论是开始节点还

113 


1 14 
是结束节点,这样的边称为超边。相比于属性图,超图更适合对多对多关系进行建模,通过
超边进行关联。如图5-6(a)所示,通过属性图对学生和课程的多对多选修关系进行建模,每
个学生可以选修多门课,同样每门课程可以有多个学生选修。图5-6(b)通过超图对多对多
的选修关系进行建模,共有1个超边,该超边的开始节点有两个,结束节点有三个。
图5-6 属性图和超图的比较
5.3 Neo4j 概述
5.3.1 特点 
目前主流的图数据库有Neo4j,FlockDB,GraphDB,InfiniteGraph,Titan,JanusGraph, 
Pregel等,这些图数据库主要采用属性图数据模型。Neo4j是一个基于Java语言开发的图
数据库,适用于大量复杂、互连接、低结构化的数据,避免了由于连接操作产生的性能问题, 
其特点如下。
(1)高性能。与关系数据库的关系查询相比,图数据库直接将所有的关系放在实体的
列表中,避免了在关系数据库中频繁地通过连接操作进行关系查询的问题,提高了查询
性能。
(2)高可用性。Neo4j企业版可以部署在集群中,在硬件设备损坏的情况下使数据库
具备完善的数据可读写能力,具有比单台数据库处理更多的负载处理能力。
(3)ACID 事务特性。能够通过事务的提交和回复确保数据提交的正确性和一致性,此
外,也可以通过日志对数据进行恢复。
(4)图分析算法库。这些算法帮助用户分析图数据中的隐藏模式和结构,用户不必关
心这些算法的实现细节,典型的算法如广度优先搜索算法、深度优先搜索算法、最小权重生
成树(MWST)算法等。
(5)REST服务接口。Neo4j图数据库除了提供基于Java的客户端驱动包外,同时也支
持REST服务访问它,使得任何支持HTTP访问的编程语言都可以使用REST 服务访问
图数据库。
5.3.2 免索引邻接
Neo4j采用免索引邻接技术提高图数据的操作性能。假设在一个关系数据库中设计了
三个基本表,分别用来存储作者信息、发表信息和论文信息,如图5-7所示。在发表信息表
中,列Rno和Pno分别是外键。那么,在查询某个学者发表了哪些论文时,需要通过两个外

1 15 
键将这些基本表连接起来。连接操作(Join)将这些数据读入内存,一旦涉及的数据量较大, 
I/O 访问延迟就会成为一个关键瓶颈。为了提高性能,通常在外键上建立索引,通过建立索
引进行查询的时间复杂度为O(log(n)),这表示随着作者数量和论文数量的增加,查询时间
也随之增加。
图5-7 作者与论文之间的发表关系
图数据库通过边建立节点间的多对多联系,不需要通过连接操作进行数据查询。免索
引邻接技术为每个节点维护了一个与该节点直接关联的节点、关系和属性双向链表,这样, 
根据节点即可快速地查找其关联的节点、关系和属性,提高了查询性能,时间复杂度降低为
O(1)。免索引邻接技术的优势是查询性能不会受节点和关系数量影响,每次遍历仅与该节
点所涉及的数据集有关,不会随着节点数的增加而增加。
5.3.3 存储结构
Neo4j图数据库主要有三种重要的对象,包括节点、关系和数学,下面介绍它们的存储
结构。
1. 节点存储结构
在Neo4j图数据库中,用来存储节点的文件是neostore.nodestore.db,该文件以记录形
式保存了所有节点,每个节点记录的长度大小固定,均为9B,格式为 
Node:inUse+nextRelId+nextPropId 
.inUse:若该项的值是1,则表示该节点被正常使用;若该项的值是0,则表示该节点
被删除,占1B。
. nextRelId:用来存储该节点的下一个关系ID,整数,占4B。
. nextPropId:用来存储该节点的下一个属性ID,整数,占4B。
图5-8 节点的物理存储结构
节点的物理存储结构如图5-8所示。
2. 关系存储结构
用来存储关系的文件名是neostore.relationshipstore.
db,该文件也以记录形式保存了所有关系, 
每个关系记录的长度大小固定,均为33B,格式为

1 16 
Relationship: inUse+firstNode+secondNode+relType+firstPrevRelId 
+firstNextrelId+secondPrevRelId +secondNextRelId+nextPropId 
.inUse:若该项的值是1,则表示该关系被正常使用;若该项的值是0,则表示该关系
被删除,占1B。
.firstNode:该关系的开始节点,整数,占4B。
.secondNode:该关系的结束节点,整数,占4B。
.relType:该关系的类型,整数,占4B。
.firstPrevRelId:开始节点的前一个关系ID,整数,占4B。
.firstNextRelId:开始节点的后一个关系ID,整数,占4B。
.secondPrevRelId:结束节点的前一个关系ID,整数,占4B。
.secondNextRelId:结束节点的后一个关系ID,整数,占4B。
. nextPropId:关系的最近属性ID,整数,占4B。
上述前后关系是在添加的时候自然形成的。如果关系是最开始添加的,则没有前一个
关系;如果关系是最后一个添加的,则没有后一个关系;其他中间添加的关系都应该有前一
个关系和后一个关系;由此,这些先后添加的关系将形成一个列表。
关系的物理存储结构如图5-9所示。
图5-9 关系的物理结构
3. 属性存储结构
用来存储属性的文件名是neostore.propertystore.db,该文件也以记录形式保存了所有
属性,每个属性记录的长度大小固定,默认41B,格式为 
Property: inUse+NextPropId+PrevPropId+DEFAULT_PAYLOAD_SIZE 
.inUse:表示属性是否可用,占1B。
. NextPropId:下一个属性的ID,占4B。
. PrevPropId:前一个属性的ID,占4B。
. DEFAULT_PAYLOAD_SIZE:属性块,存储了属性类型和属性值,占32B。
基于以上文件存储结构,可以快速地查找节点、关系及其属性。如果需要读取节点,只
要根据节点的ID号(整数值)乘以节点大小(9B)就可以方便地计算出节点在存储文件中的
位置。如果需要读取属性,只需要从节点的第一个属性的指针开始,遍历属性列表就可以获
得;如果要查找节点的关系,只需要根据节点的第一个关系,遍历整个双向链表就可以找到
关系。

1 17 
图5-10给出了一个图存储结构实例,该图包含5个节点和6个关系,其中5个节点的
存储记录如下所示。
图5-10 图存储结构实例
. Node[1,used=true,rel=1,prop=1] 
. Node[2,used=true,rel=2,prop=3] 
. Node[3,used=true,rel=1,prop=5] 
. Node[4,used=true,rel=3,prop=7] 
. Node[5,used=true,rel=6,prop=9] 
6个关系的存储记录如下所示。
. Relationship[1,used=true,source=1,target=3,type1,spre=-1,snext=2, 
tprev=-1,tNext=4,prop=-1] 
. Relationship[2,used=true,source=1,target=2,type2,spre=-1,snext=3, 
tprev=-1,tNext=5,prop=-1] 
. Relationship[3,used=true,source=1,target=4,type3,spre=-1,snext=-1, 
tprev=-1,tNext=6,prop=-1] 
. Relationship[4,used=true,source=3,target=4,type4,spre=1,snext=-1, 
tprev=3,tNext=6,prop=-1] 
. Relationship[5,used=true,source=2,target=4,type5,spre=2,snext=-1, 
tprev=4,tNext=6,prop=-1] 
. Relationship[6,used=true,source=4,target=5,type6,spre=5,snext=-1, 
tprev=-1,tNext=-1,prop=-1] 
5.4 Neo4j 查询语言
与关系数据库的标准查询语言SQL 类似,Neo4j图数据库拥有自己的查询语言
Cypher,也称为CQL(CypherQueryLanguage),该查询语言已经成为图数据库事实上的标
准语言。
Cypher也是一种声明式查询语言,允许用户不必编写图形结构的遍历代码,即可对图

1 18 
数据进行高效查询和更新。为了方便在上下文中引用查询结果,Cypher允许定义各类变
量,变量的定义需要遵循以下规则。
. 关键字不区分大小写,但是用户定义的各类对象(如属性值、标签、关系类型和变量
等)区分大小写。
. 变量名必须以字母开头,可以包含下画线、字母和数字。
. 变量命名规则也适用于属性的命名。
. 变量仅在一个查询块内可见,不能用于后续查询。
在本章中,关键字统一用大写表示,以区分用户自定义的各类对象。
例5-1 查询整个图数据库的所有节点和关系,其查询语句为 
MATCH (n) RETURN n 
上述语句是最简单的Cypher语句。MATCH 语句的功能是查询指定的模式,这里的
模式是一对小括号(),它表示节点模式。由于该节点模式中没有任何限定条件,因此所有节
点都与之相匹配。n 是自定义的节点变量,查询的所有节点全部赋值给该节点变量。
RETURN是返回语句,即将n所指代的全部节点及与该节点相关的关系全部返回。图5-11 
给出了登录Neo4j之后的图形化界面,上述命令写入顶部的输入框中。
图5-11 Neo4j图形化界面
一般地,Cypher语言的操作语句可以分为以下三类。
(1)写语句:这类语句的功能是实现对图数据库中各种对象的增加、删除和修改。
(2)读语句:这类语句的功能是实现对图数据库的查询和统计。
(3)通用语句:这类语句的功能是对图数据库操作施加某些限制条件。
除上述三类操作语句外,Cypher还提供了丰富的函数,可以被用户直接调用。
5.4.1 写语句
Cypher语言的写语句主要包括CREATE语句、MERGE语句、SET语句、DELETE语
句、REMOVE语句、FOREACH 语句、CREATEUNIQUE语句,用于管理节点、关系及它