知识图谱Neo4j Cypher查询语言详解
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识图谱Neo4j Cypher查询语言详解相关的知识,希望对你有一定的参考价值。
Cypher 语法学习
Cypher 介绍
Cypher 是图形数据库 Neo4j 的查询语言,就像 SQL 在关系型数据库中查询一样。
Cypher 受到不同方法的启发,如 WHERE 和 ORDER BY 受到了 SQL 的启发,模式匹配则借用了 SPARQL 的表达式方法,一些列表语义借用了 Haskell 和 Python 等语言,正则表达式匹配实现实用Scala programming language语言。
Cypher 的构造基于英文散文和简洁的图像,基于英语单词和灵巧的图解,使查询易于编写和阅读。
“Cypher”是一个描述性的图形查询语言,允许不必编写图形结构的遍历代码对图形存储有表现力和效率的查询。
Cypher还在继续发展和成熟,这也就意味着有可能会出现语法的变化。同时也意味着作为组件没有经历严格的性能测试。
Cypher设计的目的是一个人类查询语言,适合于开发者和在数据库上做点对点模式(ad-hoc)查询的专业操作人员(我认为这个很重要)。
Cypher是一个申明式的语言。对比命令式语言如Java和脚本语言如Gremlin和JRuby,它的焦点在于从图中如何找回(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]],Cypher 与 Python 的语法略有不同。
匹配语句
在 Neo4j 中,MATCH 命令用于从数据库中获取节点,关系的信息,类似于 SQL 中的 SELECT。RETURN 则是在 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
只返回 Table
和 Code
视图窗口,并在 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-name
和Property-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 中有两种删除方法,DELETE
和 REMOVE
。DELETE
用于删除节点和关系,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 函数
foreach
是 Cypher
中列表的更新工具,在 foreach 中,支持 create,merge,delete
和 foreach
对图进行修改
// 从字符串文本中创建 角色 节点
foreach(name in split('郭靖,杨过,张无忌',',') | create(n:角色{name:name}))
总结
Cypher 基本命令总结如下表:
命令 | 用法 |
---|---|
CREATE | 创建节点,关系和属性 |
MATCH | 检索有关节点,关系和属性 |
WHERE | 提供条件过滤检索数据 |
DELETE | 删除节点和关系 |
REMOVE | 删除节点和关系的属性 |
SET | 添加或更新标签 |
Cypher 更具体的用法,可以参考 官方API or Link。
感谢!
加油!
以上是关于知识图谱Neo4j Cypher查询语言详解的主要内容,如果未能解决你的问题,请参考以下文章