知识图谱Neo4j Cypher查询语言详解

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识图谱Neo4j Cypher查询语言详解相关的知识,希望对你有一定的参考价值。

Cypher 介绍

Cypher 是图形数据库 Neo4j 的查询语言,就像 SQL 在关系型数据库中查询一样。

Cypher 受到不同方法的启发,如 WHEREORDER BY 受到了 SQL 的启发,模式匹配则借用了 SPARQL 的表达式方法,一些列表语义借用了 HaskellPython 等语言,正则表达式匹配实现实用Scala programming language语言。

Cypher 的构造基于英文散文和简洁的图像,基于英语单词和灵巧的图解,使查询易于编写和阅读。

Cypher”是一个描述性的图形查询语言,允许不必编写图形结构的遍历代码对图形存储有表现力和效率的查询。

Cypher还在继续发展和成熟,这也就意味着有可能会出现语法的变化。同时也意味着作为组件没有经历严格的性能测试。

Cypher设计的目的是一个人类查询语言,适合于开发者和在数据库上做点对点模式(ad-hoc)查询的专业操作人员(我认为这个很重要)。

Cypher是一个申明式的语言。对比命令式语言如Java和脚本语言如GremlinJRuby,它的焦点在于从图中如何找回(what to retrieve),而不是怎么去做。这使得在不对用户公布的实现细节里关心的是怎么优化查询。

启动 Neo4j

打开终端,启动 Neo4j 服务

./neo4j start

打开浏览器,输入 http://127.0.0.1:7474/browser/ 进入 Neo4j 客户端,客户端上方的输入栏用于输入 Cypher 语句,按回车或者点击右侧三角形按钮执行 Cypher 语句,shift + 回车 进行换行。

在这里插入图片描述

基本类型

Cypher 中有以下几种基本类型:

  • 数值
  • 字符串
  • 布尔
  • 节点
  • 关系
  • 列表

数值,布尔,字符串

Cypher 中的数据类型如下

  • boolean 用于表示布尔值:true false
  • byte 用于表示 8 位整数
  • short 用于表示 16 位整数
  • int 用于表示 32 位整数
  • long 用于表示 64 位整数
  • float 用于表示 32 位浮点数
  • double 用于表示 64 位浮点数
  • char 用于表示 16 位字符
  • string 用于表示字符串

数值类型支持的常用算术运算

  • +加法运算
  • -减法运算
  • *乘法运算
  • /除法运算
  • %取余运算
  • ^幂运算
// 执行算术运算,用 return 返回结果,不同运算用 , 隔开
return 1+1,1.2-3,100000*1000,100/200,3%4,2^10,True,false

在这里插入图片描述
字符串类型支持的常用函数有

  • toUpper 用于将所有字母更改为大写字母
  • toLower 用于将所有字母改为小写字母
  • SUBSTRING 用于获取给定 String 的子字符串
  • REPLACE 用于替换一个字符串的子字符串
  • SPLIT 用于切分字符串
  • +用于字符串拼接
// 执行字符串函数,用 return 返回结果,不同运算用 , 隔开
return toUpper('a'),toLower('A'),SUBSTRING('abcdefghijk',1,3),replace('abcde','ab','de'),split('abc,def',','),'1'+'2'

在这里插入图片描述

节点和关系

Cypher 采用一对圆括号 () 来表示节点,如 (n:角色) 表示一个 角色 节点,n 是变量名,供命令执行时用 n 来访问这个节点,在命令执行完毕后就无法使用了。同时单独的 () 表示一个匿名节点,在匹配时表示匹配所有节点。

在关系中

  • --表示无方向的关系

  • --> 表示有方向的关系

  • -[r]-> 则给关系赋予一个变量名,方便对这个关系进行操作

  • -[r:配偶]-> 匹配关系为 配偶 的类型

同时为了书写简单,可以为节点和关系语法赋予一个变量

//将所有 (角色)-[配偶]-() 的子图赋值给变量 p
p = (n:角色)-[r:配偶]-()

这样变量 p 就可以写到多个查询语句中,避免重复编写

列表

Cypher 支持列表操作,并且和 Python 中的列表很相似。通过 [] 来创建列表,同时与 Python 相同,列表中可以包含不同的元素。

// 执行列表操作,用 return 返回结果
return [1,'1',True,'1'+'2']

在这里插入图片描述
Python 相同,Cypher 同样支持列表推导,列表中用符号 | 隔开,前面的是列表元素,后面的是表达式

// 对 1-3 的数做除以 2 的操作
return [x in [1,2,3] | x/2]

在这里插入图片描述

要注意 Python 中的写法是 [x/2 for x in [1,2,3]],CypherPython 的语法略有不同。

