运算符

此页面包含对可用 Cypher® 运算符的概述。

运算符概览

聚合运算符

DISTINCT

属性运算符

. 用于静态属性访问,[] 用于动态属性访问,= 用于替换所有属性,+= 用于修改特定属性

数学运算符

+, -, *, /, %, ^

比较运算符

=<><><=>=IS NULLIS NOT NULL

STRING 特定比较运算符

STARTS WITHENDS WITHCONTAINS=~(正则表达式匹配)

布尔运算符

ANDORXORNOT

字符串运算符

+||(字符串连接)、IS NORMALIZED

时间运算符

+- 用于持续时间和时间点/持续时间之间的运算,*/ 用于持续时间和数字之间的运算

映射运算符

. 用于通过键静态访问值,[] 用于通过键动态访问值

列表运算符

+||(列表连接)、IN 用于检查列表中是否存在元素、[] 用于动态访问元素

聚合运算符

聚合运算符包括

  • 删除重复值:DISTINCT

使用DISTINCT运算符

检索Person节点中唯一的眼睛颜色。

查询
CREATE
  (a:Person {name: 'Anne', eyeColor: 'blue'}),
  (b:Person {name: 'Bill', eyeColor: 'brown'}),
  (c:Person {name: 'Carol', eyeColor: 'blue'})
WITH [a, b, c] AS ps
UNWIND ps AS p
RETURN DISTINCT p.eyeColor

即使**'Anne'** 和 **'Carol'** 都有蓝色的眼睛,**'blue'** 也只返回一次。

表 1. 结果
p.eyeColor

"blue"

"brown"

行数:2
创建的节点:3
设置的属性:6
添加的标签:3

DISTINCT 通常与聚合函数结合使用。

属性运算符

属性运算符与节点或关系相关,包括

  • 使用点运算符静态访问节点或关系的属性:.

  • 使用下标运算符动态访问节点或关系的属性:[]

  • 属性替换=用于替换节点或关系的所有属性

  • 属性修改运算符+=用于设置节点或关系的特定属性

使用.运算符静态访问节点或关系的属性

查询
CREATE
  (a:Person {name: 'Jane', livesIn: 'London'}),
  (b:Person {name: 'Tom', livesIn: 'Copenhagen'})
WITH a, b
MATCH (p:Person)
RETURN  p.name
表 2. 结果
p.name

"Jane"

"Tom"

行数:2
创建的节点:2
设置的属性:4
添加的标签:2

使用[]运算符对动态计算的属性键进行过滤

查询
CREATE
  (a:Restaurant {name: 'Hungry Jo', rating_hygiene: 10, rating_food: 7}),
  (b:Restaurant {name: 'Buttercup Tea Rooms', rating_hygiene: 5, rating_food: 6}),
  (c1:Category {name: 'hygiene'}),
  (c2:Category {name: 'food'})
WITH a, b, c1, c2
MATCH (restaurant:Restaurant), (category:Category)
WHERE restaurant["rating_" + category.name] > 6
RETURN DISTINCT restaurant.name
表 3. 结果
restaurant.name

"Hungry Jo"

行数:1
创建的节点:4
设置的属性:8
添加的标签:4

有关动态属性访问的更多详细信息,请参阅基本用法

[]运算符关于null的行为在此处详细说明。

使用=运算符替换节点或关系的所有属性

查询
CREATE (a:Person {name: 'Sofia', age: 20})
WITH a
MATCH (p:Person {name: 'Sofia'})
SET p = {name: 'Ellen', livesIn: 'London'}
RETURN p.name, p.age, p.livesIn

节点上的所有现有属性都将替换为映射中提供的属性;即name属性从Sofia更新为Ellenage属性被删除,并添加了livesIn属性。

表 4. 结果
p.name p.age p.livesIn

"Ellen"

<null>

"London"

行数:1
创建的节点:1
设置的属性:5
添加的标签:1

有关使用属性替换运算符=的更多详细信息,请参阅使用映射和=替换所有属性

使用+=运算符修改节点或关系的特定属性

查询
CREATE (a:Person {name: 'Sofia', age: 20})
WITH a
MATCH (p:Person {name: 'Sofia'})
SET p += {name: 'Ellen', livesIn: 'London'}
RETURN p.name, p.age, p.livesIn

节点上的属性将按映射中提供的内容进行如下更新:name属性从Sofia更新为Ellenage属性保持不变,并添加了livesIn属性。

表 5. 结果
p.name p.age p.livesIn

"Ellen"

20

"London"

行数:1
创建的节点:1
设置的属性:4
添加的标签:1

有关使用属性修改运算符+=的更多详细信息,请参阅使用映射和+=修改特定属性

数学运算符

数学运算符包括

  • 加法:+

  • 减法或一元负号:-

  • 乘法:*

  • 除法:/

  • 取模运算:%

  • 指数运算:^

使用指数运算符 ^

查询
WITH 2 AS number, 3 AS exponent
RETURN number ^ exponent AS result
表 6. 结果
结果

8.0

行数:1

使用一元负号运算符 -

查询
WITH -3 AS a, 4 AS b
RETURN b - a AS result
表 7. 结果
结果

7

行数:1

比较运算符

比较运算符包括:

  • 相等:=

  • 不相等:<>

  • 小于:<

  • 大于:>

  • 小于或等于:<=

  • 大于或等于:>=

  • IS NULL

  • IS NOT NULL

STRING 特定的比较运算符包括:

  • STARTS WITH:对 STRING 值执行区分大小写的词缀搜索。

  • ENDS WITH:对 STRING 值执行区分大小写的后缀搜索。

  • CONTAINS:对 STRING 值执行区分大小写的包含搜索。

  • =~:用于匹配模式的正则表达式。

比较两个数字

查询
WITH 4 AS one, 3 AS two
RETURN one > two AS result
表 8. 结果
结果

行数:1

有关比较运算符行为的更多详细信息,请参阅 值的相等性和比较;有关这些运算符如何使用的更多示例,请参阅 使用范围

使用 STARTS WITH 过滤名称

查询
WITH ['John', 'Mark', 'Jonathan', 'Bill'] AS somenames
UNWIND somenames AS names
WITH names AS candidate
WHERE candidate STARTS WITH 'Jo'
RETURN candidate
表 9. 结果
候选

"John"

"Jonathan"

行数:2

STRING 匹配 包含有关 STRING 特定比较运算符的更多信息,以及说明其用法的其他示例。

值的相等性和比较

相等性

Cypher 支持使用 =<> 运算符通过相等性比较值(请参阅 属性、结构和构造值)。

只有当相同类型的值是完全相同的值时,它们才相等(例如,3 = 3"x" <> "xy")。

只有当映射将完全相同的键映射到相等的值时,映射才相等;只有当列表包含相同顺序的相等值时,列表才相等(例如,[3, 4] = [1+2, 8/2])。

不同类型的值根据以下规则被视为相等:

  • 路径被视为交替节点和关系的列表,并且等于包含完全相同的节点和关系序列的所有列表。

  • 使用 =<> 运算符将任何值与 null 进行比较始终评估为 null。这包括 null = nullnull <> null。可靠地测试值 v 是否为 null 的唯一方法是使用特殊的 v IS NULLv IS NOT NULL 相等性运算符。v IS NOT NULL 等效于 NOT(v IS NULL)

所有其他值的类型组合都不能相互比较。特别是,节点、关系和文字映射之间是不可比较的。

比较不可比较的值是错误的。

值的排序和比较

比较运算符 <=<(用于升序)和 >=>(用于降序)用于比较值的排序。以下几点详细说明了如何执行比较。

  • 数值使用数值顺序进行排序比较(例如,3 < 4 为真)。

  • 所有与 java.lang.Double.NaN 的可比性测试(<<=>>=)都评估为假。例如,当 b 为 NaN 时,1 > b1 < b 都为假。

  • 字符串值使用字典顺序进行排序比较(例如,"x" < "xy")。

  • 布尔值用于排序比较,使得 false < true

  • 不能使用 <<=>>= 运算符比较空间值。要在特定范围内比较空间值,请使用 point.withinBBox()point() 函数。

  • 空间值的排序

    • ORDER BY 要求所有值都可排序。

    • 点在数组之后,时间类型之前排序。

    • 不同 CRS 的点按 CRS 代码(SRID 字段的值)排序。对于当前支持的 坐标参考系统 集,这意味着顺序为:4326、4979、7302、9157

    • 相同 CRS 的点按每个坐标值依次排序,首先是 x,然后是 y,最后是 z

    • 请注意,此顺序与空间索引返回的顺序不同,空间索引的顺序将是空间填充曲线的顺序。

  • 时间值的比较

    • 时间瞬间值 在相同类型内是可比较的。如果一个瞬间在时间上早于另一个瞬间,则认为它小于另一个瞬间;如果它在时间上晚于另一个瞬间,则认为它大于另一个瞬间。

    • 发生在同一时间点但具有不同时区的瞬间值不被视为相等,因此必须以某种可预测的方式排序。Cypher 规定,在时间点的主要顺序之后,瞬间值按有效时区偏移量排序,从西(UTC 的负偏移量)到东(UTC 的正偏移量)。这样一来,表示同一时间点的事件将按照最早的本地时间排序。如果两个瞬间值表示同一时间点,并且具有相同的时区偏移量,但具有不同的命名时区(这仅适用于 DateTime,因为 Time 仅具有偏移量),则这些值不被视为相等,并按时区标识符(按字母顺序)作为其第三个排序组件排序。如果类型、时间点、偏移量和时区名称都相等,则这些值相等,并且任何顺序差异都无法观察到。

    • 持续时间 值不可比较,因为如果不了解是哪一天、哪个月或哪一年,则不知道一天、一个月或一年的长度。由于 持续时间 值不可比较,因此在两个 持续时间 值之间应用比较运算符的结果为 null

  • 时间值的排序

    • ORDER BY 要求所有值都可排序。

    • 时间实例在空间实例之后,字符串之前排序。

    • 可比较的值应按照其比较顺序所暗示的相同顺序排序。

    • 时间瞬间值首先按类型排序,然后按类型内的比较顺序排序。

    • 由于无法为 持续时间 值定义完整的比较顺序,因此我们专门为 持续时间 定义了 ORDER BY 的顺序

      • 持续时间 值通过将所有组件标准化为好像所有年份都为 365.2425 天长(PT8765H49M12S),所有月份都为 30.4368751/12 年)天长(PT730H29M06S),并且所有天都为 24 小时长 [1] 来排序。

  • 当一个参数为 null 时进行排序比较(例如,null < 3null)。

  • 不同类型的值的排序

  • 构造类型值的排序

    • 对于 构造类型(例如,映射和列表),容器的元素成对比较以进行排序,从而确定两个容器类型的排序。例如,[1, 'foo', 3][1, 2, 'bar'] 之前排序,因为 'foo'2 之前排序。

链接比较运算

比较可以任意链接,例如,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

请注意,a op1 b op2 c 并不意味着 ac 之间有任何类型的比较,因此,例如,x < y > 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 的链。

=<> 的链在 Cypher 中以特殊方式处理。

这意味着 1=1=true 等效于 1=1 AND 1=true,而不是 (1=1)=true1=(1=true)

例如

a < b = c <= d <> e

等效于

a < b AND b = c AND c <= d AND d <> e

使用 =~ 和正则表达式过滤单词

查询
WITH ['mouse', 'chair', 'door', 'house'] AS wordlist
UNWIND wordlist AS word
WITH word
WHERE word =~ '.*ous.*'
RETURN word
表 10. 结果
单词

"mouse"

"house"

行数:2

有关在过滤中使用正则表达式的更多信息和示例,请参阅 正则表达式

布尔运算符

布尔运算符(也称为逻辑运算符)包括:

  • 合取:AND

  • 析取:OR

  • 异或:XOR

  • 否定:NOT

以下是 ANDORXORNOT 的真值表。

a b a AND b a OR b a XOR b NOT a

使用布尔运算符过滤数字

查询
WITH [2, 4, 7, 9, 12] AS numberlist
UNWIND numberlist AS number
WITH number
WHERE number = 4 OR (number > 6 AND number < 10)
RETURN number
表 11. 结果
数字

4

7

9

行数:3

字符串运算符

字符串运算符包括:

  • 连接STRING值:+||

  • 检查STRING是否已标准化:IS NORMALIZED

使用+连接两个STRING

使用+连接字符串的功能等同于使用||。但是,+字符串连接运算符不符合GQL规范

查询
RETURN 'neo' + '4j' AS result
表 12. 结果
结果

"neo4j"

行数:1

使用||连接两个STRING

查询
RETURN 'neo' || '4j' AS result
表 13. 结果
结果

"neo4j"

行数:1

检查STRING是否IS NORMALIZED

IS NORMALIZED运算符用于检查给定的STRING是否为NFC Unicode标准化形式。

Unicode标准化是一个将相同字符串的不同表示形式转换为标准化形式的过程。有关更多信息,请参阅Unicode标准化形式的文档。

查询
RETURN "the \u212B char" IS NORMALIZED AS normalized
表 14. 结果
normalized

由于给定的STRING包含一个未标准化的Unicode字符(\u212B),因此返回false

要标准化STRING,请使用normalize()函数。

请注意,当IS NORMALIZED运算符用于非STRING值时,它将返回null。例如,RETURN 1 IS NORMALIZED将返回null

检查STRING是否IS NOT NORMALIZED

IS NOT NORMALIZED运算符用于检查给定的STRING是否不是NFC Unicode标准化形式。

查询
RETURN "the \u212B char" IS NOT NORMALIZED AS notNormalized
表 15. 结果
notNormalized

由于给定的STRING包含一个未标准化的Unicode字符(\u212B),并且未标准化,因此返回true

要标准化STRING,请使用normalize()函数。

请注意,当IS NOT NORMALIZED运算符用于非STRING值时,它将返回null。例如,RETURN 1 IS NOT NORMALIZED将返回null

使用指定的标准化类型与IS NORMALIZED

可以定义使用哪种Unicode标准化类型(默认值为NFC)。

可用的标准化类型为:

  • NFC

  • NFD

  • NFKC

  • NFKD

查询
WITH "the \u00E4 char" as myString
RETURN myString IS NFC NORMALIZED AS nfcNormalized,
    myString IS NFD NORMALIZED AS nfdNormalized

给定的STRING包含Unicode字符:\u00E4,在NFC形式中被认为是标准化的,但在NFD形式中则不是。

表 16. 结果
nfcNormalized nfdNormalized

行数:2

也可以在使用否定标准化运算符时指定标准化形式。例如,RETURN "string" IS NOT NFD NORMALIZED

时间运算符

时间运算符包括:

  • DURATION添加到时间点或另一个DURATION+

  • 从时间点或另一个DURATION中减去DURATION-

  • DURATION乘以数字:*

  • DURATION除以数字:/

下表显示了 — 对于操作和操作数类型的每种组合 — 从应用每个时间运算符返回的值的类型。

运算符 左操作数 右操作数 结果类型

+

时间点

DURATION

时间点的类型

+

DURATION

时间点

时间点的类型

-

时间点

DURATION

时间点的类型

+

DURATION

DURATION

DURATION

-

DURATION

DURATION

DURATION

*

DURATION

数字

DURATION

*

数字

DURATION

DURATION

/

DURATION

数字

DURATION

向时间点添加或从中减去DURATION

查询
WITH
  localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14}) AS aDateTime,
  duration({years: 12, nanoseconds: 2}) AS aDuration
RETURN aDateTime + aDuration, aDateTime - aDuration
表 17. 结果
aDateTime + aDuration aDateTime - aDuration

1996-10-11T12:31:14.000000002

1972-10-11T12:31:13.999999998

行数:1

DURATION的组成部分不适用于时间点将被忽略。例如,当将DURATION添加到DATE时,DURATION小时分钟纳秒将被忽略(ZONED TIMELOCAL TIME的行为类似)。

查询
WITH
  date({year:1984, month:10, day:11}) AS aDate,
  duration({years: 12, nanoseconds: 2}) AS aDuration
RETURN aDate + aDuration, aDate - aDuration
表 18. 结果
aDate + aDuration aDate - aDuration

1996-10-11

1972-10-11

行数:1

将两个持续时间添加到时间点不是一个关联操作。这是因为不存在的日期将被截断到最接近的现有日期。

查询
RETURN
  (date("2011-01-31") + duration("P1M")) + duration("P12M") AS date1,
  date("2011-01-31") + (duration("P1M") + duration("P12M")) AS date2
表 19. 结果
date1 date2

2012-02-28

2012-02-29

行数:1

向另一个DURATION添加或从中减去DURATION

查询
WITH
  duration({years: 12, months: 5, days: 14, hours: 16, minutes: 12, seconds: 70, nanoseconds: 1}) as duration1,
  duration({months:1, days: -14, hours: 16, minutes: -12, seconds: 70}) AS duration2
RETURN duration1, duration2, duration1 + duration2, duration1 - duration2
表 20. 结果
duration1 duration2 duration1 + duration2 duration1 - duration2

P12Y5M14DT16H13M10.000000001S

P1M-14DT15H49M10S

P12Y6MT32H2M20.000000001S

P12Y4M28DT24M0.000000001S

行数:1

DURATION乘以或除以数字

这些操作被简单地解释为基于除法(以及分数乘法)中单位平均长度的溢出到较小单位的逐成分操作。

查询
WITH duration({days: 14, minutes: 12, seconds: 70, nanoseconds: 1}) AS aDuration
RETURN aDuration, aDuration * 2, aDuration / 3
表 21. 结果
aDuration aDuration * 2 aDuration / 3

