Jean's Blog

一个专注软件测试开发技术的个人博客

0%

Neo4J图数据库

知识图谱介绍

知识图谱(Knowledge Graph),在图书情报界称为知识域可视化或知识领域映射地图,是显示知识发展进程与结构关系的一系列各种不同的图形,用 可视化技术描述知识资源及其载体,挖掘、分析、 构建、绘制和显示知识及它们之间的相互联系。 知识图谱是通过将应用数学、 图形学、信息可视化技术、 信息科学等学科的理论与方法与计量学引文分析、共现分析等方法结合,并利用可视化的图谱形象地展示学科的核心结构、发展历史、 前沿领域以及整体知识架构达到多学科融合目的的现代理论。它能为学科研究提供切实的、有价值的参考。

简单说来,知识图谱就是通过不同知识的关联性形成一个网状的知识结构,而这个知识结构,恰好就是人工智能AI的基石。当前AI领域热门的计算机图像、语音识别甚至是NLP,其实都是AI的感知能力,真正AI的认知能力,就要靠知识图谱。

知识图谱目前的应用主要在搜索、智能问答、推荐系统等方面。知识图谱的建设,一般包括数据获取、实体识别和关系抽取、数据存储、图谱应用都几个方面。

知识图谱由于其数据包含实体、属性、关系等,常见的关系型数据库诸如MySQL之类不能很好的体现数据的这些特点,因此知识图谱数据的存储一般是采用图数据库(Graph Databases)。而Neo4j是其中最为常见的图数据库。

Neo4J图数据库介绍

Neo4j是一个开源的NoSQL图形数据库,2003 年开始开发,使用 scala和java 语言,2007年开始发布。

  • 是世界上最先进的图数据库之一,提供原生的图数据存储,检索和处理;
  • 采用属性图模型(Property graph model),极大的完善和丰富图数据模型;
  • 专属查询语言 Cypher,直观,高效;

官方文档:https://neo4j.com

Neo4j 是一个原生图形数据库,这意味着它一直到存储级别都实现了真正的图形模型。数据以白板形式存储,而不是作为另一种技术之上的“图形抽象”。除了核心图之外,Neo4j 还提供:ACID 事务、集群支持和运行时故障转移。

Neo4j 通过AuraDB作为托管云服务提供。但您也可以使用社区版或企业版自行运行 Neo4j。企业版包括社区版的所有功能,以及额外的企业需求,例如备份、集群和故障转移功能。Neo4j 用 Java 和 Scala 编写,源代码可在GitHub上获取。

是什么让 Neo4j 成为最容易使用的图形?

  • Cypher,一种类似于 SQL 的声明式查询语言,但针对图形进行了优化。现在通过openCypher 项目被 SAP HANA Graph 和 Redis graph 等其他数据库使用。

  • 由于节点和关系的有效表示,大图中深度和广度的恒定时间遍历。可以在中等硬件上扩展到数十亿个节点。

  • 灵活的属性图模式可以随着时间的推移进行调整,从而可以在以后具体化和添加新的关系,以便在业务需求发生变化时快捷并加速域数据。

  • 流行编程语言的驱动程序,包括 Java、JavaScript、.NET、Python 等。

Neo4j 使用属性图数据库模型。图数据结构由可以通过关系连接的节点(离散对象)组成。下面是具有三个节点(圆圈)和三个关系(箭头)的图的图像。

img

Neo4j 属性图数据库模型包括:

  • 节点描述域的实体(离散对象)。
  • 节点可以有零个或多个标签来定义(分类)它们是什么类型的节点。
  • 关系描述源节点和目标节点之间的连接。
  • 关系总是有一个方向(一个方向)。
  • 关系必须有一种类型(一种类型)来定义(分类)它们是什么类型的关系。
  • 节点和关系可以具有属性(键值对),属性进一步描述它们。

在数学中,图论是对图的研究,在图论中:

  • 节点也称为顶点或点。
  • 关系也称为边、链接或线。

