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

2,281 阅读7分钟

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

语句可分为三类,包括读语句、写语句和通用语句。

  • 读语句:MATCH、OPTIONAL MATCH、WHERE、START、Aggregation和LOAD CSV。
  • 写语句:CREATE、MERGR、SET、DELETE、REMOVE、FOREACH和CREATE UNIQUE。
  • 通用语句:RETURN、ORDER BY、LIMIT、SKIP、WITH、UNWIND、UNION和CALL。

3 WHERE

WHERE在MATCH或OPTIONAL MATCH语句中添加约束,或者与WITH一起使用来过滤结果。

WHERE不能单独使用,它只能作为MATCH、OPTIONAL MATCH、START、WITH的一部分。如果是在START和WITH中,它用于过滤结果。对于MATCH和OPTIONAL MATCH,WHERE为模式增加约束,它不能看作是匹配完成后的结果过滤。

3.1 基本使用

3.1.1 布尔运算

可以在WHERE中使用布尔运算符,如AND、OR,以及布尔函数NOT。

MATCH (n)
WHERE n.name = 'Peter' XOR (n.age < 30 AND n.name = 'Tobias') OR NOT (n.name = 'Tobias' OR n.name = 'Peter')
RETURN n

3.1.2 节点标签的过滤

可以在WHERE中类似使用WHERE n:foo 写入标签断言来过滤节点。

MATCH (n)
WHERE n:Swedish
RETURN n

结果: 将返回"Andres"节点。

如果要查询不包含某个标签的其他所有节点的反向查询,可在WHERE后加NOT。

3.1.3 节点属性的过滤

可以在WHERE语句中对节点的属性进行过滤。

MATCH (n)
WHERE n.age < 30
RETURN n

结果: 返回了'Tobias'节点,因为他的年龄小于30。

3.1.4 关系属性的过滤

要对关系属性进行过滤,可在WHERE中添加如下关键词:

MATCH (n)-[k:KNOWS]->(f)
WHERE k.since < 2000
RETURN f

结果: 返回了'Peter',因为Andres自1999年就认识他了。

3.1.5 动态节点属性过滤

以方括号语法的形式可使用动态计算的值来过滤属性。

参数:

{
"prop" : "AGE"
}

查询:

MATCH (n)
WHERE n[toLower($prop)] < 30
RETURN n

结果: 返回了'Tobias',因为他的年龄小于30.

3.1.6 属性存在性检查

使用exists()只能检查节点或者关系的某个属性是否存在。

MATCH (n)
WHERE exists(n.belt)
RETURN n

结果: 'Andres'被返回了,因为只有他有belt属性。

3.2 字符串匹配

可以用 STARTS WITH 和 ENDS WITH 来匹配字符串的开始和结尾。如果不关心所匹配字符串的位置,可以用 CONTAINS ,匹配是区分大小写的。

3.2.1 匹配字符串的开始

STARTS WITH 用于以大小写敏感的方式匹配字符串的开始。

MATCH(n)
WHERE n.name STARTS WITH 'Pet'
RETURN n

结果: 'Peter'返回了,因为他的名字以'Pet'开始。

3.2.2 匹配字符串的结尾

ENDS WITH 用于以大小写敏感的方式匹配字符串的结尾。

MATCH(n)
WHERE n.name ENDS WITH 'ter'
RETURN n

结果: 'Peter'返回了,因为他的名字以'ter'结尾。

3.2.3 字符串包含

CONTAINS 用于检查字符串中是否包含某个字符串,它是大小写敏感的,且不关心匹配部分在字符串中的位置。

MATCH(n)
WHERE n.name CONTAINS 'ete'
RETURN n

结果: 'Peter'返回了,因为他的名字包含'ete'字符串。

3.2.4 字符串反向匹配

使用NOT关键词可以返回不满足给定字符串匹配要求的结果。

MATCH(n)
WHERE NOT n.name ENDS WITH 's'
RETURN n

结果: 'Peter'返回了,因为他的名字不以's'结尾。

3.3 正则表达式

Cypher支持正则表达式过滤。正则表达式的语法继承来自Java正则表达式。它支持字符串如何匹配标记,包括不区分大小写(?i),多行(?m) 和单行(?s)。标记放在正则表达式的开头,例如MATCH(n) WHERE n.name =~ '(?i)Lon.*' RETURN n 将返回名字为"London'和'LonDoN'的节点。

3.3.1 正则表达式

可以使用 =~'regexp'来进行正则表达式的匹配。

MATCH (n) 
WHERE n.name =~ 'Tob.*' 
RETURN n

