Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update match and return #1376

Merged
merged 5 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
317 changes: 69 additions & 248 deletions docs-2.0/3.ngql-guide/7.general-query-statements/2.match.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,27 @@ MATCH <pattern> [<clause_1>] RETURN <output> [<clause_2>];

- `output`:定义需要返回的输出。可以使用`AS`设置输出的别名。

!!! compatibility "历史版本兼容性"

从 3.0 版本开始,`pattern`支持同时匹配多个 Tag,所以返回属性时,需要额外指定 Tag 名称。即从`RETURN 变量名.属性名`改为`RETURN 变量名.Tag.属性名`。

- `clause_2`:支持`ORDER BY`、`LIMIT`子句。

## MATCH 工作流程

1. `MATCH`语句使用原生索引查找起始点或边,起始点或边可以在模式的任何位置。即一个有效的`MATCH`语句,**必须有一个属性、Tag 或 Edge type 已经创建索引,或者在`WHERE`子句中用 id() 函数指定了特定点的 VID**。如何创建索引,请参见[创建原生索引](../14.native-index-statements/1.create-native-index.md)。

2. `MATCH`语句在模式中搜索,寻找匹配的边或点。
## 注意事项

!!! note

`MATCH`语句采用的路径类型是`trail`,即遍历时只有点可以重复,边不可以重复。详情请参见[路径](../../1.introduction/2.1.path.md)。

3. `MATCH`语句根据`RETURN`子句检索数据。
!!! compatibility "历史版本兼容性"

## openCypher 兼容性
从 3.0.0 版本开始,`pattern`支持同时匹配多个 Tag,所以返回属性时,需要额外指定 Tag 名称。即从`RETURN 变量名.属性名`改为`RETURN 变量名.Tag.属性名`。

- nGQL 不支持遍历所有点和边,例如`MATCH (v) RETURN v`。但是,建立相应 Tag 的索引后,可以遍历对应 Tag 的所有点,例如`MATCH (v:T1) RETURN v`
- `MATCH`语句中的`WHERE`子句内不支持图模式

- WHERE 子句内不支持图模式
- `MATCH`语句采用的路径类型是`trail`,即遍历时只有点可以重复,边不可以重复。详情请参见[路径](../../1.introduction/2.1.path.md)

## 使用模式(pattern)
- `MATCH`语句中`WHERE`子句使用 id() 函数指定了点的 VID,不需要创建索引即可执行。

### 前提条件
- 当遍历所有点边时,例如`MATCH (v) RETURN v LIMIT <number_rows>`,和当遍历指定 Tag 的点或指定 Edge Type 的边时,例如`MATCH (v:T1) RETURN v LIMIT <number_rows>`,不需要创建索引,但需要使用`LIMIT`限制输出结果数量。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 当遍历所有点边时,例如MATCH (v) RETURN v LIMIT N不需要创建索引,但需要使用LIMIT限制输出结果数量。
  • 当遍历指定 Tag 的点或指定 Edge Type 的边时,例如MATCH (v:T1) RETURN v LIMIT N,不需要创建索引,但需要使用LIMIT限制输出结果数量。
  • 除以上两种情况之外,请确保MATCH语句有至少一个索引可用。如何创建和使用索引,请参见创建原生索引


请确保`MATCH`语句有至少一个索引可用,或者其中指定了 VID。如果需要创建索引,但是已经有相关的点、边或属性,用户必须在创建索引后重建索引,索引才能生效。
- 除以上两种情况之外,请确保`MATCH`语句有至少一个索引可用。如果需要创建索引,但是已经有相关的点、边或属性,用户必须在创建索引后重建索引,索引才能生效。如何创建索引,请参见[创建原生索引](../14.native-index-statements/1.create-native-index.md)

!!! caution
## 示例

索引会导致写性能大幅降低(降低 90%甚至更多)。请**不要随意**在生产环境中使用索引,除非很清楚使用索引对业务的影响。
### 创建索引

```ngql
# 在 Tag player 的 name 属性和 Edge type follow 上创建索引。
Expand Down Expand Up @@ -98,25 +86,44 @@ nebula> SHOW JOB 122;

### 匹配点

!!! Compatibility "历史版本兼容性"

在 Nebula Graph 3.0.0 之前,不支持 `MATCH (v) RETURN v`。在 Nebula Graph 3.0.0 开始,支持`MATCH (v) RETURN v`,不需要创建索引,但需要使用 `LIMIT` 限制输出结果数量。

用户可以在一对括号中使用自定义变量来表示模式中的点。例如`(v)`。

```ngql
nebula> MATCH (v) \
RETURN v \
LIMIT 3;
+-----------------------------------------------------------+
| v |
+-----------------------------------------------------------+
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
| ("player106" :player{age: 25, name: "Kyle Anderson"}) |
| ("player115" :player{age: 40, name: "Kobe Bryant"}) |
+-----------------------------------------------------------+
```

### 匹配 Tag

!!! Note
!!! Compatibility "历史版本兼容性"

匹配 Tag 的前提是 Tag 本身有索引或者 Tag 的某个属性有索引,否则,用户无法基于该 Tag 执行 `MATCH` 语句。
在 Nebula Graph 3.0.0 之前,匹配 Tag 的前提是 Tag 本身有索引或者 Tag 的某个属性有索引,否则,用户无法基于该 Tag 执行 `MATCH` 语句。从Nebula Graph 3.0.0 开始,匹配 Tag 可以不创建索引,但需要使用 `LIMIT` 限制输出结果数量

用户可以在点的右侧用`:<tag_name>`表示模式中的 Tag。

```ngql
nebula> MATCH (v:player) \
RETURN v;
+---------------------------------------------------------------+
| v |
+---------------------------------------------------------------+
| ("player105" :player{age: 31, name: "Danny Green"}) |
| ("player109" :player{age: 34, name: "Tiago Splitter"}) |
| ("player111" :player{age: 38, name: "David West"}) |
RETURN v \
LIMIT 3;
+-----------------------------------------------------------+
| v |
+-----------------------------------------------------------+
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
| ("player106" :player{age: 25, name: "Kyle Anderson"}) |
| ("player115" :player{age: 40, name: "Kobe Bryant"}) |
+-----------------------------------------------------------+
...
```

Expand Down Expand Up @@ -207,7 +214,7 @@ nebula> MATCH (v:player { name: 'Tim Duncan' })--(v2) \

!!! compatibility "历史版本兼容性"

在 nGQL 1.x 中,`--`符号用于行内注释, nGQL 2.x ,`--`符号表示出边或入边,不再用于注释。
在 nGQL 1.x 中,`--`符号用于行内注释, nGQL 2.x ,`--`符号表示出边或入边,不再用于注释。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"})--(v2:player) \
Expand Down Expand Up @@ -305,34 +312,43 @@ nebula> MATCH p=(v:player{name:"Tim Duncan"})-->(v2) \

### 匹配边

除了用`--`、`-->`、`<--`表示未命名的边之外,用户还可以在方括号中使用自定义变量命名边。例如`-[e]-`。
!!! Compatibility "历史版本兼容性"

在 Nebula Graph 3.0.0 之前,匹配边的前提是边本身有对应属性的索引,否则,用户无法基于边执行 `MATCH` 语句。从 Nebula Graph 3.0.0 开始,匹配边可以不创建索引,但需要使用 `LIMIT` 限制输出结果数量,并且必须指定边的方向。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"})-[e]-(v2) \
RETURN e;
+-----------------------------------------------------------------------+
| e |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
| [:follow "player101"->"player100" @0 {degree: 95}] |
| [:follow "player102"->"player100" @0 {degree: 75}] |
...
nebula> MATCH ()<-[e]-() \
RETURN e \
LIMIT 3;
+----------------------------------------------------+
| e |
+----------------------------------------------------+
| [:follow "player101"->"player102" @0 {degree: 90}] |
| [:follow "player103"->"player102" @0 {degree: 70}] |
| [:follow "player135"->"player102" @0 {degree: 80}] |
+----------------------------------------------------+
```

