3.3.1 MATCH语句

MATCH语句用于指定的模式检索数据库。

3.3.1.1 简介

MATCH语句通过模式来检索数据库。它常与带有约束或者断言的WHERE语句一起使用,这使得匹配的模式更具体。断言是模式描述的一部分,不能看作是匹配结果的过滤器。这意味着WHERE应当总是与MATCH语句放在一起使用。

MATCH可以出现在查询的开始或者末尾,也可能位于WITH之后。如果它在语句开头,此时不会绑定任何数据。Neo4j将设计一个搜索去找到匹配这个语句以及WHERE中指定断言的结果。这将牵涉数据库的扫描,搜索特定标签的节点或者搜索一个索引以找到匹配模式的开始点。这个搜索找到的节点和关系可作为一个“绑定模式元素(Bound Pattern Elements)”。它可以用于匹配一些子图的模式,也可以用于任何进一步的MATCH语句,Neo4j将使用这些已知的元素来找到更进一步的未知元素。

Cypher是声明式的,因此查询本身不指定搜索的算法。Neo4j会自动地用最好的方法去找到开始节点和匹配模式。WHERE中的断言可以在模式匹配之前、匹配中或者匹配后进行处理。这可以通过查询编译器来影响这个决定。详情可参见3.5.1节和3.6.4节。

MATCH语句示例如图3-3所示。

图3-3 MATCH语句示例

3.3.1.2 查找节点

1.查询所有节点

通过指定一个不带标签的节点的模式,可以返回图中的所有节点。

查询:

结果将返回数据库中的所有节点。

结果:

2.查询带有某个标签的所有节点

通过指定带有一个标签的节点的模式,可以获取满足该标签的所有节点。

查询:

结果将返回数据库中的所有电影。

结果:

3.查询关联节点

符号--意为相关的,这个关系不带有类型和方向。

查询:

结果将返回'Oliver Stone'导演的所有电影。

结果:

4.匹配标签

可以为查询的节点增加标签约束。

查询:

结果将返回与Person 'Oliver Stone'相连的带有Movie标签的所有节点。

结果:

3.3.1.3 查找关系

1.外向关系

关系的方向可以通过-->或者<--来表示。

查询:

结果将返回与Person 'Oliver Stone'外向连接的所有节点。

结果:

2.有向关系和变量

当需要过滤关系中的属性,或者返回关系的时候,就很有必要使用变量了。

查询:

结果将返回'Oliver Stone'的外向关系的类型。

结果:

3.匹配关系类型

当已知要匹配关系的类型时,可通过冒号后面紧跟关系类型。

查询:

结果将返回电影'Wall Street'中的所有演员。

结果:

4.匹配多种关系类型

当需要匹配多种关系中的一种时,可以通过竖线(|)将多个关系连接在一起。

查询:

结果将返回与'Wall Street'节点关系为ACTED_IN或者DIRECTED的所有节点。

结果:

5.匹配关系类型和使用关系变量

如果想通过变量来引用关系和指定关系类型,可以将它们放在一起。例如:

查询:

结果将返回电影'Wall Street'中所有演员的角色。

结果:

3.3.1.4 关系的深度

1.带有特殊字符的关系类型

某些时候数据库中可能会有非字母字符的类型,或者中间含有空格。可以使用反引号“`”将它们括起来。下面的例子在'Charlie Sheen'和'Rob Reiner'之间添加了一个包含有空格的关系。

查询:

该查询产生的结果如图3-4所示。

图3-4 查询结果图

查询:

结果将返回带有空格的关系类型。

结果:

2.多个关系

关系可以多语句以()--()的形式来表达,或者它们相互连接在一起。例如:

查询:

结果将返回'Charlie Sheen'参演的电影和电影的导演。

结果:

3.可变长度关系

可变长度关系和节点的语法如下:

minHops和maxHops都是可选的,默认值分别为1和无穷大。当没有边界值的时候,点也是可以省略的。当只设置了一个边界的时候,如果省略了点,则意味着这是一个固定长度的模式。

查询:

结果将返回与'Charlie Sheen'具有1跳(Hop)到3跳关系的所有电影。

结果:

4.具有多种关系类型的可变长度关系

可变长度关系可以与多种关系类型组合。在这种情况下,*minHops..maxHops适用于所有关系类型以及它们的任何组合。

查询:

结果将返回与'Charlie Sheen'具有2跳ACTED_IN或DIRECTED关系的所有人员。

结果:

5.可变长度关系的关系变量

当连接两个节点之间的长度是可变的,那么关系变量返回的将可能是一个关系列表。

查询:

结果将返回一个关系列表。

结果:

6.可变长度路径上的属性匹配

带有属性的可变长度关系,意味着路径上的所有关系都必须包含给定的属性值。在这个查询中,'Charlie Sheen'和他的父亲'Martin Sheen'之间有两条路径。其中一条包含一个'blocked'关系,另外一条则没有。首先,通过下面的语句增加BLOCKED和UNBLOCKED关系。

查询:

后续将以图3-5为基础来讲解。

图3-5 可变长度路径上的属性匹配图例

查询:

结果将返回'Charlie Sheen'和'Martin Sheen'之间满足blocked属性值为false的所有关系。

结果:

7.零长度路径

可以通过指定可变长度路径的下界值为零,来实现两个变量指向同一个节点。

查询:

结果将返回电影本身及一跳关系的演员和导演。

结果:

8.命名路径

如果想返回或者需要对路径进行过滤,可以将路径赋值给一个变量。

查询:

结果将返回从'Michael Douglas'开始的路径。

结果:

9.不指定方向匹配关系

可以不指定方向来匹配关系,Cypher将尝试匹配两个方向的关系。

查询:

结果将返回两个相连的节点a和b。

结果:

3.3.1.5 最短路径

1.单条最短路径

通过使用shortestPath函数很容易找到两个节点之间的最短路径,如下所示。

查询:

上面查询的含义为:找到两个节点之间的最短路径,路径最大长度为15。在搜索最短路径的时候,还可以使用关系类型、最大跳数和方向等约束条件。如果用到了WHERE语句,则相关的断言会被包含到shortestPath中去。如果路径的关系元素中用到了none()或者all()断言,那么这些将用于在检索时提高性能。

结果:

2.带断言的最短路径

查询:

这个查询寻找'Charlie Sheen'和'Martin Sheen'之间的最短路径,通过WHERE断言可以确保不考虑两个节点之间的父亲/儿子关系。

结果:

3.所有最短路径

找到两个节点之间的所有最短路径。

查询:

结果将找到'Martin Sheen'和'Michael Douglas'之间的两条最短路径。

结果:

3.3.1.6 通过id查询节点或关系

1.通过id查询节点

可以在断言中使用id()函数来根据id查询节点。

提示:Neo4j会重用已删除的节点和关系的内部id。这意味着依赖Neo4j内部的id存在风险。因此,建议通过程序来产生id。

查询:

结果将返回节点id为0的节点。

结果:

2.通过id查询关系

通过id查询关系与查询节点类似,但在实践中不推荐这么做。

查询:

结果将返回关系id为0的关系。

结果:

3.通过id查询多个节点

通过id查询多个节点的时候,可以将id放到IN语句中。

查询:

结果将返回IN语句中列出的所有节点。

结果: