NEO4J-Cypher图数据库查询语言(1)

1,839 阅读6分钟

Cypher图数据库查询语言(1) :Cypher概述

Cypher图数据库查询语言(2) :Cypher基本语法

Cypher图数据库查询语言(3) :Cypher语句-MATCH,OPTIONAL MATCH

Cypher图数据库查询语言(4) :Cypher语句-WHERE

Cypher图数据库查询语言(5) :Cypher语句-START,Aggregation 和 LOAD CSV

Cypher图数据库查询语言(6) :Cypher语句-CREATE,MERGR

Cypher图数据库查询语言(7) :Cypher语句-SET,DELETE,REMOVE

Cypher图数据库查询语言(8) :Cypher语句-FOREACH,CREATE UNIQUE

Cypher图数据库查询语言(9) :Cypher语句-RETURN,ORDER BY

Cypher图数据库查询语言(10) :Cypher语句-LIMIT,SKIP

Cypher图数据库查询语言(11) :Cypher语句-WITH,UNWIND,UNION,CALL

1 Cypher是什么

Cypher 是一种声明式图数据库查询语言,它具有丰富的表现力,能高效地查询和更新图数据。

2 模式(Patterns)

2.1 与关系数据库类比

Neo4j图由节点和关系构成。节点可能还有标签和属性,关系可能还有类型和属性。节点表达的是实体,关系连接一对节点。

Neo4j 关系数据库
节点
节点的标签 表名
属性
一个节点 一行数据
  • 节点可以看作类似关系数据库中的表,但又不完全一样
  • 节点的标签可以理解为不同的表名
  • 属性类似关系数据库中表的列
  • 一个节点的数据类似关系数据库中表的一行数据
  • 拥有相同标签的节点通常具有类似的属性,但不必完全一样,这点与关系数据库中一张表的行数据拥有相同的列是不一样的

2.2 节点语法

Cypher采用一对圆括号()来表示节点,如:()、(foo). 下面是常见的节点表示法:

()
(matrix)
(:Movie)
(matrix:Movie)
(matrix:Movie {title:"The Matrix"})
(matrix:Movie {title:"The Matrix", released:1997})

简单的()表达了一个匿名节点。如果想在其他地方引用这个节点,可以添加一个变量,如(matrix)。此变量可见范围局限于单个语句。

Movie 标签声明了节点类型。

节点的属性以key/value列表形式存在,并外加一对大括号。属性可以存储信息或限制模式。

2.3 关系语法

Cypher使用一对短横线(即--)表示一个无方向关系。
有方向的关系:-->或<--
方括号[]可用于添加变量、属性和类型信息

关系的常见表达方式如下:

-->
-[role]->
-[:ACTED_IN]->
-[role:ACTED_IN]->
-[role:ACTED_IN {roles: ["Neo"]}]->

关系的方括号内的语法和语义与节点类似,定义了可以在别处引用的变量,关系的类型类似于节点的标签,关系的属性等同于节点的属性。

注意,属性的值可以是数组。

2.4 模式语法

将节点和关系的语法组合在一起可以表达模式。简单案例:

(keanu:Person:Actor{name: "Keanu Reeves"}) - [role:ACTED_IN {roles: ["Neo"]}]-> (matrix:Movie {title:"The Matrix"})

2.5 模式变量

为了增强模块性和减少重复,Cypher允许将模式赋给一个变量。这使得匹配到的路径可以用于其他表达式,如:

acted_in = (:Person) - [:ACTED_IN] ->(:Movie)

3 查询和更新图

Cypher语句既可以用于查询,又可以用于更新图数据。

3.1 更新语句的结构

一个Cypher查询部分不能同时匹配和更新图数据。每个部分要么读取和匹配图,要么更新它。

如果需要从图中读取,然后更新图,那么该查询隐含地包含两部分——第一部分是读取,第二部分是写入。如果查询只是读取,Cypher将采用惰性加载(Lazy Load),事实上并没匹配模式,直到需要返回结果时才实际地去匹配。在更新查询语句中,所有的读取操作必须在任何的写操作发生之前完成。

当希望使用聚合数据进行过滤时,必须使用WITH将两个读语句部分连接在一起,】。第一部分做聚合,第二部分过滤来自第一部分的结果,如下所示:

MATCH (n {name:'John'}) - [:FRIEND] - (friend)
WITH n, count(friend) AS friendsCount
WHERE friendsCount > 3
RETURN n, friendsCount

下面是一个将聚合数据更新到图中的例子:

MATCH (n {name:'John'}) - [:FRIEND] - (friend)
WITH n, count(friend) AS friendsCount
SET n.friendCount = friendsCount
RETURN n.friendsCount

3.2 返回数据

任何查询都可以返回数据。RETURN语句有三个子句,分别为SKIPLIMITORDER BY

4 事务

任何更新图的查询都运行在一个事务中。一个更新查询要么全部成功,要么全部失败。Cypher或者创建一个新事务,或者运行在一个已有的事务中:

  • 如果运行上下文中没有事务,Cypher将创建一个,一旦查询完成就提交该事务。
  • 如果运行上下文中已有事务,查询就会运行在该事务中。直到该事务成功地提交之后,数据才会持久化到磁盘中去。

可以将多个查询作为单个事务来提交:
(1) 开始一个事务
(2)运行多个Cypher更新查询
(3)一次提交这些查询

5 唯一性

当进行模式匹配时,Neo4j将确保单个模式中不会包含匹配到多次的同一个图关系。

例如:查找一个用户的朋友的朋友不应该返回该用户。

CREATE (adam:User {name:'Adam'}), (pernilla:User {name:'Pernilla'}), (david:User {name:'David'}), (adam) - [:FRIEND] ->  (Pernilla), (Pernilla) - [:FRIEND] ->  (david)

上面Cypher语句创建的朋友关系:
adam -> pernilla -> david

下面来查询adam的朋友的朋友:

MATCH (user:User {name: 'Adam'}) - [r1:FRIEND] - () -[r2:FRIEND] - (friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

结果:

然而,有时也未必一直希望这样。如果查询应当返回该用户,可以通过多个MATCH语句延伸匹配关系来实现,如下:

MATCH (user:User {name: 'Adam'}) - [r1:FRIEND] - (friend) 
MATCH -[r2:FRIEND] - (friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

注意,下面的查询看起来与前一个类似,但事实上它等价于再前一个。

MATCH (user:User {name: 'Adam'}) - [r1:FRIEND] - (friend), (friend) -[r2:FRIEND] - (friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

这里的MATCH语句包含一个有两条路径的单个模式,而前一个查询有两个不同的模式。

6 兼容性

Cypher不是一成不变的语言。新版本引入了很多新的功能,一些旧的功能可能会被移除。如果需要旧版本依然可以访问到。这里有两种方式在查询中选择使用哪个版本:

  • 为所有查询设置版本:可以通过neo4j.conf中cypher.default_language_version参数来配置Neo4j数据库使用哪个版本的Cypher语言。
  • 在查询中指定版本:简单地在查询开始的时候写上版本,如Cypher2.3.

下面是一个指定使用Cypher2.3的查询例子:

CYPHER 2.3
START n=node:nodes(name = 'A')
RETURN n