P14DT13M10.000000001S

P28DT26M20.000000002S

P4DT16H4M23.333333333S

行数:1

映射运算符

映射运算符包括:

  • 使用点运算符静态访问映射中键的值:.

  • 使用下标运算符动态访问映射中键的值:[]

有关[]运算符相对于null的行为,请参阅使用null页面。

使用.运算符静态访问嵌套映射中键的值

查询
WITH {person: {name: 'Anne', age: 25}} AS p
RETURN  p.person.name
表 22. 结果
p.person.name

"Anne"

行数:1

使用[]运算符和参数动态访问映射中键的值

可以使用参数指定要访问的值的键。

参数
{
  "myKey" : "name"
}
查询
WITH {name: 'Anne', age: 25} AS a
RETURN a[$myKey] AS result
表 23. 结果
结果

"Anne"

行数:1

更多信息可以在映射章节中找到。

列表运算符

列表运算符包括:

  • 连接列表l1l2[l1] + [l2][l1] || [l2]

  • 检查元素e是否存在于列表l中:e IN [l]

  • 使用下标运算符动态访问列表中的元素:[]

有关IN[]运算符相对于null的行为,请参阅此处

使用+连接两个列表

查询
RETURN [1,2,3,4,5] + [6,7] AS myList
表 24. 结果
myList

[1,2,3,4,5,6,7]

行数:1

使用||连接两个列表

查询
RETURN [1,2,3,4,5] || [6,7] AS myList
表 25. 结果
myList

[1,2,3,4,5,6,7]

行数:1

使用IN检查数字是否在列表中

查询
WITH [2, 3, 4, 5] AS numberlist
UNWIND numberlist AS number
WITH number
WHERE number IN [2, 3, 8]
RETURN number
表 26. 结果
数字

2

3

行数:2

使用IN进行更复杂的列表成员资格操作

一般规则是,如果作为右操作数给定的列表包含一个与左操作数具有相同类型和内容(或值)的元素,则IN运算符将评估为true。列表只能与其他列表进行比较,并且列表innerList的元素将按升序从innerList中的第一个元素到innerList中的最后一个元素进行成对比较。

以下查询检查列表[2, 1]是否为列表[1, [2, 1], 3]的元素。

查询
RETURN [2, 1] IN [1, [2, 1], 3] AS inList

该查询评估为true,因为右边的列表包含一个元素,即列表[1, 2],它与左操作数具有相同的类型(列表)并包含相同的内容(按给定顺序的数字21)。如果左操作数为[1, 2]而不是[2, 1],则查询将返回false

表 27. 结果
inList

行数:1

乍一看,以下查询中左操作数和右操作数的内容似乎相同。

查询
RETURN [1, 2] IN [1, 2] AS inList

但是,IN评估为false,因为右操作数不包含与左操作数具有相同类型 — 即列表 — 的元素。

表 28. 结果
inList

行数:1

以下查询可用于确定列表 — 例如,从labels()函数获得的列表 — 是否包含至少一个也存在于另一个列表中的元素。

MATCH (n)
WHERE size([label IN labels(n) WHERE label IN ['Person', 'Employee'] | 1]) > 0
RETURN count(n)

只要labels(n)返回PersonEmployee(或两者),查询将返回大于零的值。

使用[]运算符访问列表中的元素

查询
WITH ['Anne', 'John', 'Bill', 'Diane', 'Eve'] AS names
RETURN names[1..3] AS result

方括号将从起始索引1提取元素,直到(但不包括)结束索引3

表 29. 结果
结果

["John","Bill"]

行数:1

使用[]运算符和参数动态访问列表中的元素

可以使用参数指定要访问的元素的索引。

参数
{
  "myIndex" : 1
}
查询
WITH ['Anne', 'John', 'Bill', 'Diane', 'Eve'] AS names
RETURN names[$myIndex] AS result
表 30. 结果
结果

"John"

行数:1

在嵌套列表上使用IN[]

IN可以与[]结合使用以测试元素是否存在于嵌套列表中。

查询
WITH [[1, 2, 3]] AS l
RETURN 3 IN l[0] AS result
表 31. 结果
结果

行数:1

有关列表的更多详细信息,请参阅一般列表


1. 每年的365.2425天来自闰年的频率。闰年发生在序数可被4整除的年份,不可被100整除,除非可被400整除。这意味着在400年内有((365 * 4 + 1) * 25 - 1) * 4 + 1 = 146097天,这意味着平均每年365.2425天。