WHERE
简介
WHERE
子句本身不是一个子句,而是MATCH
、OPTIONAL MATCH
和WITH
子句的一部分。
当与MATCH
和OPTIONAL MATCH
一起使用时,WHERE
会为描述的模式添加约束。它不应该被视为匹配完成后再进行的过滤器。
但在WITH
的情况下,WHERE
只是过滤结果。
在多个MATCH
/ OPTIONAL MATCH
子句的情况下,WHERE
中的谓词始终是紧接其前的MATCH
/ OPTIONAL MATCH
中模式的一部分。如果WHERE
放入错误的MATCH
子句中,则结果和性能都可能会受到影响。
索引 可用于在各种情况下优化使用WHERE
的查询。
示例图
以下图用于下面的示例
要重新创建该图,请在空的 Neo4j 数据库中运行以下查询
CREATE
(andy:Swedish:Person {name: 'Andy', age: 36, belt: 'white'}),
(timothy:Person {name: 'Timothy', age: 25}),
(peter:Person {name: 'Peter', age: 35, email: 'peter_n@example.com'}),
(andy)-[:KNOWS {since: 2012}]->(timothy),
(andy)-[:KNOWS {since: 1999}]->(peter)
基本用法
节点模式谓词
WHERE
可以出现在MATCH
子句或模式推导中的节点模式内
WITH 30 AS minAge
MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person WHERE b.age > minAge)
RETURN b.name
b.name |
---|
|
|
当以这种方式使用时,WHERE
中的谓词可以引用WHERE
子句所属的节点变量,但不能引用MATCH
模式中的其他元素。
相同的规则适用于模式推导
MATCH (a:Person {name: 'Andy'})
RETURN [(a)-->(b WHERE b:Person) | b.name] AS friends
friends |
---|
|
|
布尔运算
以下布尔运算符可与WHERE
子句一起使用:AND
、OR
、XOR
和NOT
。有关运算符如何与null
一起工作的更多信息,请参阅有关使用 null 的章节。
MATCH (n:Person)
WHERE n.name = 'Peter' XOR (n.age < 30 AND n.name = 'Timothy') OR NOT (n.name = 'Timothy' OR n.name = 'Peter')
RETURN
n.name AS name,
n.age AS age
ORDER BY name
name | age |
---|---|
|
|
|
|
|
|
|
根据节点标签过滤
要根据标签过滤节点,请使用WHERE n:foo
在WHERE
关键字后编写标签谓词
MATCH (n)
WHERE n:Swedish
RETURN n.name, n.age
返回Andy
的name
和age
值
n.name | n.age |
---|---|
|
|
|
根据节点属性过滤
要根据节点属性进行过滤,请在WHERE
关键字后编写您的子句
MATCH (n:Person)
WHERE n.age < 30
RETURN n.name, n.age
返回Timothy
的name
和age
值,因为他不到 30 岁
n.name | n.age |
---|---|
|
|
|
根据关系属性过滤
要根据关系属性进行过滤,请在WHERE
关键字后编写您的子句
MATCH (n:Person)-[k:KNOWS]->(f)
WHERE k.since < 2000
RETURN f.name, f.age, f.email
返回Peter
的name
、age
和email
值,因为Andy
从 2000 年之前就认识他了
f.name | f.age | f.email |
---|---|---|
|
|
|
|
根据动态计算的节点属性过滤
要使用动态计算的名称过滤属性,请使用方括号语法
WITH 'AGE' AS propname
MATCH (n:Person)
WHERE n[toLower(propname)] < 30
RETURN n.name, n.age
返回Timothy
的name
和age
值,因为他不到 30 岁
n.name | n.age |
---|---|
|
|
|
STRING
匹配
可以使用STARTS WITH
和ENDS WITH
匹配STRING
的前缀和后缀。要进行子字符串搜索(即,无论在STRING
中的位置如何都匹配),请使用CONTAINS
。
匹配是区分大小写的。尝试对不是STRING
值的值使用这些运算符将返回null
。
使用STARTS WITH
进行前缀STRING
搜索
STARTS WITH
运算符用于对STRING
的开头执行区分大小写的匹配
MATCH (n:Person)
WHERE n.name STARTS WITH 'Pet'
RETURN n.name, n.age
返回Peter
的name
和age
值,因为他的名字以“Pet”开头。
n.name | n.age |
---|---|
|
|
|
使用ENDS WITH
进行后缀STRING
搜索
ENDS WITH
运算符用于对STRING
的结尾执行区分大小写的匹配
MATCH (n:Person)
WHERE n.name ENDS WITH 'ter'
RETURN n.name, n.age
返回Peter
的name
和age
值,因为他的名字以“ter”结尾。
n.name | n.age |
---|---|
|
|
|
使用CONTAINS
进行子字符串搜索
CONTAINS
运算符用于执行区分大小写的匹配,而不管在STRING
中的位置如何
MATCH (n:Person)
WHERE n.name CONTAINS 'ete'
RETURN n.name, n.age
返回Peter
的name
和age
,因为他的名字包含“ete”。
n.name | n.age |
---|---|
|
|
|
检查STRING
是否IS NORMALIZED
IS NORMALIZED
运算符(在 Neo4j 5.17 中引入)用于检查给定的STRING
是否为NFC
Unicode 规范化形式。
MATCH (n:Person)
WHERE n.name IS NORMALIZED
RETURN n.name AS normalizedNames
给定的STRING
值仅包含规范化的 Unicode 字符,因此返回所有匹配的name
属性。有关更多信息,请参阅有关规范化运算符的部分。
normalizedNames |
---|
|
|
|
请注意,当对非STRING
值使用IS NORMALIZED
运算符时,它将返回null
。例如,RETURN 1 IS NORMALIZED
返回null
。
正则表达式
Cypher®支持使用正则表达式进行过滤。正则表达式语法继承自Java 正则表达式。这包括支持更改STRING
值匹配方式的标志,包括不区分大小写的(?i)
、多行(?m)
和点号匹配所有字符(?s)
。
标志位于正则表达式的开头。有关在模式开头给出的正则表达式标志的示例,请参阅不区分大小写的正则表达式部分。
使用正则表达式匹配
要根据正则表达式进行匹配,请使用=~ 'regexp'
MATCH (n:Person)
WHERE n.name =~ 'Tim.*'
RETURN n.name, n.age
返回Timothy
的name
和age
值,因为他的名字以“Tim”开头。
n.name | n.age |
---|---|
|
|
|
正则表达式中的转义
像.
或*
这样的字符在正则表达式中具有特殊含义。要将它们用作普通字符,而没有特殊含义,请对其进行转义。
MATCH (n:Person)
WHERE n.email =~ '.*\\.com'
RETURN n.name, n.age, n.email
返回Peter
的name
、age
和email
值,因为他的电子邮件以“.com”结尾。
n.name | n.age | n.email |
---|---|---|
|
|
|
|
请注意,Java 正则表达式中的正则表达式构造仅在解析给定字符串文字中的转义字符序列后应用。有时需要添加额外的反斜杠来表达正则表达式构造。此列表阐明了这两个定义的组合,其中包含原始转义序列和正则表达式中的结果字符。
字符串文字序列 | 结果正则表达式序列 | 正则表达式匹配 |
---|---|---|
|
制表符 |
制表符 |
|
|
制表符 |
|
退格键 |
退格键 |
|
|
单词边界 |
|
换行符 |
NewLine |
|
|
换行符 |
|
回车符 |
回车符 |
|
|
回车符 |
|
换页符 |
换页符 |
|
|
换页符 |
|
单引号 |
单引号 |
|
双引号 |
双引号 |
|
反斜杠 |
反斜杠 |
|
|
反斜杠 |
|
Unicode UTF-16 代码点( |
Unicode UTF-16 代码点( |
|
|
Unicode UTF-16 代码点( |
使用未经消毒的用户输入的正则表达式会使您容易受到 Cypher 注入的攻击。请考虑改用参数。 |
路径模式表达式
与存在子查询类似,路径模式表达式可用于断言指定路径在图中是否存在至少一次。虽然存在子查询功能更强大,并且能够执行路径模式表达式所能实现的任何操作,但路径模式表达式更简洁。
路径模式表达式具有以下限制(需要扩展功能的用例应考虑改用存在子查询)。
根据模式过滤
MATCH
(timothy:Person {name: 'Timothy'}),
(other:Person)
WHERE (other)-->(timothy)
RETURN other.name, other.age
返回具有到Timothy
的出站关系的节点的name
和age
值。
other.name | other.age |
---|---|
|
|
|
缺少属性和值
如果属性丢失,则默认为false
由于缺少的属性计算为null
,因此示例中的比较对于没有belt
属性的节点将计算为false
。
MATCH (n:Person)
WHERE n.belt = 'white'
RETURN n.name, n.age, n.belt
仅返回具有白色腰带的节点的name
、age
和belt
值。
n.name | n.age | n.belt |
---|---|---|
|
|
|
|
如果属性丢失,则默认为true
要将节点或关系属性与缺少的属性进行比较,请使用IS NULL
运算符。
MATCH (n:Person)
WHERE n.belt = 'white' OR n.belt IS NULL
RETURN n.name, n.age, n.belt
ORDER BY n.name
这将返回所有节点的所有值,即使是那些没有belt
属性的节点。
n.name | n.age | n.belt |
---|---|---|
|
|
|
|
|
|
|
|
|
|
根据null
过滤
要测试值或变量是否为null
,请使用IS NULL
运算符。要测试值或变量是否不为null
,请使用IS NOT NULL
运算符,NOT(IS NULL x)
也有效。
MATCH (person:Person)
WHERE person.name = 'Peter' AND person.belt IS NULL
RETURN person.name, person.age, person.belt
返回名称为Peter
但没有belt
属性的节点的name
和age
值。
person.name | person.age | person.belt |
---|---|---|
|
|
|
|
使用范围
模式元素谓词
可以将WHERE
子句添加到模式元素以指定其他约束。
关系模式谓词
WHERE
也可以出现在MATCH
子句中的关系模式内部。
WITH 2000 AS minYear
MATCH (a:Person)-[r:KNOWS WHERE r.since < minYear]->(b:Person)
RETURN r.since
r.since |
---|
|
|
但是,它不能用于可变长度关系中,因为这会导致错误。例如
WITH 2000 AS minYear
MATCH (a:Person)-[r:KNOWS*1..3 WHERE r.since > b.yearOfBirth]->(b:Person)
RETURN r.since
Relationship pattern predicates are not supported for variable-length relationships.
将谓词放在关系模式内可以提高可读性。请注意,这与使用独立的WHERE
子句严格等价。
WITH 2000 AS minYear
MATCH (a:Person)-[r:KNOWS]->(b:Person)
WHERE r.since < minYear
RETURN r.since
r.since |
---|
|
|
关系模式谓词也可以用在模式推导中,同样适用上述注意事项。
WITH 2000 AS minYear
MATCH (a:Person {name: 'Andy'})
RETURN [(a)-[r:KNOWS WHERE r.since < minYear]->(b:Person) | r.since] AS years
年份 |
---|
|
|