跳转至

GO

GO从给定起始点开始遍历图。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}:指定跳数。如果没有指定跳数,默认值N1。如果N0,NebulaGraph 不会检索任何边。
  • M TO N {STEP|STEPS}:遍历M~N跳的边。如果M0,输出结果和M1相同,即GO 0 TO 2GO 1 TO 2是相同的。
  • <vertex_list>:用逗号分隔的点 ID 列表,或特殊的引用符$-.id。详情参见管道符
  • <edge_type_list>:遍历的 Edge type 列表。
  • REVERSELY | BIDIRECT:默认情况下检索的是<vertex_list>的出边(正向),REVERSELY表示反向,即检索入边;BIDIRECT 为双向,即检索正向和反向,通过返回 <edge_type>._type 字段判断方向,其正数为正向,负数为反向。
  • WHERE <conditions>:指定遍历的过滤条件。用户可以在起始点、目的点和边使用WHERE子句,还可以结合ANDORNOTXOR一起使用。详情参见 WHERE

    Note

    • 遍历多个 Edge type 时,WHERE子句有一些限制。例如不支持WHERE edge1.prop1 > edge2.prop2
    • GO 语句执行时先遍历所有的点,然后再根据过滤器条件进行过滤。
  • 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

示例

# 返回 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" |
+-------------+
# 添加过滤条件。
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" |
+-----------------+------------+---------------------+
# 遍历多个 Edge type。属性没有值时,会显示`NULL`。
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 的朋友和朋友所属队伍。
nebula> GO FROM "player100" OVER follow REVERSELY \
        YIELD src(edge) AS id | \
        GO FROM $-.id OVER serve \
        WHERE properties($^).age > 20 \
        YIELD properties($^).name AS FriendOf, properties($$).name AS Team;
+---------------------+-----------------+
| FriendOf            | Team            |
+---------------------+-----------------+
| "Boris Diaw"        | "Spurs"         |
| "Boris Diaw"        | "Jazz"          |
| "Boris Diaw"        | "Suns"          |
...

# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v)<-[e:follow]- (v2)-[e2:serve]->(v3)  \
        WHERE id(v) == 'player100' \
        RETURN v2.player.name AS FriendOf, v3.team.name AS Team;
+---------------------+-----------------+
| FriendOf            | Team            |
+---------------------+-----------------+
| "Boris Diaw"        | "Spurs"         |
| "Boris Diaw"        | "Jazz"          |
| "Boris Diaw"        | "Suns"          |
...
# 查询 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" |
...
# 根据年龄分组。
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]     |
+-------------+----------------------------+----------+
# 分组并限制输出结果的行数。
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" | "player125" | "player100" | "player101" |
| "player100" | "player101" | "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 4, 2023