3.2 Cypher 语法(1)
本节主要描述 Cypher 查询语言的基本语法,因为篇幅较长,分为两期更新。
3.2.1 类型
Cypher 处理的所有值都有一个特定的类型,它支持如下类型:
- 数值型
- 字符串
- 布尔型
- 节点
- 关系
- 路径
- 映射(Map)
- 列表(List)
在 Cypher 语句中,大多数类型的值都可以使用字面值表达式。在使用 null 的时候要特别注意,因为 null 是任何类型的值。节点、关系和路径可以作为模式匹配的返回结果。
**tips: ** 标签(label)不是值,它只是模式匹配的一种语法形式。
3.2.2 表达式
3.2.2.1 概述
Cypher 中的表达式如下:
- 十进制(整型和双精度型)的字面值:13、-4000、 3.14、 6.022E23。
- 十六进制整型字面值(以 0x 开头):0x13zf、0xFC3A9、 -0x66eff。
- 八进制整型字面值(以0开头):01372、 02127、. -05671。
- 字符串字面值:‘Hello’、“World”。
- 布尔字面值:true、 false、 TRUE、FALSE。
- 变量:n、x、rel、 myFancyVariable、 ‘A name with weird stuff in it[]!’ 。
- 属性:n.prop、 x.prop、 rel.thisProperty 、myFancyVariable. "(weird property name)’。
- 动态属性:n[“prop”]、 rel[n.city + n.zip]、map[coll[0]]。
- 参数:$param、$o
- 表达式列表:[‘a’,‘b’]. [1,2,3]、 [‘a’, 2, n.property, $param]、[]。
- 函数调用:length§、 nodes§。
- 聚合函数: avg(x.prop). count(*)。
- 路径-模式: (a)–>()<–(b).
- 计算式: 1 + 2 and 3 <4.
- 返回true或者 false 的断言表达式: a.prop = ‘Hello’、length§>10、 exists(a.name)。
- 正则表达式:a.name =~ 'Tob.*.
- 大小写敏感的字符串匹配表达式: a.surname STARTS WITH ‘Sven’、a.surname ENDS WITH ‘son’ or a.surmame CONTAINS ‘son’.
- CASE表达式。
3.2.2.2 转义字符
字符 | 含义 |
---|---|
\t | 制表符 |
\b | 退格 |
\n | 换行 |
\r | 回车 |
\f | 换页 |
\’ | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
\uxxxx | Unicode UTF-16 编码点(4位的十六进制数字必须以“\u”开头) |
\uxxxxxxxx | Unicode UTF-32 编码点(8位的十六进制数字必须以“\u”开头) |
3.2.2.3 Case 表达式
Cypher 支持 Case 条件表达式,它类似于其他语言中的 if/else 语句。
1.简单的 Case 表达式
计算表达式的值,然后依次与 WHEN 语句中的表达式进行比较,直到匹配上为止。如果未匹配上,则 ELSE 中的表达式将作为结果。如果 ELSE 语句不存在,那么将返回 null 。
语法:
CASE test
WHEN value THEN result
[WHEN ...]
[ELSE default]
END
参数:
- test:一个有效的表达式。
- value:一个表达式,它的结果将与 test 表达式的结果进行比较。
- result:如果 value 表达式能够与 test 表达式匹配,它将作为结果表达式。
- default:没有匹配的情况下的默认返回表达式。
查询:
MATCH (n)
RETURN
CASE n.eyes
WHEN 'blue'
THEN 1
WHEN 'brown'
THEN 2
ELSE 3 END AS result
结果(图片仅为示例):
2.一般的 Case 表达式
按顺序判断断言,直到找到一个为 true , 然后对应的结果被返回。如果没有找到,就返回 ELSE 的值。如果没有 ELSE 语句,则返回 null 。
语法:
CASE
WHEN predicate THEN result
[WHEN ...]
[ELSE default]
END
参数:
- predicate:判断的断言,以找到一个有效的可选项。
- result:如果 predicate 匹配到, result 就作为结果表达式。
- default:没有匹配到情况下,默认返回表达式。
查询:
MATCH (n)
RETURN
CASE
WHEN n.eyes = 'blue'
THEN 1
WHEN n.age < 40
THEN 2
ELSE 3 END AS result
结果(图片仅为示例):
3.2.3 变量
当需要引用模式(Pattern)或者查询某一部分的时候, 可以对其进行命名。针对不同部分的这些命名被称为变量。例如:
MATCH (n)-->(b)
RETURN b
这里的n和b就是变量。
变量名是区分大小写的。它可以包含下划线、字母(a~z、 A~Z)和数字(0~9),但必须以字母开头。如果变量名中需要用到其他字符,可以用反向单引号(’) 将变量名括起来。比如,如果变量名中包含特殊字符 μ ,则可以按如下方式使用:
match ('μg':food) return 'μg'
变量的命名规则同样也适用于属性的命名。
**tips:**变量仅在同一个查询内可见。它不能被用于后续的查询。如果有 WITH 连接起来的多个
查询部分,变量必须列在 WITH 语句中才能应用到后续部分。
3.2.4 参数
Cypher 支持带参数的查询,这意味着开发人员不是必须用字符串来构建查询。此外,这也让执行计划的缓存更容易。
参数能够用于 WHERE语句中的字面值和表达式, START 语句中的索引值、索引查询以及节点和关系的 id 。 参数不能用于属性名、关系类型和标签,因为这些模式(Pattern)将作为查询结构的一部分被编译进查询计划。
合法的参数名是字母、数字以及两者的组合。下面是一个使用参数的完整例子。参数以 JSON 格式提供,具体如何提交它们取决于所使用的驱动程序。
3.2.4.1 字符串
参数:
{
"name": "John"
}
可以有两种查询方式来使用参数,如下:
方式①
MATCH (n)
WHERE n.name = $name
RETURN n
方式②
MATCH (n {name: $name})
RETURN n
3.2.4.2 正则表达式
参数:
{
"regex": ".*h.*"
}
查询:
MATCH (n)
WHERE n.name =~ $regex
RETURN n.name
3.2.4.3 大小写敏感的字符串模式匹配
参数:
{
"name": "Michael"
}
查询:
MATCH (n)
WHERE n.name STARTS WITH $name
RETURN n.name
3.2.4.4 创建带有属性的结点
参数:
{
"props": {
"name": "Andres",
"position": "Developer"
}
}
查询:
CREATE ($props)
3.2.4.5 创建带有多个属性的结点
参数:
{
"props": [ {
"awesome": true,
"name": "Andres",
"position": "Developer"
}, {
"children": 3,
"name": "Michael",
"postion": "Developer"
} ]
}
查询:
UNWIND $props AS properties
CREATE (n:Person)
SET n = properties
RETURN n
3.2.4.6 设置结点的所有属性
注意:这将替换当前的所有属性
参数:
{
"props": {
"name": "Andres",
"position": "Developer"
}
}
查询:
MATCH (n)
WHERE n.name='Michael'
SET n = $props
3.2.4.7 SKIP 和 LIMIT
参数:
{
"s": 1,
"l": 1
}
查询:
MATCH (n)
RETURN n.name
SKIP $s
LIMIT $l
3.2.4.8 结点 id
参数:
{
"id": 0
}
查询:
MATCH (n)
WHERE id(n) = $id
RETURN n.name
3.2.4.9 多个结点 id
参数:
{
"ids": [0, 1, 2]
}
查询:
MATCH (n)
WHERE id(n) IN $ids
RETURN n.name
3.2.5 运算符
3.2.5.1 数学运算符
数学运算符包括 + 、 - 、 * 、 / 、 % 和 ^ 。
3.2.5.2 比较运算符
比较运算符包括 = 、 <> 、 < 、 > 、 <= 、 >= 、 IS NULL 和 IS NOT NULL 。
3.2.5.3 布尔运算符
布尔运算符包括 AND 、 OR 、 XOR 和 NOT 。
3.2.5.4 字符串运算符
连接字符串的运算符为 + ,正则表达式的匹配运算符为 =~ 。
3.2.5.5 列表运算符
列表的连接也可以通过 + 运算符,可以用 IN 来检查列表中是否存在某个元素。
3.2.5.6 属性运算符
Cypher 2.0 版本以后,之前存在的属性运算符 ”?“ 和 “!” 已经被移除了。这个语法不再支持。对于不存在的属性将返回 null 。如果真的还需要 “?” 运算符的功能,可以使用(NOT(has(<ident> .prop)) OR <ident> .prop=<value>)。使用 “?” 表达可选关系也被移除了,取而代之的是 OPTINAL MATCH 。
3.2.5.7 值的相等与比较
Cypher 支持使用 = 和 <> 来比较两个值的相等/不相等关系,同类型的值只有它们是同一个值的时候才相等,如 3=3 和 “x” <> “xy” 。
只有两个 Map 的键相同且指向的值也相等的时候它们才相等。对于列表来说,只有它们包含相等值的相同序列的时候才相等,如 [3, 4]=[1+2, 8/2]。
不同类型的值在比较相等的时候遵循以下规则:
- 路径可看作是一些节点和关系的列表,它等于所有包含相同序列节点和关系的所有列表。
- 对任何值测试是否 = 和 <> null 都将返回 null ,这包括 null=null 和 null<>null 。唯一可靠地测试一个值是否为 null 的方法是使用 IS NULL 或者 IS NOT NULL 。
不同类型之间不能相互比较。特别地,节点、关系和映射之间不能相互比较。
3.2.5.8 值的排列与比较
比较运算符 <= 、 < (升序)和 >= 、 > (降序)可以用于值排序的比较,如下所示。
- 数字型值的排序比较采用数字顺序。
- java.lang.Double.NaN 大于所有值。
- 字符串排序的比较采用字典顺序。如 “x”< “xy” 。
- 布尔值的排序遵循 false < true 。
- 当有个参数为 null 的时候,比较结果为 null ,如 null<3 的结果为 null 。
- 将其他类型的值相互比较进行排序将报错。
3.2.5.9 链式比较运算
比较运算可以被任意地联结在一起,如 x<y<=z 等价于 x<y AND y<=z 。
正式地,如果 a, b, c, …, y, z 是表达式, op1, op2, … opN 是比较运算符,这时,a op1 b
op2 c … y opN z 等价于a op1 b AND b op2 c AND … y opN z。
例如:
MATCH (n) WHERE 21 < n.age <= 30 RETURN n
等价于:
MATCH (n) WHERE 21 < n.age AND n.age <= 30 RETURN n
该查询将匹配年龄介于 21 和 30 之间的所有节点。
3.2.6 注释
Cypher 语言的注释类似其他语言,用双斜线//来注释行,例如:
MATCH (n) RETURN n //这是行末尾注释
MATCH (n)
//这是整行注释
RETURN n
MATCH (n) WHERE n.property='//这不是注释' RETURN n