关于 NoSQL

Neo4J 属于 NoSQL 非关系型数据库的范畴。

基本概念理解

SQL 是结构化查询语言(Structured Query Language)的缩写,是一种编程语言,其应用场景一般是关系型数据库。而 NoSQL 是一种概念,全称为“Not Only SQL”,一般代表非关系型数据库,或称文档型数据库。

为什么要用 NoSQL?

在关系型数据库中,一般一张表可以代表实体或联系,数据和关系都存放在表中,在使用时需要预先定义好表的结构,即预定义的模式。而有时如果根据业务需要,我们需要对实体/关系的属性做调整时,这就必须涉及到对表结构的调整,且新增数据可能还涉及历史数据的补足,显得不够灵活。也就是说,我们的行动可能会被表结构所约束,如果在最初设计数据库时没有考虑完整实体的业务属性,可能会给之后的维护带来麻烦。

而以 Neo4J 为例的非关系型数据库,在字段约束上就显得没有那么严谨,在 Neo4J 数据库中仅有节点和关系两类需要我们考虑的实例,而对于节点和关系,我们可以为其自由增减属性,在部分应用场景中显得比较灵活。

举个例子,我们正在开发一个文献信息系统,使用关系型数据库做好了基本的数据库设计,包含了文献的基本信息,而甲方在验收时突然加需求说要在文献详情页展示文献的参考文献和引证文献、相关推荐文献,这可能就需要对数据库进行不小的调整,因为引入了两个一对多关系。(而且如果改进不当,有可能大幅增加数据库存储)

而如果我们使用的是 Neo4J 数据库,上述操作就很简单了,只需要建立两种关系(Relation)——引用关系和推荐关系即可,不需对节点本身做批量的修改。前台需要获取参考、引证、推荐时,只需查询这两种关系,并返回对应的节点即可

所以,我使用 NoSQL 的理由可能就归结于——灵活,不受限于预定义关系模式

安装使用 Neo4J

下载安装

前往 Neo4j Download Center - Neo4j Graph Database Platform 即可下载,选择社区版本(Community Server)即可。

以 Windows 为例,下载完成后会得到一个 zip 压缩包,将其全部内容解压到某个目录下即可。例如 C:\Program Files\neo4j

对于 Linux 系统,可以选择用 yum 方式下载 Neo4J RPM,可以参考 https://yum.neo4j.com/ 。使用这种方式安装系统会帮助检查环境和依赖,所以可以跳过下面的两节(2.2 & 2.3)。

基础环境检查:Java

Neo4J 是基于 Java 的图数据库,运行需要 Java 环境。可以在命令行中输入以下命令以检查是否有该环境:

1
java -version

image-20210902205954029

如果不存在,可以去 Java 官网 下载,如果使用 neo4j version 3 下载 JDK 8 版本即可;如果使用 neo4j version 4 建议下载 JDK 11

基础环境检查:环境变量

以 Windows 为例,右击此电脑-属性-高级系统设置- [高级] 选项卡-环境变量处可设置环境变量。

Java 环境变量

  • 查看系统变量里是否有名为 JAVA_HOME 的变量,如无则创建。地址为 Java 的安装目录(安装目录下的 /bin 文件夹有 java.exe)。
  • 在系统变量的 Path 变量中添加 %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

Neo4J 环境变量

  • 在系统中新建变量,变量名为 Neo4J ,变量值为 Neo4J 的安装目录。
  • 在系统变量的 Path 变量中添加 %NEO4J_HOME%\bin

命令安装启动

终端键入

1
neo4j install-service

即可完成安装。安装完成后,键入

1
neo4j start