结果: 'Tobias'返回了,因为他的名字以'Tob'开始。

3.3.2 正则表达式中的转义字符

如果需要在正则表达式中插入斜杠,需使用转义字符。注意:字符串中的反斜杠也需要转义。

MATCH (n) 
WHERE n.address =~ 'Sweden\\/Malmo' 
RETURN n

结果: 'Tobias'返回了,因为他的地址在'Sweden/Malmo'。

3.3.3 正则表达式的非大小写敏感

在正则表达式前面加入(?i)之后,整个正则表达式将变成非大小写敏感。

MATCH (n)
WHERE n.name =~ '(?i)ANDR.*'
RETURN n

结果: 'Andres'被返回了,因为他的名字在不考虑大小写的情况下以'ANDR'开始。

3.4 在WHERE中使用路径模式

3.4.1 模式过滤

模式是返回一个路径列表的表达式。列表表达式也是断言,空列表代表false,非空列表代表true。因此,模式不仅仅是表达式,同时也是断言。模式的局限性在于只能在单条路径中表达它,不能像在MATCH语句中那样使用逗号分隔多条路径,但可以通过AND组合多个模式。

不能在WHERE中的模式引入新的变量。尽管它看起来与MATCH中的模式类似。但MATCH (a)-[]-(b)与WHERE (a)-[]-(b)有很大的不同,前者将产生一个它匹配到的a和b之间路径子图,而后者是排除匹配到的a和b之间没有一个有向关系链的任何子图。

MATCH (tobias { name: 'Tobias'}),(others)
WHERE others.name IN ['Andres','Peter'] AND (tobias)<--(others)
RETURN others

结果: 返回了有外向关系指向'Tobias'的节点。

3.4.2 模式中的NOT过滤

NOT功能可用于排除某个模式。

MATCH (persons),(peter{ name:'Peter'})
WHERE NOT (persons)-->(peter)
RETURN persons

结果: 返回没有外向关系指向'Peter'的节点。

3.4.3 模式中的属性过滤

可以在模式中添加属性来过滤结果。

MATCH (n)
WHERE (n)-[:KNOWS]-({name: 'Tobias'})
RETURN n

结果: 返回与节点'Tobias'有KNOWS关系的所有节点。

3.4.4 关系类型过滤

可以在MATCH模式中添加关系类型,但有时候希望在类型过滤上具有丰富的功能。这时,可以将类型与其他进行比较。例如,下面是一个对关系类型与一个正则表达式进行比较的例子。

MATCH (n)-[r]->()
WHERE n.name='Andres' AND type(r)=~'K.*'
RETURN r

结果: 这个查询返回与节点'Andres'以'K'开始的所有关系。

3.5 列表

3.5.1 IN运算符

检查列表中是否存在某个元素,可以使用IN运算。

MATCH (n)
WHERE a.name IN ['Peter', 'Tobias']
RETURN a

结果: 这个查询检查字符串列表中是否存在某个属性。

3.6 不存在的属性和值

如果属性不存在,对它的判断默认返回false。

对于不存在的属性值就当作null,在下面例子中,对于没有belt属性的节点的比较将返回false。

MATCH (n)
WHERE n.belt = 'white'
RETURN n

结果: 仅返回了belt为white的节点。

3.6.1 属性不存在默认为true的情况

如果要比较的属性存在,则可以与期望的值进行比较。如果不存在(IS NULL),默认值为true。如:

MATCH (n)
WHERE n.belt = 'white' OR  n.belt IS NULL
RETURN n
ORDER BY n.name

结果: 返回了满足belt属性值为white和不存在belt属性的所有节点。

3.6.2 空值过滤

有时候需要测试某个值或变量名是否为null。在Cypher中与SQL类似,可以使用IS NULL。相反,“不为空”使用IS NOT NULL,尽管NOT (IS NULL x)也可以。

MATCH (person)
WHERE person.name = 'Peter' AND person.belt IS NULL
RETURN person

结果: 返回name属性值为'Peter'的且不存在belt属性的节点。

3.7 使用范围

3.7.1 简单范围

检查某个元素是否在指定的范围,可以使用不等运算符<, >=和>

MATCH (a)
WHERE a.name >= 'Peter'
RETURN a

结果: 返回节点的name属性值的字典顺序大于或等于'Peter'的节点。

3.7.2 范围的组合

多个不等式可以组合构成一个范围。

MATCH (a)
WHERE a.name >= 'Andres' AND a.name < 'Tobias'
RETURN a

结果: 返回节点的name属性值的字典顺序介于'Andres'和'Tobias'之间的节点。