Neo4j概述

2018/07/01 Neo4j

Neo4j概述

Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。

什么是Neo4j

什么是Neo4j呢?Neo4j是一个NoSQL的图数据库管理系统。这里所说的图是指图论中的图这种数据结构,图是一个比线性表和树更高级的数据结构。在Neo4j中,图表示为一些节点和连接这些节点的关系的集合,其中,节点表示实体,关系表示实体之间的连接方式。

在Neo4j中存储的关联数据表现为树状或网络状的形形色色的图,它更加形象和直观地表现了现实世界中的应用场景。Neo4j不但能给人一种耳目一新的感觉,更重要的是它能始终保持高效的查询性能,不会因为数据的增长而降低了查询的反应能力。 Neo4j是一个NoSQL数据库,像其他NoSQL数据库一样具有高效的查询性能。同时,Neo4j还具有完全事务管理特性,完全支持ACID(Atomicity,Consistency,Isolation,Durability)事务管理。 实践证明,图数据库具有很强的表现力。像 Facebook中巨大的社交数据,Google搜索引擎的海量网页,或者现实世界中繁杂的交通网络,大至宏观世界的天文数据,小至微观世界的量子模型等,现实世界中不同领域的数据都可以使用图数据库来存储和访问。 Neo4j自2010年2月发布1.0.0版本,经过几年时间一些大中型企业的使用实践,可以充分证明Neo4j是一个成熟的数据库,同时也是一个安全可靠的数据库管理系统。

Neo4j数据的特点

在Neo4j数据库中存储的图数据,相比于大家比较熟悉的关系型数据库来说,它没有模式结构(如表或视图等逻辑结构的定义),而是用节点和关系的属性来表现实体的内容。使用属性,可以让Neo4j的图数据具有更加出色的表现能力,使其像关系型数据库那样包含非常丰富的内容。

Neo4j的图数据结构具有如下基本特征:

  • 节点、关系和属性是构成图数据的三个基本要素。
  • 节点和关系的属性是一个Key-Value的数据集合。
  • 每个关系都有一个开始节点和一个结束节点相互连接。
  • 大多数情况下关系可以不需要属性。 从以上特征中可以看出,Neo4j存储的数据是一个属性图。其中,节点表示一个实体,实体可以是人、事物或者任何一种定义,节点的属性就是实体的内容。而实体之间的关联表现为节点的关系,比如朋友关系、从属关系等。

从总体来看,Neo4j就是由无数相互联系的节点所组成的图形,它能很好并且形象地表现出现实世界中相互联系的事物。从这一方面来说,Neo4j存储的数据更能体现事物之间相互联系的本质,这种关联数据表现出了现实场景中事物本来的样子。

Neo4j数据的表现形式

由于Neo4j并不需要模式结构定义,因而非常适合用来存储非结构化或半结构化的数据,所以在数据表现形式上,与RDBMS或其他NoSQL数据库相比,都具有绝对的优势。

例如,在使用RDBMS设计数据库时,一般遵循这样一条规则:首先要做一些数据模型的分析,然后再进行实体-关系模型的设计,接下来才开始定义一些表结构。在这个过程中,必不可少地需要考虑一些范式规范,以便让存储的数据可以避免过多的冗余。最后可能为了一些性能要求,还会反过来使用一些反范式设计,再增加一点冗余字段。经过所有这些工作之后,才能确定数据结构的定义。而当数据结构确定之后,就不能再有大的变更了,否则整个系统结构都要跟着更改。 纵观使用RDBMS的整个设计和开发过程,有时你会觉得,在这种情况下的程序开发者似乎显得太蹩脚了。虽然明知这些工作很烦琐,但还是要求你必须得这样做。 使用Neo4j来设计数据库,就不需要有这么多繁琐的过程,我们只需借助于在做业务需求时画出的一些简单框图,就可以用来作为数据模型,很容易地将其转化为图数据结构。

[部门] 《=属于  [用户]

