前言

今天,我们一起来学习知识图谱中的Neo4J。首先,什么是知识图谱?先摘一段百度百科:


Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中——但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。

Neo4j因其嵌入式、高性能、轻量级等优势,越来越受到关注.


Neo是一个网络——面向网络的数据库——也就是说,它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络上而不是表中。网络(从数学角度叫做图)是一个灵活的数据结构,可以应用更加敏捷和快速的开发模式。


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


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


本文,从Neo4j的数据存储来学习如何使用

一、Neo4J简介

官网: https://neo4j.com/

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

对比关系型数据库:

关系型数据库(RDBMS) 图数据库
节点
列和数据 属性和数据
约束 关系

对比其他NoSQL数据库

NoSQL数据库大致可以分为四类:

  • 键值(key/value)数据库
  • 列存储数据库
  • 文档型数据库
  • 图数据库

image.png

二、Neo4J下载安装

方法1:安装Neo4j Community Server

Neo4j和MySQL类似,我们也需要安装一个服务端程序,再安装一个客户端程序,客户端程序不安装直接使用命令行操作也可以。接下来先安装服务端程序。

首先在 https://neo4j.com/download-center// 下载Neo4J。Neo4J分为社区版和企业版,企业版在横向扩展、权限控制、运行性能、HA等方面都比社区版好,适合正式的生产环境,普通的学习和开发采用免费社区版就好。

注意: neo4j最新版对应的java版本是jdk11 image

jdk8可以下载 Neo4j Community Edition 3.5.28

官方文档: https://neo4j.com/docs/operations-manual/3.5/

解压到新目录(注意:目录名称不要有中文),比如: D:\neo4j\

# 将Neo4j作为控制台应用程序运行
<NEO4J_HOME>\bin\neo4j console
# 将Neo4j作为服务使用进行安装
<NEO4J_HOME>\bin\neo4j install-service

进入到bin目录,执行

neo4j console: 直接启动 neo4j 服务,

此外,还有其他几个命令:


install-service | uninstall-ser update-service : 安装/卸载/更新 neo4j 服务

start/stop/restart/status: 启动/停止/重启/状态

-V 输出更多信息


启动成功之后就可以在浏览器进行访问了,默认端口号是7474,ip改为服务器地址。

http://localhost:7474

访问成功应该是下图这个页面,能访问到说明正常启动,输入默认用户名neo4j和密码neo4j进行连接。

image

连接成功后如下图所示:

image

这个界面很友好,英文好的同学可以根据官方向导开始学习了。而像我这种英文渣渣就只能一步步慢慢摸索了。

安装方法2:直接按照带服务端的客户端

对于初学者来说大多数还都是在Windows系统上进行入门学习,所以我们可以直接下载Windows的客户端运行使用。

这里可以直接下载最新版客户端版本

image

安装客户端后可以自行选择任何neo4j server版本进行安装,都是界面化操作,安装好server之后可以直接一键启动,启动成功后也可以使用浏览器http://localhost:7474进行连接,也可以使用客户端连接,很方便。

image

基础工作完成之后,我们开始命令CQL语句的学习。

三:Neo4j Cypher 语言

到这里还是先学习一下Neo4j的数据模型再写CQL吧。

Neo4j数据模型

Neo4j是一个表示关系连接的图数据库,既然是图,那么必然有节点,和连接两个节点之间的关系组成。每个节点相当于一个实体,每个实体都有构成它的属性。

比如刘备和关羽,刘备和关羽都是一个个的实体,都可以称作为一个节点,他们有一个共同的标签:都是人,。他们之间的关系为:兄弟,刘备的属性是仁义、大耳贼、汉皇后裔等等。关羽的属性有:勇猛、忠义等等。

image

在Neo4j中,数据模型的主要构建块是:

节点

节点(Node)是图数据库中的一个基本元素,用来表示一个实体记录,就像关系数据库中的一条记录一 样。在Neo4j中节点可以包含多个属性(Property)和多个标签(Label)。


节点是主要的数据元素,节点通过关系连接到其他节点

节点可以具有一个或多个属性(即,存储为键/值对的属性)

节点有一个或多个标签,用于描述其在图表中的作用

属性

属性(Property)是用于描述图节点和关系的 键值对 。其中Key是一个字符串,值可以通过使用任何 Neo4j数据类型来表示

关系

关系(Relationship)同样是图数据库的基本元素。

当数据库中已经存在节点后,需要将节点连接起来构成图。关系就是用来连接两个节点,关系也称为图论的边(Edge) ,其始端和末端都必须是节点,关系不 能指向空也不能从空发起。关系和节点一样可以包含多个属性,但关系只能有一个类型(Type) 。


关系连接两个节点

关系是方向性的

节点可以有多个甚至递归的关系

关系可以有一个或多个属性(即存储为键/值对的属性)

基于方向性,Neo4j关系被分为两种主要类型:


单向关系

双向关系

标签

标签(Label)将一个公共名称与一组节点或关系相关联, 节点或关系可以包含一个或多个标签。 我们可以为现有节点或关系创建新标签, 我们可以从现有节点或关系中删除标签。

Cypher 语言

Neo4j的Cypher语言是为处理图形数据而构建的,CQL代表Cypher查询语言。像Oracle数据库具有查询 语言SQL,Neo4j具有CQL作为查询语言。


它是Neo4j图形数据库的查询语言。

它是一种声明性模式匹配语言

它遵循SQL语法。

它的语法是非常简单且人性化可读的格式。

CQL命令 用法
CREATE 创建节点,关系和属性
MATCH 检索有关节点,关系和属性数据
RETURN 返回查询结果
WHERE 提供条件过滤检索数据
DELETE 删除节点和关系
REMOVE 删除节点和关系的属性
ORDER BY 排序检索数据
SET 添加或更新标签

官方文档命令说明: https://neo4j.com/docs/cypher-manual/3.5/clauses/

CQL命令实战

直接看Cypher的语法会非常枯燥,本文通过一个实际的案例来一步一步学习如何使用Cypher来操作Neo4J。

CREATE是创建操作,n是节点,Person是 标签 ,代表节点的类型。花括号{}代表节点的 属性 ,属性类似Python的字典。这条语句的含义就是创建一个标签为Person的节点,该节点具有一个name属性,属性值是刘备。return n 就是返回当前节点的值


如图所示,在Neo4J的界面上可以看到创建成功的节点。

image

我们继续来创建三国更多的人物节点,并分别命名:

查看刚创建的这些节点信息

这里,MATCH是匹配操作,而小括号()代表一个 节点 node(可理解为括号类似一个圆形),括号里面的n为 标识符

这里为便于直观感受先使用基本的查询语句,后面再详细讲解。


Neo4J贴心地使用不用的颜色来表示不同类型的节点。

image

这里的方括号[]即为关系,大哥为关系的类型。注意这里的箭头–>是有方向的,表示是从a到b的关系。 如图,刘备和关羽之间建立了大哥关系,


再使用这个命令查看我们刚才创建的关系,通过Neo4J的可视化很明显的可以看出:

image

在关系中,同样的使用花括号{}来增加关系的属性,也是类似Python的字典,这里给大哥关系增加了since属性,属性值为“桃园结义”,表示他们建立兄弟关系的时间。

image

-接下来增加更多的关系

match (p1:shu {name:'刘备'}),(p2:shu{name:'关羽'}) create (p1)- [r:rel {relation:'结义兄弟'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'张飞'}) create (p1)- [r:rel {relation:'结义兄弟'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'马超'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'庞统'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'黄忠'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'赵云'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'魏延'}) create (p1)- [r:rel {relation:'主公'}]->(p2);





    
match (p1:shu {name:'刘备'}),(p2:shu{name:'法正'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'糜芳'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'甘夫人'}),(p2:shu{name:'刘备'}) create (p1)- [r:rel {relation:'妻'}]->(p2);
match (p1:shu {name:'糜夫人'}),(p2:shu{name:'刘备'}) create (p1)- [r:rel {relation:'次妻'}]->(p2);
match (p1:shu {name:'孙尚香'}),(p2:shu{name:'刘备'}) create (p1)- [r:rel {relation:'妻'}]->(p2);
match (p1:shu {name:'关羽'}),(p2:shu{name:'关兴'}) create (p1)- [r:rel {relation:'父子'}]->(p2);
match (p1:shu {name:'关平'}),(p2:shu{name:'关羽'}) create (p1)- [r:rel {relation:'义子'}]->(p2);
match (p1:shu {name:'张飞'}),(p2:shu{name:'张苞'}) create (p1)- [r:rel {relation:'父子'}]->(p2);
match (p1:shu {name:'马腾'}),(p2:shu{name:'马超'}) create (p1)- [r:rel {relation:'父子'}]->(p2);
match (p1:shu {name:'马腾'}),(p2:shu{name:'韩遂'}) create (p1)- [r:rel {relation:'异性兄弟'}]->(p2);
match (p1:shu {name:'马谡'}),(p2:shu{name:'马良'}) create (p1)- [r:rel {relation:'弟弟'}]->(p2);
match (p1:shu {name:'糜芳'}),(p2:shu{name:'糜夫人'}) create (p1)- [r:rel {relation:'兄妹'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'诸葛亮'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'黄月英'}),(p2:shu{name:'诸葛亮'}) create (p1)- [r:rel {relation:'妻'}]->(p2);
match (p1:shu {name:'黄承彦'}),(p2:shu{name:'黄月英'}) create (p1)- [r:rel {relation:'父女'}]->(p2);
match (p1:shu {name:'姜维'}),(p2:shu{name:'诸葛亮'}) create (p1)- [r:rel {relation:'弟子'}]->(p2);
match (p1:shu {name:'诸葛亮'}),(p2:shu{name:'诸葛瑾'}) create (p1)- [r:rel {relation:'兄弟'}]->(p2);
match (p1:shu {name:'诸葛亮'}),(p2:shu{name:'诸葛瞻'}) create (p1)- [r:rel {relation:'父子'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'刘禅'}) create (p1)- [r:rel {relation:'父子'}]->(p2);
match (p1:shu {name:'甘夫人'}),(p2:shu{name:'刘禅'}) create (p1)- [r:rel {relation:'母子'}]->(p2);
match (p1:shu {name:'刘禅'}),(p2:shu{name:'姜维'}) create (p1)- [r:rel {relation:'主公'}]->(p2);
match (p1:shu {name:'诸葛瞻'}),(p2:shu{name:'刘禅'}) create (p1)- [r:rel {relation:'女婿'}]->(p2);
match (p1:shu {name:'刘备'}),(p2:shu{name:'刘胜'}) create (p1)- [r:rel {relation:'后代'}]->(p2);
match (p1:shu {name:'刘胜'}),(p2:shu{name:'刘启'}) create (p1)- [r:rel {relation:'父子'}]->(p2);
match (p1:shu {name:'刘启'}),(p2:shu{name:'刘辩'}) create (p1)- [r:rel {relation:'宗亲'}]->(p2);
match (p1:shu {name:'刘辩'}),(p2:shu{name:'刘协'}) create (p1)- [r:rel {relation:'让位'}]->(p2);
MATCH (p1:wei {name:'曹植'}), (p2:wei {name:'曹操'}) MERGE (p1)-[:儿子]->(p2);
MATCH (p1:wei {name:'曹丕'}), (p2:wei {name:'曹操'}) MERGE (p1)-[:儿子]->(p2);
MATCH (p1:wei {name:'曹操'}), (p2:wei {name:'曹丕'}) MERGE (p1)-[:父亲]->(p2);
MATCH (p1:wei {name:'曹操'}), (p2:wei {name:'曹植'}) MERGE (p1)-[:父亲]->(p2);
MATCH (p1:wu {name:'孙策'}), (p2:wu {name:'孙权'}) MERGE (p1)-[:弟弟  {type:"亲情"}]->(p2);
MATCH (p1:wu {name:'孙权'}), (p2:wu {name:'孙策'}) MERGE (p1)-[:哥哥  {type:"亲情"}]->(p2)
MATCH (p1:wu {name:'周瑜'}), (p2:wu {name:'孙策'}) MERGE (p1)-[:主公  {type:"主从"}]->(p2);

将上面生成的节点和关系语句在neo4j中执行,就可以了。然后查询,就可以看到效果图了,

有点图谱的意思了吧?

image

篇幅太长了,剩下的详细查询方法,更新,删除,等另起一篇文章写。

拜拜~