### 匹配 Edge type

和点一样,用户可以用`:<edge_type>`表示模式中的 Edge type,例如`-[e:follow]-`。

!!! Compatibility "历史版本兼容性"

在 Nebula Graph 3.0.0 之前,匹配 Edge Type 的前提是 Edge type 本身有对应属性的索引,否则,用户无法基于 Edge Type 执行 `MATCH` 语句。从 Nebula Graph 3.0.0 开始,匹配 Edge Type 可以不创建索引,但需要使用 `LIMIT` 限制输出结果数量,并且必须指定边的方向。

```ngql
nebula> MATCH ()-[e:follow]-() \
RETURN e;
+-----------------------------------------------------+
| e |
+-----------------------------------------------------+
| [:follow "player104"->"player105" @0 {degree: 60}] |
| [:follow "player113"->"player105" @0 {degree: 99}] |
| [:follow "player105"->"player100" @0 {degree: 70}] |
...
nebula> MATCH ()-[e:follow]->() \
RETURN e \
limit 3;
+----------------------------------------------------+
| e |
+----------------------------------------------------+
| [:follow "player102"->"player100" @0 {degree: 75}] |
| [:follow "player102"->"player101" @0 {degree: 75}] |
| [:follow "player129"->"player116" @0 {degree: 90}] |
+----------------------------------------------------+

```

### 匹配边的属性
Expand Down Expand Up @@ -501,202 +517,7 @@ nebula> MATCH (v1:player{name:"Tim Duncan"}), (v2:team{name:"Spurs"}) \
+----------------------------------------------------+----------------------------------+
```

## 常用检索操作

### 检索点或边的信息

使用`RETURN {<vertex_name> | <edge_name>}`检索点或边的所有信息。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"}) \
RETURN v;
+----------------------------------------------------+
| v |
+----------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------+

nebula> MATCH (v:player{name:"Tim Duncan"})-[e]->(v2) \
RETURN e;
+-----------------------------------------------------------------------+
| e |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
| [:follow "player100"->"player101" @0 {degree: 95}] |
| [:follow "player100"->"player125" @0 {degree: 95}] |
+-----------------------------------------------------------------------+
```

### 检索点 ID

使用`id()`函数检索点 ID。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"}) \
RETURN id(v);
+-------------+
| id(v) |
+-------------+
| "player100" |
+-------------+
```

### 检索 Tag

使用`labels()`函数检索点上的 Tag 列表。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"}) \
RETURN labels(v);
+------------+
| labels(v) |
+------------+
| ["player"] |
+------------+
```

检索列表`labels(v)`中的第 N 个元素,可以使用`labels(v)[n-1]`。例如下面示例使用`labels(v)[0]`检索第一个元素。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"}) \
RETURN labels(v)[0];
+--------------+
| labels(v)[0] |
+--------------+
| "player" |
+--------------+
```

### 检索点或边的单个属性

使用`RETURN {<vertex_name> | <edge_name>}.<property>`检索单个属性。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"}) \
RETURN v.player.age;
+--------------+
| v.player.age |
+--------------+
| 42 |
+--------------+
```

使用`AS`设置属性的别名。

```ngql
nebula> MATCH (v:player{name:"Tim Duncan"}) \
RETURN v.player.age AS Age;
+-----+
| Age |
+-----+
| 42 |
+-----+
```

### 检索点或边的所有属性

使用`properties()`函数检索点或边的所有属性。

```ngql
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[]->(v2) \
RETURN properties(v2);
+----------------------------------+
| properties(v2) |
+----------------------------------+
| {name: "Spurs"} |
| {age: 36, name: "Tony Parker"} |
| {age: 41, name: "Manu Ginobili"} |
+----------------------------------+
```