例如,如上图所示的简单框图,它可以表示有用户和部门两个实体,并且它们之间存在一种隶属关系。至于在框图中是使用方框还是圆框则完全根据个人喜好,并没有什么区别。在使用Neo4j来进行数据库设计时,使用这个简单的框图就足够了。要用Neo4j来表现这一数据,将会存储部门和用户这两个节点,以及一个连接这两个节点的隶属关系。

综合表现

Neo4j查询的高性能表现、易于使用的特性及其设计的灵活性和开发的敏捷性,以及坚如磐石般的事务管理特性,都充分说明了使用Neo4j是一个不错的选择。有关它的所有优点,总结起来,主要表现在以下几个方面。

  • 闪电般的读/写速度,无与伦比的高性能表现。
  • 非结构化数据存储方式,在数据库设计上具有很大的灵活性。
  • 能很好地适应需求变化,并适合使用敏捷开发方法。
  • 很容易使用,可以用嵌入式、服务器模式、分布式模式等方式来使用数据库。
  • 使用简单框图就可以设计数据模型,方便建模。
  • 图数据的结构特点可以提供更多更优秀的算法设计。
  • 完全支持ACID完整的事务管理特性。
  • 提供分布式高可用模式,可以支持大规模的数据增长。
  • 数据库安全可靠,可以实时备份数据,很方便恢复数据。
  • 图的数据结构直观而形象地表现了现实世界的应用场景。

Neo4j的核心概念

  • Nodes(结点,类似地铁图里的一个地铁站):图形的基本单位主要是结点和关系,都可以包含属性,一个结点就是一行数据,一个关系也是一行数据,里面的属性就是数据库的行(Row)的字段。除了属性之外,关系和结点还可以有零到多个标签,标签可以认为是一个特殊分组方式。
  • Relationships(关系,类似两个相邻地铁站之间的路线):关系的功能是组织和连接结点,一个关系连接两个结点(一个开始结点和一个结束结点)。所有的点被连接起来就形成了一张图,通过关系可以组织结点形成任意的结构,如 list、tree、map、tuple,或者更复杂的结构。关系有方向(进和出),代表一种指向。
  • Properties(属性,类似地铁站的名字、位置、大小、进出口数量等):属性非常类似数据库里面的字段,只有结点和关系可以有0到多个属性。属性的类型基本和Java的数据类型一致,分为数值、字符串、布尔及其他一些类型。字段名必须是字符串。
  • Labels(标签,类似地铁站的属于哪个区):标签形容一种角色或者给结点加上一种类型,一个结点可以有多种类型,通过类型区分一类结点,在查询时更加方便和高效;标签在给属性建立索引或者约束时也会用到。标签名称必须是非空的 unicode 字符串,另外标签最大标记容量是int的最大值。
  • Traversal(遍历,类似看地图找路径):查询时通常是遍历图谱以找到路径,在遍历时通常会有一个开始结点,然后根据系统提供的查询语句,遍历相关路径上的结点和关系,得到最终的结果。
  • Paths(路径,类似从一个地铁站到另一个地铁站的所有的到达路径):路径是一个或多个结点通过关系连接起来的列表,例如得到图谱查询或者遍历的结果。
  • Schema(模式,类似存储数据的结构):Neo4j是一个无模式或者less模式的图形数据库。使用时它不需要定义任何模式(Schema)。
  • Indexes(索引):遍历图需要大量的随机读/写,如果没有索引,则可能意味着每次索引都是全图扫描。若在字段属性上构建索引,则任何查询操作都会使用索引,这样能大幅度提升查询性能。构建索引是一个异步请求,在后台创建直至成功后,才能最终生效。如果创建失败,可以重建索引,要先删除索引,然后从日志里面找出创建失败的原因,最后再创建。
  • Constraints(约束):约束定义在某个字段上,限制字段值为唯一值,创建约束会自动创建索引。

Neo4j 的物理存储文件

Neo4j 作为图形数据库,数据主要分为结点、关系、结点或关系上的属性3类,这些数据也可以通过检索工具库如Lucene进行存储检索。在Neo4j中,结点和关系的属性是用一个键值的双向列表来保存的;结点的关系是用一个双向列表来保存的。通过关系找到其前导和后继结点。结点保存第1个属性和第1个关系ID。

图形的存储结构包括如下5类文件。

(1)存储结点的文件:存储结点数据及其序列 ID 包括存储结点数组、数组的下标(即该结点的 ID)、最大的 ID 及已经释放的 ID;存储结点标签及其序列 ID包括存储结点标签数组数据、数组的下标(即该结点标签的ID)。

(2)存储关系的文件:存储关系数据及其序列ID包括存储关系记录数组数据和ID;存储关系组数据及其序列ID包括存储关系组数组数据和ID;存储关系类型及其序列ID包括存储关系类型数组数据和ID;存储关系类型的名称及其序列ID包括存储关系类型 token 数组数据和ID。

(3)存储标签的文件:存储标签标记数据及其序列ID包括标签标记数组数据和ID、标签标记名字数据及其序列ID、标签标记的名字数据和ID。

(4)存储属性的文件:存储属性数据及其序列ID包括存储属性数据和ID;存储属性数据中的数组类型数据及其序列ID包括存储属性(键值结构)的值是数组的数据和ID; 属性数据为长字符串类型的存储文件及其序列 ID 包括存储属性(键值结构)的值是字符串的数据和ID;属性数据的索引数据文件及其序列ID包括存储属性(键值结构)的键的索引数据和ID;属性数据的键值数据存储文件及其序列ID包括存储属性(键值结构)的键的字符串值和ID。

(5)其他文件:存储版本信息、存储模式数据、活动的逻辑日志、记录当前活动的日志文件名称等。

Neo4j的存储结构

Neo4j 主要有4类结点、属性、关系等文件,以数组作为核心存储结构;同时对结点、属性、关系等类型的每个数据项都会分配一个唯一的ID,在存储时以该ID 为数组的下标。在访问时ID作为下标,在图遍历等操作时,可以不用索引就快速定位。

  • 结点(指向联系和属性的单向链表)的存储方式 第一个字节表示是否使用的标志位;接着的4个字节代表关联到这个结点的第一个关系的ID;接着的4个字节代表第一个属性ID;接着的5个字节是代表当前结点的标签,指向该结点的标签存储;最后一个字节作为保留位。一个结点共占9个字节,格式为
    in_use(byte)+next_rel_ID(int)+next_prop_ID(int)
    

    表达式的含义:结点是否可用(1)+最近一个关系的ID(4)+最近一个属性的ID(4)。 通过每个结点 ID 号,很容易通过计算偏移量获取这个结点的相关数据。结点数据包含最后一个关系ID,可以通过关系ID快速获取结点所有关系。

  • 关系(双向链表)的存储方式 第一个字节表示是否使用的标志位;接着的4个字节代表起始结点的ID;接着的4个字节代表结束结点的ID;然后是关系类型,占用5个字节,依次是起始结点的上下联系和结束结点的上下结点,以及一个指示当前记录是否位于联系链的最前面。一个关系占33个字节,格式为
    in_use(byte)+first_node(int)+second_node(int)+rel_type(int)+first_prev_rel_ID( int)+first_next_rel_ID(int)+second_prev_rel_ID(int)+second_next_rel_ID(int)+next_p rop_ID(int)
    

    各个部分的含义:是否可用(1)+关系的头结点(4)+关系的尾结点(4)+关系类型(4)+头结点的前一个关系ID(4)+头结点的后一个关系ID(4)+尾结点的前一个关系ID(4)+尾结点的后一个关系ID(4)+关系的最近属性ID(4)。 我们通过使用结点的前后关系所形成的双向链表,可以快速搜索到结点所有相关的边。在添加关系过程中,对第一个关系来说,情况是第一个关系结点没有尾关系ID(-1表示),最后一个关系结点则没有前一个关系ID(-1表示),中间添加的关系都应该有前一个和后一个关系ID,最终通过这些关系ID形成结点的关系列表。

  • 属性存储的存储方式 属性是固定大小,每个属性记录包括4个属性(一个属性记录最多容纳4个属性)和指向属性链中下一个属性的 ID。属性记录包括属性类型和指向属性索引文件的指针,同时属性记录中可以内联和动态存储,在属性值存储占用小时,会直接存储在属性记录中,对大属性值,可以分别存储在动态字符存储和动态数组存储中。由于动态记录同样由记录大小固定的记录链表组成,因此大字符串和大数组会占据多个动态记录。一个属性默认占41个字节,格式为
    next and prev high bits(1)+next(4)+prev(4)+DEFAULT_PAYLOAD_SIZE(property blocks 32);
    

    其含义:是否可用(1)+前一个属性ID(4)+后一个属性ID(4)+属性块(32)。 属性记录形成一个双向链表,每一个持有一个或多个属性块的实际的属性键值对。因为属性块长度是可变的,一个完整的属性记录可以只是一个属性块。属性块格式为“属性类型(8B)+属性值(非基础类型占8B)”,属性键与属性值分别存储在不同的文件中。