匹配语句

Neo4j 中,MATCH 命令用于从数据库中获取节点,关系的信息,类似于 SQL 中的 SELECTRETURN 则是在 MATCH 搜索完成后返回数据,因此 MATCH 必须与 RETURN 同时使用。

根据标签匹配节点

// 匹配所有 角色 节点
match (n:角色) return n

可以看到 Graph 视图窗口显示 角色 节点一共有 35 个。
在这里插入图片描述

根据标签和属性匹配节点

// 匹配 name 为 郭靖 的 角色 节点
match (n:角色{name:'郭靖'}) return n

在这里插入图片描述

匹配任意关系

// 匹配出有任意关系的两个节点
match p = (n)-[r]->(m) return p

在这里插入图片描述

可选匹配

optional match 类似于 match,不同之处在于 optional match 在匹配不到内容时返回 null 方便查询继续进行,而 match 直接返回查询无结果

// 用 match 匹配 郭靖 是否有关系到 倚天屠龙记
match p=(n:角色{name:'郭靖'})-[r]->(:作品{name:'倚天屠龙记'}) return p

因为查询无结果,所以 match 只返回 TableCode 视图窗口,并在 Table 视图窗口显示查询无结果。在这里插入图片描述

// 用 optional match 匹配 郭靖 是否有关系到 倚天屠龙记
optional match p=(n:角色{name:'郭靖'})-[r]->(:作品{name:'倚天屠龙记'}) return p

可以看到 Table 视图窗口返回了变量 P 的值,为 null
在这里插入图片描述

过滤匹配

就像 SQL 一样, Neo4j 中提供 WHERE 子句来过滤 MATCH 的查询结果

// 查询 `郭靖` 在哪些作品中出现
MATCH (n:作品)-[]-(m:角色) where m.name='郭靖' return n.name

在这里插入图片描述
同时 WHERE 可以结合函数 exists() ,字符串匹配 starts with,ends with,contains,逻辑匹配 in,not,and,or 和正则表达式匹配进行更加精细的匹配

// 属性存在性检查函数 exists(),匹配所有拥有 desc 属性的节点
match (n) where exists(n.desc)  return n

在这里插入图片描述

// 匹配所有 name 起始为 郭 的节点
match (n) where n.name starts with "郭" return n

在这里插入图片描述

// 匹配所有 与 杨过 和 小龙女 有关的节点,同时过滤掉 杨康 和 张三丰
match p=(n)--(m) where  n.name in ['杨过','小龙女'] and not m.name in ['杨康','张三丰'] return p

在这里插入图片描述
正则表达式的语法为 =~ 'regexp'

// 匹配所有 name 包含 龙 的节点,这个正则表达式等价为 match(n) where n.name contains '龙' return n
match (n) where n.name =~ '.+?龙.+' return n

在这里插入图片描述
LIMIT 子句用于限制返回匹配结果的数量

// 查询射雕英雄传作品中三个 `角色` 名
MATCH (n:作品)-[]-(m:角色) where n.name='射雕英雄传' return m.name limit 3

在这里插入图片描述

路径长度匹配

在关系中,允许匹配特定路径长度的内容,如:

  • (n)-[*2]->(m) 表示关系数量为 2 的 3 个节点的匹配, 等价于 (a)-[]->()-[]->(b)
  • (n)-[*2..4]->(m) 匹配路径长度为 2 到 4 之间的路径
  • (n)-[*2..]->(m) 匹配路径长度大于 2 的路径
  • (n)-[*..4]->(m) 匹配路径长度小于 4 的路径
  • (n)-[*]->(m) 匹配任意长度的路径

示例:

// 匹配 郭靖 到 黄蓉,路径长度为 1 到 3 的所有结果
MATCH p=(n)-[*1..3]-(m) where n.name='郭靖' and m.name='黄蓉' return p

在这里插入图片描述

CREATE 命令

Neo4j 中,CREATE 命令用于创建节点关系

创建节点

CREATE 创建单个节点语法如下:

CREATE (
    <node-name>:<lable-name>
    {
        <Property1-name>:<Property1-value>
        ......
        <Propertyn-name>:<Propertyn-value>:
    }
)

node-name 是要创建的节点名称,label-name 是节点标签名称。 Property-nameProperty-value 分别是节点的属性值的 key-value 对。

如创建一个 金轮法王 节点,即在 label 为 角色的节点中创建一个 name金轮法王 的节点,同时为这个节点拥有来自 蒙古 的属性

// 创建 角色 节点,拥有属性 name-金轮法王,from-蒙古
CREATE (n:角色 {name:'金轮法王',from:'蒙古'})

同时可以看到左侧的 Node Labels 节点数从 64 个增加到了 65 个。

在这里插入图片描述
但在进行这个操作后,视图界面并不返回 Graph 界面,因为 CREATE 命令可以允许不跟 RETURN 同时使用,若使用了 RETURN,才会返回 Graph 界面。

创建关系

CREATE 创建单个关系到节点语法如下:

CREATE (<node1-name>:<lable1-name>)-
        [(relationship-name:<relationship-label-name>)]
        ->(<node2-name>:<lable2-name>)

Neo4j 只支持有向图,node1-name 为出节点,node2-name 为入节点, relationship-name 为关系的名称,relationship-label-name 为关系的标签名称。

CREATE (n:角色{name:'王重阳',nickname:'中神通'})-
        [:师弟]
        ->(m:角色{name:'周伯通',nickname:'老顽童'})

在这里插入图片描述

混合使用

因为存在两个内容完全相同的节点,因此,要给已经存在的两个节点创建关系,则不能简单地使用 CREATE 命令,而是要先用 MATCH 找到已存在的节点,再构建关系。

如要创建 金轮法王杨过 的关系,则先要找到 金轮法王杨过 这两个节点,再向这两个节点之间添加关系

match (n:角色),(m:角色) where n.name='金轮法王' and m.name='杨过'  create (n)-[:对手]->(m)

在这里插入图片描述

MERGE 命令

MERGE 命令是 CREATE 命令和 MATCH 命令的组合。 MERGE 在图中搜索给定模式,如果存在,则返回结果,如果不存在,则创建并返回结果。

如用 MERGE 命令增加少林门派

merge (n:门派{name:'少林'}) return n

在这里插入图片描述
此时查询所有 门派 信息,可以看到一共有 7 个 门派
在这里插入图片描述
若此时执行:

merge (n:门派{name:'丐帮'}) return n

在这里插入图片描述
丐帮 节点已经存在,所以不会增加新的 丐帮 节点,查询所有 门派 信息时可以看到依然是 7 个门派。

SET 子句

SET 用于给现有节点或关系添加新属性,因此,SET 需要配合 MATCH 使用。 如给 杨过 节点增加一个 “西狂” 属性

match (n:角色) where n.name='杨过' set n.nickname='西狂' return n

在这里插入图片描述

SHORTESTPATH 函数

shortestPath 函数用于查找两个节点之间的最短路径。 如查找 张无忌降龙十八掌 之间的关系
在这里插入图片描述
这个图说明,洪七公 曾经教授过 杨过杨过 又教授过 张三丰,最后 张三丰 教授过 张无忌,同时 洪七公 的武功有 降龙十八掌

DELETE 删除和 REMOVE 删除

Neo4j 中有两种删除方法,DELETEREMOVEDELETE用于删除节点和关系,REMOVE 用于删除节点和关系的标签与属性。两者都需要配合 MATCH ,先匹配到内容,再执行操作

删除属性

REMOVE金轮法王from 属性删除。

match (n:角色) where n.name='金轮法王' remove n.from return n

在这里插入图片描述
此时点击节点,可以看到 from 属性已经被删掉了。

删除节点和边

若要删除节点,则需要删除与节点相关的所有边,这与图论一致——不存在没有节点的边。 因此要删掉金轮法王这个节点,就先需要找到该节点和所在关系,再进行删除

match (n:角色)-[r]-() where n.name='金轮法王' delete n,r

在这里插入图片描述

清空数据库

清空数据库,意味着要清空所有的节点节点存在两种情况:有边连接的和孤立的节点,因此需要同时匹配这两种情况,再进行删除

match (n) optional match (n)-[r]-() delete n,r

在这里插入图片描述

可以从侧边栏看到关系和节点都已经被删除。

FOREACH 函数

foreachCypher 中列表的更新工具,在 foreach 中,支持 create,merge,deleteforeach 对图进行修改

// 从字符串文本中创建 角色 节点
foreach(name in split('郭靖,杨过,张无忌',',') | create(n:角色{name:name}))

在这里插入图片描述

总结

Cypher 基本命令总结如下表:

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

Cypher 更具体的用法,可以参考 官方API or Link

感谢!

加油!

以上是关于知识图谱Neo4j Cypher查询语言详解的主要内容,如果未能解决你的问题,请参考以下文章

快速入门知识图谱 - Neo4J Cypher查询语言教程

快速入门知识图谱 - Neo4J Cypher查询语言教程

Cypher语法

Neo4j的查询语法笔记

Neo4j的查询语法笔记

知识图谱开发实战:搭建上市公司知识图谱