### 检索 Edge type

使用`type()`函数检索匹配的 Edge type。

```ngql
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e]->() \
RETURN DISTINCT type(e);
+----------+
| type(e) |
+----------+
| "serve" |
| "follow" |
+----------+
```

### 检索路径

使用`RETURN <path_name>`检索匹配路径的所有信息。

```ngql
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[*3]->() \
RETURN p;
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| p |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:follow@0 {degree: 90}]->("player102" :player{age: 33, name: "LaMarcus Aldridge"})-[:serve@0 {end_year: 2019, start_year: 2015}]->("team204" :team{name: "Spurs"})> |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:follow@0 {degree: 90}]->("player102" :player{age: 33, name: "LaMarcus Aldridge"})-[:serve@0 {end_year: 2015, start_year: 2006}]->("team203" :team{name: "Trail Blazers"})> |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:follow@0 {degree: 90}]->("player102" :player{age: 33, name: "LaMarcus Aldridge"})-[:follow@0 {degree: 75}]->("player101" :player{age: 36, name: "Tony Parker"})> |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
...
```

### 检索路径中的点

使用`nodes()`函数检索路径中的所有点。

```ngql
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[]->(v2) \
RETURN nodes(p);
+---------------------------------------------------------------------------------------------------------------------+
| nodes(p) |
+---------------------------------------------------------------------------------------------------------------------+
| [("player100" :star{} :player{age: 42, name: "Tim Duncan"}), ("player204" :team{name: "Spurs"})] |
| [("player100" :star{} :player{age: 42, name: "Tim Duncan"}), ("player101" :player{name: "Tony Parker", age: 36})] |
| [("player100" :star{} :player{age: 42, name: "Tim Duncan"}), ("player125" :player{name: "Manu Ginobili", age: 41})] |
+---------------------------------------------------------------------------------------------------------------------+
```

### 检索路径中的边

使用`relationships()`函数检索路径中的所有边。

```ngql
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[]->(v2) \
RETURN relationships(p);
+-------------------------------------------------------------------------+
| relationships(p) |
+-------------------------------------------------------------------------+
| [[:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}]] |
| [[:follow "player100"->"player101" @0 {degree: 95}]] |
| [[:follow "player100"->"player125" @0 {degree: 95}]] |
+-------------------------------------------------------------------------+
```

### 检索路径长度

使用`length()`函数检索路径的长度。

```ngql
nebula> MATCH p=(v:player{name:"Tim Duncan"})-[*..2]->(v2) \
RETURN p AS Paths, length(p) AS Length;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+
| Paths | Length |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:serve@0 {end_year: 2016, start_year: 1997}]->("team204" :team{name: "Spurs"})> | 1 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})> | 1 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})> | 1 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:serve@0 {end_year: 2018, start_year: 1999}]->("team204" :team{name: "Spurs"})> | 2 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:serve@0 {end_year: 2019, start_year: 2018}]->("team215" :team{name: "Hornets"})> | 2 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:follow@0 {degree: 95}]->("player100" :player{age: 42, name: "Tim Duncan"})> | 2 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:follow@0 {degree: 90}]->("player102" :player{age: 33, name: "LaMarcus Aldridge"})> | 2 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})> | 2 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})-[:serve@0 {end_year: 2018, start_year: 2002}]->("team204" :team{name: "Spurs"})> | 2 |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})-[:follow@0 {degree: 90}]->("player100" :player{age: 42, name: "Tim Duncan"})> | 2 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+
```

### 多MATCH检索
## 多MATCH检索

不同的模式有不同的筛选条件时,可以使用多`MATCH`,会返回模式完全匹配的行。

Expand All @@ -712,7 +533,7 @@ nebula> MATCH (m)-[]->(n) WHERE id(m)=="player100" \
+-------------+-------------+-------------+
```

### OPTIONAL MATCH检索
## OPTIONAL MATCH检索

参见[OPTIONAL MATCH](optional-match.md)。

Expand Down
Loading