哪些领域更适合使用Neo4j

Neo4j从推出至今,已经经历了几年时间的考验和锤炼,原则上可以应用于任何领域。从大量的应用实践中可以看出,Neo4j在处理关联数据时更能体现出它的绝对优势。例如,社区网络、推荐引擎、地理(网络)数据、主数据存储、访问控制、欺诈检测、物流管理等,都在实际应用中表现出无与伦比的优势。

社区网络

在一个社区中,人与人之间具有亲属、同事、朋友等各种关系,而每个人又有不同的兴趣、爱好,并且从事各种不同的活动。如果社区庞大,各种关系又纷纭复杂,那么使用一般的关系型数据库或其他 NoSQL数据库来管理,是很难厘清这些数据及其关系的。如果我们把这之中的人和各种事物及其关系使用节点和关系的形式存储在Neo4j的图数据库中并用它来进行数据管理,这不仅是一件极其容易的事情,并且对其中的各种关系也能做到脉络清楚、有条不紊。而且在Neo4j中通过关联数据管理,还可以很容易地发现或发掘这些数据中各种各样的价值。例如,在一个社区网络中,通过每个人的爱好这一关系,人们可以认识更多的朋友,还可以由此组织一些让人更加感兴趣的活动等。

推荐引擎

由社区网络的数据累积和沉淀就可以引申出一个推荐引擎。比如在一个电影社区中,哪些观众在哪里看了哪些电影,并对哪些电影做了哪些评价。有了这些数据之后,我们就能做一个电影社区推荐引擎,让这些数据产生不可估量的商业价值。例如,当前有哪几部电影是被观众所追捧的,而这些电影还有哪些观众没有看过,在这些观众之中,哪些是比较活跃的,哪些是具有朋友关系的,这样就可以将这几部电影对各个群体进行有目的的推荐。这种推荐就是最有效的,对于电影院来说,这无疑是一种商业价值。

交通运输

庞大的交通系统,如航运、海运、铁路运输、公路运输等,任何一种运输系统都将连接世界各地,大到全球、全国,小到地区、城市运输,这里面的运输工具、线路、站点以及班次、调度等各种数据,庞大而又繁杂交错,这些数据使用Neo4j来存储和管理会显得脉络清楚、井然有序,因为图的数据结构正好体现了这种数据的特性。使用图的遍历算法能够很快地计算出从一个站点到另一个站点的最短路径。

物流管理

物流管理是交通网络的一个具体应用。对于一个大型的物流系统来说,几秒钟就有可能增加几百个甚至几千个包裹。如果是在一个城市中,那么这一个个包裹将分布于不同区域和街道之中,而要使包裹能够尽快地送达用户手中,在包裹分拣中心要找出每一个包裹配送的最短路径,再将它分配到不同的配送点,这时,Neo4j就能发挥它的特长了。

