GO¶
GO
语句是 NebulaGraph 图数据库中用于从给定起始点开始遍历图的语句。GO
语句采用的路径类型是walk
,即遍历时点和边都可以重复。
openCypher 兼容性¶
本文操作仅适用于原生 nGQL。
语法¶
GO [[<M> TO] <N> {STEP|STEPS} ] FROM <vertex_list>
OVER <edge_type_list> [{REVERSELY | BIDIRECT}]
[ WHERE <conditions> ]
YIELD [DISTINCT] <return_list>
[{ SAMPLE <sample_list> | <limit_by_list_clause> }]
[| GROUP BY {<col_name> | expression> | <position>} YIELD <col_name>]
[| ORDER BY <expression> [{ASC | DESC}]]
[| LIMIT [<offset>,] <number_rows>];
<vertex_list> ::=
<vid> [, <vid> ...]
<edge_type_list> ::=
<edge_type> [, <edge_type> ...]
| *
<return_list> ::=
<col_name> [AS <col_alias>] [, <col_name> [AS <col_alias>] ...]
<N> {STEP|STEPS}
:指定跳数。如果没有指定跳数,默认值N
为1
。如果N
为0
,NebulaGraph 不会检索任何边。
M TO N {STEP|STEPS}
:遍历M~N
跳的边。如果M
为0
,输出结果和M
为1
相同,即GO 0 TO 2
和GO 1 TO 2
是相同的。
<vertex_list>
:用逗号分隔的点 ID 列表。
<edge_type_list>
:遍历的 Edge type 列表。
REVERSELY | BIDIRECT
:默认情况下检索的是<vertex_list>
的出边(正向),REVERSELY
表示反向,即检索入边;BIDIRECT
为双向,即检索正向和反向。可通过YIELD
返回<edge_type>._type
字段判断方向,其正数为正向,负数为反向。
-
WHERE <conditions>
:指定遍历的过滤条件。用户可以在起始点、目的点和边使用WHERE
子句,还可以结合AND
、OR
、NOT
、XOR
一起使用。详情参见 WHERE。Note
- 遍历多个 Edge type 时,
WHERE
子句有一些限制。例如不支持WHERE edge1.prop1 > edge2.prop2
。 - GO 语句执行时先遍历所有的点,然后再根据过滤器条件进行过滤。
- 遍历多个 Edge type 时,
YIELD [DISTINCT] <return_list>
:定义需要返回的输出。<return_list>
建议使用 Schema 相关函数指定返回信息,当前支持src(edge)
、dst(edge)
、type(edge)
等,暂不支持嵌套函数。详情参见 YIELD。
SAMPLE <sample_list>
:用于在结果集中取样。详情参见 SAMPLE。
<limit_by_list_clause>
:用于在遍历过程中逐步限制输出数量。详情参见 LIMIT。
GROUP BY
:根据指定属性的值将输出分组。详情参见 GROUP BY。分组后需要再次使用YIELD
定义需要返回的输出。
-
ORDER BY
:指定输出结果的排序规则。详情参见 ORDER BY。Note
没有指定排序规则时,输出结果的顺序不是固定的。
LIMIT [<offset>,] <number_rows>]
:限制输出结果的行数。详情参见 LIMIT。
使用说明¶
- GO 语句中的
WHERE
和YIELD
子句通常结合属性引用符($^
和$$
)或函数properties($^)
和properties($$)
指定点的属性;使用函数properties(edge)
指定边的属性。用法参见属性引用符和 Schema 相关函数。 - GO 复合语句中如需引用子查询的结果,需要为该结果设置别名,并使用管道符
|
传递给下一个子查询,同时在下一个子查询中使用$-
引用该结果的别名。详情参见管道符。 - 当查询属性没有值时,返回结果显示
NULL
。
场景及示例¶
查询起始点的直接邻居点¶
场景:查询某个点的直接相邻点,例如查询一个人所属队伍。
# 返回 player102 所属队伍。
nebula> GO FROM "player102" OVER serve YIELD dst(edge);
+-----------+
| dst(EDGE) |
+-----------+
| "team203" |
| "team204" |
+-----------+
查询指定跳数内的点¶
场景:查询一个点在指定跳数内的所有点,例如查询一个人两跳内的朋友。
# 返回距离 player102 两跳的朋友。
nebula> GO 2 STEPS FROM "player102" OVER follow YIELD dst(edge);
+-------------+
| dst(EDGE) |
+-------------+
| "player101" |
| "player125" |
| "player100" |
| "player102" |
| "player125" |
+-------------+
# 查询 player100 1~2 跳内的朋友。
nebula> GO 1 TO 2 STEPS FROM "player100" OVER follow \
YIELD dst(edge) AS destination;
+-------------+
| destination |
+-------------+
| "player101" |
| "player125" |
...
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v) -[e:follow*1..2]->(v2) \
WHERE id(v) == "player100" \
RETURN id(v2) AS destination;
+-------------+
| destination |
+-------------+
| "player100" |
| "player102" |
...
添加过滤条件¶
场景:查询满足特定条件的点和边,例如查询起始点和目的点之间具有特定属性的边。
# 使用 WHERE 添加过滤条件。
nebula> GO FROM "player100", "player102" OVER serve \
WHERE properties(edge).start_year > 1995 \
YIELD DISTINCT properties($$).name AS team_name, properties(edge).start_year AS start_year, properties($^).name AS player_name;
+-----------------+------------+---------------------+
| team_name | start_year | player_name |
+-----------------+------------+---------------------+
| "Spurs" | 1997 | "Tim Duncan" |
| "Trail Blazers" | 2006 | "LaMarcus Aldridge" |
| "Spurs" | 2015 | "LaMarcus Aldridge" |
+-----------------+------------+---------------------+
查询所有边¶
场景:查询起始点关联的所有边。
# 返回 player102 关联的所有边。
nebula> GO FROM "player102" OVER * BIDIRECT YIELD edge AS e;
+-----------------------------------------------------------------------+
| e |
+-----------------------------------------------------------------------+
| [:follow "player101"->"player102" @0 {degree: 90}] |
| [:follow "player103"->"player102" @0 {degree: 70}] |
| [:follow "player135"->"player102" @0 {degree: 80}] |
| [:follow "player102"->"player100" @0 {degree: 75}] |
| [:follow "player102"->"player101" @0 {degree: 75}] |
| [:serve "player102"->"team203" @0 {end_year: 2015, start_year: 2006}] |
| [:serve "player102"->"team204" @0 {end_year: 2019, start_year: 2015}] |
+-----------------------------------------------------------------------+
查询多个 Edge type¶
场景:查询起始点关联的多个边类型可以通过设置多个Edge Type实现,也可以通过设置*
关联所有的边类型。
# 遍历多个 Edge type。
nebula> GO FROM "player100" OVER follow, serve \
YIELD properties(edge).degree, properties(edge).start_year;
+-------------------------+-----------------------------+
| properties(EDGE).degree | properties(EDGE).start_year |
+-------------------------+-----------------------------+
| 95 | __NULL__ |
| 95 | __NULL__ |
| __NULL__ | 1997 |
+-------------------------+-----------------------------+
查询入边方向的点¶
# 返回关注 player100 的邻居点。
nebula> GO FROM "player100" OVER follow REVERSELY \
YIELD src(edge) AS destination;
+-------------+
| destination |
+-------------+
| "player101" |
| "player102" |
...
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v)<-[e:follow]- (v2) WHERE id(v) == 'player100' \
RETURN id(v2) AS destination;
+-------------+
| destination |
+-------------+
| "player101" |
| "player102" |
...
子查询作为起始点¶
场景:使用子查询的结果作为图遍历的起始点。
# 查询 player100 年龄大于 20 的朋友和这些朋友所属队伍。
nebula> GO FROM "player100" OVER follow \
YIELD dst(edge) AS id | \
GO FROM $-.id OVER serve \
WHERE properties($^).age > 20 \
YIELD properties($^).name AS Friend, properties($$).name AS Team;
+---------------------+-----------------+
| Friend | Team |
+---------------------+-----------------+
| "Tony Parker" | "Spurs" |
| "Tony Parker" | "Hornets" |
| "Manu Ginobili" | "Spurs" |
+---------------------+-----------------+
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v)-[e:follow]-> (v2)-[e2:serve]->(v3) \
WHERE id(v) == 'player100' \
AND properties(v2).age > 20 \
RETURN v2.player.name AS Friend, v3.team.name AS Team;
+---------------------+-----------------+
| Friend | Team |
+---------------------+-----------------+
| "Tony Parker" | "Spurs" |
| "Tony Parker" | "Hornets" |
| "Manu Ginobili" | "Spurs" |
+---------------------+-----------------+
使用 GROUP BY 分组¶
场景:使用GROUP BY
分组,然后使用YIELD
返回分组后的结果。
# 根据年龄分组。
nebula> GO 2 STEPS FROM "player100" OVER follow \
YIELD src(edge) AS src, dst(edge) AS dst, properties($$).age AS age \
| GROUP BY $-.dst \
YIELD $-.dst AS dst, collect_set($-.src) AS src, collect($-.age) AS age;
+-------------+----------------------------+----------+
| dst | src | age |
+-------------+----------------------------+----------+
| "player125" | {"player101"} | [41] |
| "player100" | {"player125", "player101"} | [42, 42] |
| "player102" | {"player101"} | [33] |
+-------------+----------------------------+----------+
使用 ORDER BY 和 LIMIT 排序和限制输出结果¶
# 分组并限制输出结果的行数。
nebula> $a = GO FROM "player100" OVER follow YIELD src(edge) AS src, dst(edge) AS dst; \
GO 2 STEPS FROM $a.dst OVER follow \
YIELD $a.src AS src, $a.dst, src(edge), dst(edge) \
| ORDER BY $-.src | OFFSET 1 LIMIT 2;
+-------------+-------------+-------------+-------------+
| src | $a.dst | src(EDGE) | dst(EDGE) |
+-------------+-------------+-------------+-------------+
| "player100" | "player101" | "player100" | "player101" |
| "player100" | "player125" | "player100" | "player125" |
+-------------+-------------+-------------+-------------+
其他用法¶
# 在多个边上通过 IS NOT EMPTY 进行判断。
nebula> GO FROM "player100" OVER follow WHERE properties($$).name IS NOT EMPTY YIELD dst(edge);
+-------------+
| dst(EDGE) |
+-------------+
| "player125" |
| "player101" |
+-------------+
最后更新:
September 6, 2024