属性图模型

在 Neo4j 中,信息被组织为节点、关系和属性。

img

节点是图中的实体。

  • 节点可以用labels来标记,代表它们在域中的不同角色(例如Person)。

  • 节点可以保存任意数量的键值对或属性(例如,name)。

  • 节点标签还可以将元数据(例如索引或约束信息)附加到某些节点。

关系提供两个节点实体之间的定向命名连接(例如, Person LOVES Person)。

  • 关系总是有方向、类型、起始节点和结束节点,并且它们可以有属性,就像节点一样。

  • 节点可以具有任意数量或类型的关系,而不会牺牲性能。

  • 尽管关系总是有方向的,但它们可以在任何方向上有效地导航。

示例介绍

下面的示例图介绍了属性图的基本概念:

img

要创建示例图,请使用 Cypher 子句 CREATE

1
CREATE (:Person:Actor {name: 'Tom Hanks', born: 1956})-[:ACTED_IN {roles: ['Forrest']}]->(:Movie {title: 'Forrest Gump', released: 1994})<-[:DIRECTED]-(:Person {name: 'Robert Zemeckis', born: 1951})

节点

节点用于表示域的实体(离散对象)。

最简单的可能的图是没有关系的单个节点。考虑下图,它由单个节点组成。

img

节点标签:

  • Person
  • Actor

属性是:

  • name:Tome Hanks
  • born:1956

可以使用 Cypher 使用以下查询创建节点:

1
CREATE (:Person:Actor {name: 'Tom Hanks', born: 1956})

节点标签

标签通过将节点分组(分类)到集合中来塑造域,其中具有特定标签的所有节点都属于同一集合

例如,代表用户的所有节点都可以用标签进行标记User。完成此操作后,您可以要求 Neo4j 仅在您的用户节点上执行操作,例如查找具有给定名称的所有用户。

由于标签可以在运行时添加和删除,因此它们也可以用于标记节点的临时状态。标签Suspended可用于表示已暂停的银行账户,标签Seasonal可表示当前应季的蔬菜。

一个节点可以有零到多个标签。

在示例图中,节点标签 、Person和Actor,Movie用于描述(分类)节点。可以添加更多标签来表达数据的不同维度。

下图显示了多个标签的使用。

img

关系

关系描述源节点和目标节点之间的连接如何相关。节点可能与其自身有关系。

关系:

  • 连接源节点和目标节点。
  • 有一个方向(一个方向)。
  • 必须有一个类型(一种类型)来定义(分类)它是什么类型的关系。
  • 可以有属性(键值对),进一步描述关系。

关系将节点组织成结构,允许图形类似于列表、树、地图或复合实体——其中任何一个都可以组合成更复杂、更丰富的互连结构。

img

关系类型:ACTED_IN

属性是:

  • roles: [‘Forrest’]

  • performance: 5

该属性有一个数组值,其中roles包含单个项目Forrest

可以使用 Cypher 使用以下查询创建关系:

1
CREATE ()-[:ACTED_IN {roles: ['Forrest'], performance: 5}]->()

注意:必须创建或引用节点和目标节点才能创建关系

关系总是有方向的。然而,如果方向没有用处,则可以忽略它。这意味着除非需要正确描述数据模型,否则不需要在相反方向添加重复关系。

节点可以与其自身有关系。如果要表达Tom Hanks KNOWS自己的话,可以这样表达:

img

关系类型:关系必须只有一种关系类型

下面是一个ACTED_IN关系,该Tom Hanks节点作为源节点,Forrest Gump作为目标节点。

img

观察该Tom Hanks节点具有外出关系,而该Forrest Gump节点具有传入关系。

特性

属性是用于存储节点和关系上的数据的键值对。

财产的价值部分:

  • 可以保存不同的数据类型,例如number、string、 或boolean。

  • 可以保存包含字符串、数字或布尔值等的同类列表(数组)。

示例一:数字

1
CREATE (:Example {a: 1, b: 3.14})
  • 该属性a的类型integer值为1。
  • 该属性b的类型float值为3.14。

示例二:字符串和布尔值

1
CREATE (:Example {c: 'This is an example string', d: true, e: false})
  • 该属性c的类型string值为’This is an example string’。
  • 该属性d的类型boolean值为true。
  • 该属性e的类型boolean值为false。

示例三:列表

1
CREATE (:Example {f: [1, 2, 3], g: [2.71, 3.14], h: ['abc', 'example'], i: [true, true, false]})
  • 该属性f包含一个值为 的数组[1, 2, 3]。
  • 该属性g包含一个值为 的数组[2.71, 3.14]。
  • 该属性h包含一个值为 的数组[‘abc’, ‘example’]。
  • 该属性i包含一个值为 的数组[true, true, false]。

遍历和路径

遍历是查询图表以找到问题答案的方式,例如:“我的朋友喜欢哪些我还没有拥有的音乐”?或“如果电源出现故障,哪些Web服务会受到影响?”

遍历图是指按照一定的规则,通过关系来访问节点。在大多数情况下,仅访问图的子集。

路径匹配:为了根据微小的示例数据库找出汤姆·汉克斯出演了哪些电影,遍历将从节点开始Tom Hanks,遵循连接到该节点的任何关系,并以该节点作为结果ACTED_IN结束(参见黑线):

img

遍历结果可以作为长度为的路径返回 1:

img

最短可能路径的长度为零。它包含单个节点并且没有关系。

仅包含单个节点的路径的长度为0。

img

包含一个关系的路径的长度为1。

img

模式

Neo4j 中的模式指的是索引约束

Neo4j 通常被描述为模式可选,这意味着不需要创建索引和约束。您可以创建数据(节点、关系和属性),而无需预先定义架构。可以在需要时引入索引和约束,以获得性能或建模优势。

命名约定

节点标签、关系类型和属性(关键部分)区分大小写,例如,这意味着 propertyname与 property 不同Name。

建议采用以下命名约定:

图实体 推荐形式 例子
节点标签 驼峰式大小写,以大写字符开头 Person、VehicleOwner 反例:vehicle_owner
关系类型 大写,使用下划线分隔单词 OWNS_VEHICLE 反例:ownsVehicle
财产 小驼峰式,以小写字符开头 firstName而不是first_name

Neo4J安装

在Neo4J官网有介绍不同系统的安装方式,推荐使用Docker安装

1
docker pull neo4j

启动

1
docker run -d --name neo4j-neosemantics -p 7474:7474 -p 7687:7687 -v /home/jean/neo4j/data:/data -v /home/jean/neo4j/logs:/logs -v /home/jean/neo4j/conf:/conf -v /home/jean/neo4j/import:/var/lib/neo4j/import -v /home/jean/neo4j/plugins:/plugins --env NEO4J_AUTH=neo4j/12345678 neo4j
  • -d --name container_name //-d表示容器后台运行 —name指定容器名字
  • -p 7474:7474 // 将本地的7474端口映射到容器的7474端口(HTTP端口)
  • -p 7687:7687 // 将本地的7687端口映射到容器的7687端口(Bolt协议)
  • -v /home/jean/neo4j/data:/data //把容器内的数据目录挂载到宿主机的对应目录下
  • -v /home/jean/neo4j/logs:/logs //挂载日志目录
  • -v /home/jean/neo4j/conf:/conf //挂载配置目录
  • -v /home/jean/neo4j/import:/var/lib/neo4j/import //挂载数据导入目录
  • -v /home/jean/neo4j/plugins:/plugins //挂载使用插件
  • --env NEO4J_AUTH=neo4j/password //设定数据库的名字的访问密码(注意:密码设定必须是8个字符以上)
  • neo4j //指定使用的镜像