主数据管理

对于一些结构化数据,例如客户资料、组织数据、产品数据等,使用Neo4j来存储和管理,可以很好地避免数据僵化,让数据具有实时价值,充满活力。不管是自上而下的查询,还是使用遍历,都能保持高效的查询性能。使用Neo4j灵活的属性管理还能让数据适应组织及产品结构的变迁和演化。

访问控制

如果有一个大型平台,它有成千上万的用户,并且有成倍的资源,那么对于这些资源的访问,必须要有一个有效的控制系统,以控制哪些用户能够访问哪些特定的资源,或者哪些用户不能访问哪些资源等。使用Neo4j来处理这些关联数据及实现访问控制正是它的特长。

欺诈检测

涉及银行卡、信用卡的欺诈交易,或者电信诈骗事项,使用关联数据可以厘清一个账号或一个电话号码的关系和行为,很容易在这些关系和行为之中找出某些异常的举动,从而能很快地检测出欺诈或诈骗行为。所以使用Neo4j来建立欺诈检测系统,或者使用关联数据来进行预测、推荐建议等做法都是不错的选择。

其他应用领域,如金融、教育、零售、科学、新闻调查、卫生保健等,Neo4j都能发挥它的长处。总之,使用Neo4j不但可以很好地管理繁杂的关联数据,也能适应大规模的数据增长,并且能连接不同领域的数据,提供最全面和最快的实时反应速度。

哪些领域不适合使用Neo4j

从上面的介绍中可以看出,Neo4j的应用领域涵盖了很广的范围,几乎所有领域都可以使用。但是,世界上没有万能的东西,下面一些领域就不推荐使用Neo4j。

  • 记录大量基于事件的数据。
  • 需要对大规模分布式数据进行处理(以PB级别计算的数据)。
  • 二进制数据存储。
  • 适合保存在关系型数据库中的结构化数据。 注意,Neo4j企业版是要收费的,而只有企业版才能使用分布式安装,并且可以提供负载均衡和高可用配置等功能。社区版只能单机使用,最多可以使用数十亿个节点、关系和属性。

Neo4j的安装

Neo4j有两个版本,分别是社区版(Community Edition)和企业版(Enterprise Edition)。社区版是免费并且开源的,但只适用于单实例部署,即只能用于单机安装和使用。不过,社区版已经具备了Neo4j的全部功能,包括可编程的API调用、Cypher查询语言使用和ACID事务管理等。社区版非常适合用来构建一个小型项目,或者用于项目的前期开发和调试。

Docker安装Neo4j

  • 从镜像源中找合适的镜像:docker search neo4j,或者到dockerhub上查找:https://hub.docker.com/_/neo4j/tags
  • 拉取镜像源docker pull neo4j:4.4.17-community ,也可以加上版本号
  • 查看本地镜像,检查是否拉取成功,docker images
  • 构建neo4j容器
    docker run -d --name neo4j \
      -p 7474:7474 -p 7687:7687 \
      -v /home/neo4j/data:/data \
      -v /home/neo4j/logs:/logs \
      -v /home/neo4j/conf:/var/lib/neo4j/conf \
      -v /home/neo4j/import:/var/lib/neo4j/import \
      --env NEO4J_AUTH=neo4j/root neo4j:4.4.17-community
    
  • data——数据存放的文件夹 logs——运行的日志文件夹 conf——数据库配置文件夹(在配置文件neo4j.conf中配置包括开放远程连接、设置默认激活的数据库) import——为了大批量导入csv来构建数据库,需要导入的节点文件nodes.csv和关系文件rel.csv需要放到这个文件夹下) 其中container_name可以自己指定。另外NEO4J_AUTH也是你自己来进行设置。 简化命令
    docker run -d --name neo4j -p 7474:7474 -p 7687:7687 -v /home/neo4j/data:/data -v /home/neo4j/logs:/logs -v /home/neo4j/conf:/var/lib/neo4j/conf -v /home/neo4j/import:/var/lib/neo4j/import --env NEO4J_AUTH=neo4j/root neo4j:4.4.17-community
    

    然后在浏览器中输入:http://localhost:7474/,ip为启动服务的主机地址。 输入构建容器时配置的用户名和密码即可。 需要说明的是:

  • 社区版本不支持命令create database xxx,只有企业版可以!
  • 社区版本只允许同时打开一个数据库