即可启动 Neo4J 服务。在浏览器中输入终端提示的 url(默认为 http://localhost:7474)即可进入 Neo4J 的浏览器页面。

默认的账号密码配置为:

  • 账号:neo4j
  • 密码:neo4j

后续可根据页面提示,进入向导。

Neo4J 浏览器界面

键入命令

1
neo4j stop

可以停止服务。

数据备份与迁移

有时我们可能需要将数据库中的数据进行迁移,如将本地数据库中的数据部署到在线服务器上,就需要进行数据迁移。数据迁移涉及到数据安全等问题,需要使用 neo4j-admin 命令进行,可以在终端输入 neo4j-admin help 查看是否在安装时已配好环境变量,如果无有效响应,可以切换至 %NEO4J_HOME%\bin 下,启动 neo4j-admin

数据备份到文件

终端键入如下命令即可完成备份。

1
neo4j-admin dump --database=<database_name> --to=<file_directory>

其中 <database_name> 为 Neo4J 数据库名,<file_directory> 为保存的目标地址。

文件加载至数据库

终端键入如下命令即可将备份文件加载到数据库

1
neo4j-admin load --from=<file_directory> --database=<database_name> [--force]

参数含义同上。这里尾部添加 force 参数可以忽略上载时的错误,强制执行。

Cypher 语言

在 MySQL 中,我们会使用 SQL 语言对数据库进行操作;而在 Neo4J 中,操作数据库的主语言为 CQL (Cypher Query Language)Cypher 的语法提供了一种类 SQL 方式来匹配图中的节点和关系,即模式。如若具备 SQL 的基础,那么学习起 Cypher 就能变得更加容易。

操作目标

使用 Cypher 语言,我们可以操作节点关系模式三种对象,这三种对象具有不同的表示形式。

节点

在 Cypher 语言中,节点一般使用小括号表示:()

小括号中填写变量名,如(a),获取到 a 后可以对 a 进行后续操作。

我们也可以对节点补充更多细节,一般可以限定其类型和属性值。

  • 限定节点标签:使用冒号 : ,如 (a:Author)(a:Author:Person)
  • 限定节点属性:使用花括号 {} 补充键值对。如(a:Author {age:21,sex:'男'})

如果动作不关心节点是什么,括号内可留空,仅有括号,表示这是一个节点。

关系

在 Cypher 语言中,关系一般使用中括号表示:[]

关系的括号内如节点一样,可以添加变量名、类型、属性键值对。

已知,关系需要由两个节点组成(包括自环),用中括号连接两个节点表示关系。

  • 如果不需要强调关系的方向,节点与关系之间使用一根短横线连接:()-[rel:FRIENDS]-()
  • 如果需要强调关系的方向,则在终止节点前使用尖括号表示箭头:()-[relation:KNOWS]->()

关系括号内也可以留空。

模式

模式组成的基本要素就是节点和关系的表示方法。在模式中,可以添加逗号,函数等实现更复杂的查询。

如我们需要查询文献中的互引行为(由两组关系组成),可以使用逗号连接两组关系。(下面的示例用到了 MATCH RETURN 关键词,后面会介绍)

1
MATCH pattern=(a:Paper)-[:reference]->(b:Paper),(b:Paper)-[:reference]->(a:Paper) RETURN p

示例-互引查询

查找模式时,默认会返回模式中涉及的所有对象,在 Neo4J 数据库的浏览器页面查询模式,可以返回节点和关系,并用图的形式可视化。如执行

1
MATCH pattern=(a:Paper)-[r:reference]->(b) RETURN pattern

和执行

1
MATCH (a:Paper)-[r:reference]->(b) RETURN a,r,b

都可以触发 Neo4J 浏览器端的可视化。

模式可视化

操作命令

MATCH

MATCH 命令起匹配作用,后接节点、关系、模式等。MATCH 需要和其他命令一起使用。

RETURN

RETURN 命令一般和 MATCH 命令搭配使用,返回之前匹配的结果。

1
2
MATCH (node:Author) RETURN node //匹配节点
MATCH ()-[r:KNOWS]->() RETURN r //匹配关系

CREATE

CREATE 命令可用于创建节点和关系。

1
2
CREATE (node:Author {name:'John'}) //创建节点
CREATE (node:Author {name:'John'})-[r:KNOWS]->(node2:Author {name:'Lennon'}) //创建节点和关系

DELETE

DELETE 命令一般和 MATCH 命令搭配使用,当 MATCH 匹配到符合条件的节点/关系后,可以将其删除。

1
2
MATCH (node:Author) DELETE node //删除节点
MATCH (n) DELETE n //删除库中所有节点

WHERE

除了表示节点时,限定其标签和属性之外,使用 WHERE 可以以逻辑表达式的形式添加更多匹配条件来过滤结果。WHERE 放在 MATCH 之后,RETURN 之前。

支持如下比较运算符:

符号 含义
= 等于
<> 不等于
<;<= 小于;小于等于
>;>= 大于;大于等于

支持如下逻辑运算符:

符号 含义
AND
OR
NOT
XOR 异或

支持包含关系 IN,IS NULL 判断等。

举例应用:

  1. 用于获取节点时,过滤匹配条件

    1
    2
    MATCH a=(p:Paper)-[r:reference]->(q:Paper) WHERE p.year - q.year > 30 AND q.year IN [2000,2001,2002,2003] RETURN a 
    // 获取所有的引用年限差大于 30 年,且被引文献发表年份在2000-2003年的所有引用模式.
  2. 用于现有节点的关系建立

    1
    2
    3
    4
    MATCH (p:Paper),(q:Paper)
    WHERE p.id = '1001' AND q.id = '4001'
    CREATE (p)-[r:reference {value:10}]->(q)
    RETURN r// 建立id为1001,4001的节点之间的关系,并返回该关系

ORDER BY

ORDER BY 可使返回的记录按照指定的字段排序,可以是升序或降序(关键字 ASC/DESC)。

1
MATCH (node:Author) RETURN node ORDER BY node.year DESC

LIMIT & SKIP

LIMIT 可以限制结果返回的条数,SKIP 类似于 Hive SQL 中的 OFFSET,可以控制跳过多少条记录,二者可以组合使用。

1
MATCH (node:Author) RETURN node SKIP 10 LIMIT 10

SET

SET 可用于属性的增加/修改,匹配到符合条件的节点/关系后直接对相应属性更改即可。

1
MATCH (p:Paper) WHERE p.year < 2000 SET p.century = '20th'

REMOVE

REMOVE 可用于删除节点/关系的属性。

1
MATCH (p:Paper) WHERE p.year < 2000 REMOVE p.century

聚合函数

Cypher 支持如下聚合函数(含义与 SQL 几乎相同):

函数 含义
COUNT() 计数
MAX() 最大值
MIN() 最小值
SUM() 求和
AVG() 平均值

举例:计算符合条件的节点数量

1
MATCH (n:Author) WHERE n.sex='M' RETURN COUNT(n)

高级语言支持

Neo4J 是一个数据库,并不是一个可视化工具,虽然它内置的浏览器交互界面非常好用,但是不要低估了 Neo4J 广阔的应用场景。

PythonPy2Neo 包可以直接操纵 Neo4J 数据库。详细的使用,可以查看官方文档,Py2Neo Handbook,注意版本与本地对应。

Java Spring 框架 也对此有支持,可以查看 Spring Data Neo4j