启动成功,访问地址:http://xxx.xxx.xxx:7474/browser/

打开页面后,会需要链接访问的数据库

image-20231215114747554

注意:没有设置用户名和密码,默认用户名密码是:neo4j/neo4j,首次登录后会强制进行用户名和密码修改

链接成功后,进入到neo4j主页

image-20231215114927812

Neo4j 的图形化界面主要包含了以下几个部分:

  • 导航面板:位于左侧,包含了数据库中的节点标签、关系类型等元数据信息,用于查看数据库的整体结构。
  • 查询编辑器:用户可以用来检索、修改或者删除数据库中的数据。提供语法高亮和自动完成功能。
  • 查询结果面板:位于底部,显示 Cypher 查询结果,结果以图形和表格的形式呈现,用户可在这里查看查询返回的节点、关系和属性信息,同时提供的还有图形查看器、帮助用户更好地理解查询结果。
  • 信息面板:用于显示有关节、关系和查询结果的详细信息。
  • 工具栏:包含常用的操作按钮,如运行查询、清空结果、切换图形视图和表格视图等。
  • 图形视图:查询结果为图形时,可直观地查看和导航图形数据库中的节点和关系。
  • 控制台:用于显示 Cypher 查询的执行结果和任何错误信息。

Neo4J初使用

下面我们通过提供的案例看下,初识neo4j如何使用

image-20231215115531563

image-20231215115634338

image-20231215115843960

Cypher语句

Cypher简介

Cypher 是 Neo4j 提出的图查询语言,是一种声明式的图数据库查询语言,它拥有精简的语法和强大的表现力,能够精准且高效地对图数据进行查询和更新。它是一种受 SQL 启发的语言,它允许声明想要从图数据库中选择、插入、更新或删除什么,而不需要精确地描述如何做到这一点。通过 Cypher,用户可以构建表达性强且高效的查询,处理所需的创建、读取、更新和删除功能。

Cypher组成结构

Cypher 的焦点在于从图中如何找回,而不是怎么去做,这个查询语言包含以下几个明显的部分:

  • START:在图中的开始点,通过元素的ID或所以查找获得。
  • MATCH:图形的匹配模式,束缚于开始点。
  • WHERE:过滤条件。
  • RETURN:返回所需要的。

Cypher基本命令

Cypher 基本命令总结如下表:

命令 用法
CREATE 创建节点、关系和属性
MATCH 检索有关节点、关系和属性
WHERE 提供条件过滤检索数据
DELETE 删除节点和关系
REMOVE 删除节点和关系属性
SET 添加或更新标签

Cypher 更具体的用法,下文会进行具体介绍,也可以参考:https://neo4j.com/developer/cypher/

案例

下面我们通过案例熟悉Cypher语句,以下是我们的需求:

  • 登录功能
    • 用户名密码登录、手机验证码登录、扫描二维码登录
    • 登录成功跳转系统主页
    • 登录失败提留在当前登录页面

以上需求使用Cypher语句,生成知识图谱

创建节点

1
2
// 创建登录事件节点
CREATE (:LoginMethod{name: "Login"})
1
2
3
4
5
6
// 创建用户名密码登录节点
CREATE (:Login{name:"UserLogin"})
// 创建手机验证码登录节点
CREATE (:Login{name:"PhoneVerificationLogin"})
// 创建扫描二维码登录节点
CREATE (:Login{name:"QRCode"})

查询节点

1
MATCH (login:Login) RETURN login

image-20231219171922341

查询看到四个节点已经创建完成

查询整个图形数据库

1
MATCH (n) RETURN n

查询具有指定Lable的节点

1
MATCH (login:Login) RETURN login

查询具有指定属性的节点

1
MATCH (login:{name: "Login"}) RETURN login

关系运算符,例如:查询born属性小于1955的节点

1
MATCH (n) WHERE n.born<1955 RETURN n

逻辑运算符(not、and、or)

1
2
3
4
MATCH(n) WHERE n:标签1 or n:标签B  RETURN DISTINCT n
MATCH(n) WHERE not n:标签1 and not n:标签B RETURN DISTINCT n
MATCH (n) WHERE any(label in labels(n) WHERE label in ['标签1', '标签2']) RETURN n
MATCH (n) WHERE any(label in labels(n) WHERE label not in ['标签1', '标签2']) RETURN n

创建关系

1
2
3
MATCH (a:LoginMethod{name:"Login"}) MATCH (b:Login{name:"UserLogin"}) CREATE (a) -[:ChooseLoginMethod]->(b);
MATCH (a:LoginMethod{name:"Login"}) MATCH (c:Login{name:"PhoneVerificationLogin"}) CREATE (a) -[:ChooseLoginMethod]->(c);
MATCH (a:LoginMethod{name:"Login"}) MATCH (d:Login{name:"QRCode"}) CREATE (a) -[:ChooseLoginMethod]->(d);

注意:以上语句要一句一句的执行

执行查询,我们看到节点关系已经创建完成

1
MATCH (login:Login) RETURN login
1
MATCH (n) WHERE n:LoginMethod OR n:Login RETURN n

image-20231219172758761

接下来,我们再次创建登录操作的节点,及关系建立

1
2
3
4
5
6
7
8
// 创建登录成功的节点
CREATE (:Operate{name: "LoginSuccess"})
// 创建登录失败的的节点
CREATE (:Operate{name:"LoginFail"})
// 创建跳转系统主页的节点
CREATE (:Page{name:"MainPage"})
// 创建跳转登录页面的节点
CREATE (:Page{name:"LoginPage"})

建立关系

1
2
3
4
5
6
7
8
MATCH (a:Login{name:"UserLogin"}) MATCH (b:Operate{name:"LoginSuccess"}) CREATE (a) -[:LoginOperate]->(b);
MATCH (a:Login{name:"PhoneVerificationLogin"}) MATCH (b:Operate{name:"LoginSuccess"}) CREATE (a) -[:LoginOperate]->(b);
MATCH (a:Login{name:"QRCode"}) MATCH (b:Operate{name:"LoginSuccess"}) CREATE (a) -[:LoginOperate]->(b);
MATCH (a:Operate{name:"LoginSuccess"}) MATCH (b:Page{name:"MainPage"}) CREATE (a) -[:Jump]->(b);
MATCH (a:Login{name:"UserLogin"}) MATCH (b:Operate{name:"LoginFail"}) CREATE (a) -[:LoginOperate]->(b);
MATCH (a:Login{name:"PhoneVerificationLogin"}) MATCH (b:Operate{name:"LoginFail"}) CREATE (a) -[:LoginOperate]->(b);
MATCH (a:Login{name:"QRCode"}) MATCH (b:Operate{name:"LoginFail"}) CREATE (a) -[:LoginOperate]->(b);
MATCH (a:Operate{name:"LoginFail"}) MATCH (b:Page{name:"LoginPage"}) CREATE (a) -[:Stay]->(b);

查询,根据需求,已经完成一个登录功能的知识图谱

1
MATCH (n) WHERE n:LoginMethod OR n:Login OR n:Operate OR n:Page RETURN n

image-20231219180043384

删除节点

通过 name 属性 删除这一个节点

1
2
MATCH (n:TEST1{name:'temp'})
delete n

通过 id 属性 删除这一个节点

1
2
3
MATCH (r)
WHERE id(r) = 492
DELETE r

删除一个节点及其所有的关系

1
2
3
MATCH (r)
WHERE id(r) = 615
DETACH DELETE r

删除所有节点和所有的关系

1
2
MATCH (r)
DETACH DELETE r

删除一个标签中所有的节点

1
2
MATCH (r:Loc)
DETACH DELETE r

删除所有的节点和关系

1
2
3
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
DELETE n,r