图形数据的表示和操作

从某种意义上讲,图形就是二元关系,它利用一系列由线(边)或箭头(边)连接的点(结点)提供了强大的视觉效果。图有多种形式:有向图/无向图,标号图/无标号图。图形可以解决距离的计算、关系中环的查找,以及连通性的确定等问题。

图形数据库源起欧拉和图理论,称为面向/基于图形的数据库,对应的英文是 Graph 数据库。有向图的结构,各结点是用圆圈表示的,结点的名称就在圆圈中央。通常用从0开始的整数为结点命名,或者使用等效的枚举。结点集合N ={0,1,2,3,4}, A 中的边(u ,v )都是由从 u 到 v 的箭头表示的,边的集合是 A ={(0,0),(0,1), (0,2),(1,3),(2,0), (2,1),(2,4),(3,2),(3,4),(4,1)}。边(u ,v )表示为u →v ,v 被称为边的头部,u 被称为边的尾部,例如,0→1就是图中的一条边,它的头部是结点1,尾部是结点0。另一条边是0→0,这样一条从某结点通向其自身的边就叫作自环(Loop)。对该边而言,头部和尾部都是结点0。当u →v 是边时,还可以说u 是v 的前导(Predecessor),v 是u 的后继(Successor)。边0→1就表示0是1的前导而1是0的后继,而边0→0则表示0同时是其本身的前导和后继。

为图的各结点附加标号(Label),标号是绘制在所对应的结点附近的,在靠近边中点的位置为边放置标号。结点的标号或边的标号可以是任意类型的。同一幅图中各结点的名称必须是唯一的,但可能有不止一个结点的标号相同。

有向图中的路径是一列结点(v 1 ,v 2 ,…,v k ),其中每个结点都有到下一个结点的边,也就是v i →v i +1,i =1,2,…,k -1。该路径的长度是k -1,也就是这条路径上边的数量。例如,图中的(0,1,3)就是一条长度为2的路径。k =1的情况也是可以存在的。也就是说,任何结点v 本身都是一条从v 到v 的长度为0的路径。

有向图中的环路(Cycle)是指起点和终点为同一结点的长度不为0的路径。环路的长度就是这条路径的长度。环路的起点和终点可以是其中的任一结点。环路(v 1 ,v 2 ,…,v k ,v 1 )也可以写为(v 2 ,…,v k ,v 1 ,v 2 ),或者写为(v 3 ,…,v k ,v 1 ,v 2 ,v 3 )等。例如,环路(1,3,2,4,1)也可以写为(2,4,1,3,2)。

在每条环路中,第一个结点和最后一个结点都是相同的。如果环路(v 1 ,v 2 ,…,v k ,v 1 )的结点 v 1 ,v 2 ,…,v k 中没有一个出现一次以上,就说该环路是简单环路,简单环路的唯一重复出现在最终结点处。

图的实现:实现图的标准方式有两种。第一种叫作邻接表,大致上与二元关系的实现方法类似。设结点是由整数0,1,…,MAX-1或者等价的枚举类型命名的。使用NODE作为结点的类型,可以假设NODE跟int是一回事。 第二种叫作邻接矩阵。可以用代码“BOOLEAN arcs[MAX][MAX];”创建二维数组。其中如果存在边u →v ,则arcs[u ][v ]的值为TRUE,否则该值为FALSE。

参考资料

官网地址:https://neo4j.com

Search

    微信好友

    博士的沙漏

    Table of Contents