MATCH

    一个MATCH语句定义了一个搜索模式,用该模式匹配存储在Nebula Graph中的数据,然后用RETURN子句检索数据。

    本文示例使用测试数据集进行演示。

    GOLOOKUP等其他查询语句相比,MATCH的语法更灵活。MATCH语法可以概括如下:

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

    2. MATCH语句在模式中搜索,寻找匹配的边或点。

      Note

      MATCH语句采用的路径类型是trail,即遍历时只有点可以重复,边不可以重复。详情请参见。

    3. MATCH语句根据RETURN子句检索数据。

    • nGQL不支持遍历所有点和边,例如MATCH (v) RETURN v。但是,建立相应Tag的索引后,可以遍历对应Tag的所有点,例如MATCH (v:T1) RETURN v

    • WHERE子句内不支持图模式。

    请确保MATCH语句有至少一个索引可用,或者其中指定了VID。如果需要创建索引,但是已经有相关的点、边或属性,用户必须在创建索引后重建索引,索引才能生效。

    Caution

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

    1. # 在Tag player的name属性和Edge type follow上创建索引。
    2. nebula> CREATE TAG INDEX name ON player(name(20));
    3. nebula> CREATE EDGE INDEX follow_index on follow();
    4. # 重建索引使其生效。
    5. nebula> REBUILD TAG INDEX name;
    6. +------------+
    7. | New Job Id |
    8. +------------+
    9. | 121 |
    10. +------------+
    11. nebula> REBUILD EDGE INDEX follow_index
    12. +------------+
    13. | New Job Id |
    14. +------------+
    15. | 122 |
    16. +------------+
    17. # 确认重建索引成功。
    18. nebula> SHOW JOB 121;
    19. +----------------+---------------------+------------+-------------------------+-------------------------+
    20. | Job Id(TaskId) | Command(Dest) | Status | Start Time | Stop Time |
    21. +----------------+---------------------+------------+-------------------------+-------------------------+
    22. | 121 | "REBUILD_TAG_INDEX" | "FINISHED" | 2021-05-27T02:18:02.000 | 2021-05-27T02:18:02.000 |
    23. +----------------+---------------------+------------+-------------------------+-------------------------+
    24. | 0 | "storaged1" | "FINISHED" | 2021-05-27T02:18:02.000 | 2021-05-27T02:18:02.000 |
    25. +----------------+---------------------+------------+-------------------------+-------------------------+
    26. | 1 | "storaged0" | "FINISHED" | 2021-05-27T02:18:02.000 | 2021-05-27T02:18:02.000 |
    27. +----------------+---------------------+------------+-------------------------+-------------------------+
    28. | 2 | "storaged2" | "FINISHED" | 2021-05-27T02:18:02.000 | 2021-05-27T02:18:02.000 |
    29. +----------------+---------------------+------------+-------------------------+-------------------------+
    30. nebula> SHOW JOB 122;
    31. +----------------+----------------------+------------+-------------------------+-------------------------+
    32. | Job Id(TaskId) | Command(Dest) | Status | Start Time | Stop Time |
    33. +----------------+----------------------+------------+-------------------------+-------------------------+
    34. | 122 | "REBUILD_EDGE_INDEX" | "FINISHED" | 2021-05-27T02:18:11.000 | 2021-05-27T02:18:11.000 |
    35. +----------------+----------------------+------------+-------------------------+-------------------------+
    36. | 0 | "storaged1" | "FINISHED" | 2021-05-27T02:18:11.000 | 2021-05-27T02:18:21.000 |
    37. +----------------+----------------------+------------+-------------------------+-------------------------+
    38. | 1 | "storaged0" | "FINISHED" | 2021-05-27T02:18:11.000 | 2021-05-27T02:18:21.000 |
    39. +----------------+----------------------+------------+-------------------------+-------------------------+
    40. | 2 | "storaged2" | "FINISHED" | 2021-05-27T02:18:11.000 | 2021-05-27T02:18:21.000 |
    41. +----------------+----------------------+------------+-------------------------+-------------------------+

    匹配点

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

    匹配 Tag

    Note

    匹配 Tag 的前提是 Tag 本身有索引或者 Tag 的某个属性有索引,否则,用户无法基于该 Tag 执行 MATCH 语句。

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

    1. nebula> MATCH (v:player) RETURN v;
    2. +---------------------------------------------------------------+
    3. | v |
    4. +---------------------------------------------------------------+
    5. | ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
    6. +---------------------------------------------------------------+
    7. | ("player106" :player{age: 25, name: "Kyle Anderson"}) |
    8. +---------------------------------------------------------------+
    9. | ("player115" :player{age: 40, name: "Kobe Bryant"}) |
    10. +---------------------------------------------------------------+
    11. ...

    匹配点的属性

    Note

    匹配点的属性的前提是 Tag 本身有对应属性的索引,否则,用户无法执行 MATCH 语句匹配该属性。

    用户可以在Tag的右侧用{<prop_name>: <prop_value>}表示模式中点的属性。

    1. # 使用属性name搜索匹配的点。
    2. nebula> MATCH (v:player{name:"Tim Duncan"}) RETURN v;
    3. +----------------------------------------------------+
    4. | v |
    5. +----------------------------------------------------+
    6. | ("player100" :player{name: "Tim Duncan", age: 42}) |
    7. +----------------------------------------------------+

    使用WHERE子句也可以实现相同的操作:

    1. nebula> MATCH (v:player) WHERE v.name == "Tim Duncan" RETURN v;
    2. +----------------------------------------------------+
    3. | v |
    4. +----------------------------------------------------+
    5. | ("player100" :player{name: "Tim Duncan", age: 42}) |
    6. +----------------------------------------------------+

    在openCypher 9中,=是相等运算符,在nGQL中,==是相等运算符,=是赋值运算符。

    匹配点ID

    用户可以使用点ID去匹配点。id()函数可以检索点的ID。

    1. nebula> MATCH (v) WHERE id(v) == 'player101' RETURN v;
    2. +-----------------------------------------------------+
    3. | v |
    4. +-----------------------------------------------------+
    5. | ("player101" :player{age: 36, name: "Tony Parker"}) |
    6. +-----------------------------------------------------+

    要匹配多个点的ID,可以用WHERE id(v) IN [vid_list]

    1. nebula> MATCH (v:player { name: 'Tim Duncan' })--(v2) \
    2. WHERE id(v2) IN ["player101", "player102"] RETURN v2;
    3. +-----------------------------------------------------------+
    4. | v2 |
    5. +-----------------------------------------------------------+
    6. | ("player101" :player{name: "Tony Parker", age: 36}) |
    7. +-----------------------------------------------------------+
    8. | ("player102" :player{name: "LaMarcus Aldridge", age: 33}) |
    9. +-----------------------------------------------------------+
    10. | ("player101" :player{name: "Tony Parker", age: 36}) |
    11. +-----------------------------------------------------------+

    匹配连接的点

    用户可以使用--符号表示两个方向的边,并匹配这些边连接的点。

    历史版本兼容性

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

    1. nebula> MATCH (v:player{name:"Tim Duncan"})--(v2) \
    2. RETURN v2.name AS Name;
    3. +---------------------+
    4. | Name |
    5. +---------------------+
    6. | "Tony Parker" |
    7. +---------------------+
    8. | "LaMarcus Aldridge" |
    9. +---------------------+
    10. | "Marco Belinelli" |
    11. +---------------------+
    12. | "Danny Green" |
    13. +---------------------+
    14. | "Aron Baynes" |
    15. +---------------------+
    16. ...

    用户可以在--符号上增加<>符号指定边的方向。

    1. # -->表示边从v开始,指向v2。对于点v来说是出边,对于点v2来说是入边。
    2. RETURN v2.name AS Name;
    3. +-----------------+
    4. | Name |
    5. +-----------------+
    6. | "Spurs" |
    7. +-----------------+
    8. | "Tony Parker" |
    9. +-----------------+
    10. | "Manu Ginobili" |
    11. +-----------------+

    如果需要扩展模式,可以增加更多点和边。

    1. nebula> MATCH (v:player{name:"Tim Duncan"})-->(v2)<--(v3) \
    2. RETURN v3.name AS Name;
    3. +---------------------+
    4. | Name |
    5. +---------------------+
    6. | "Tony Parker" |
    7. +---------------------+
    8. +---------------------+
    9. | "Dejounte Murray" |
    10. +---------------------+
    11. | "Tony Parker" |
    12. +---------------------+
    13. | "LaMarcus Aldridge" |
    14. +---------------------+
    15. ...

    如果不需要引用点,可以省略括号中表示点的变量。

    1. nebula> MATCH (v:player{name:"Tim Duncan"})-->()<--(v3) \
    2. RETURN v3.name AS Name;
    3. +---------------------+
    4. | Name |
    5. +---------------------+
    6. | "Tony Parker" |
    7. +---------------------+
    8. | "LaMarcus Aldridge" |
    9. +---------------------+
    10. | "Rudy Gay" |
    11. +---------------------+
    12. | "Danny Green" |
    13. +---------------------+
    14. | "Kyle Anderson" |
    15. +---------------------+
    16. ...

    匹配路径

    连接起来的点和边构成了路径。用户可以使用自定义变量命名路径。

    openCypher兼容性

    在nGQL中,@符号表示边的rank,在openCypher中,没有rank概念。

    匹配边

    除了用----><--表示未命名的边之外,用户还可以在方括号中使用自定义变量命名边。例如-[e]-

    1. nebula> MATCH (v:player{name:"Tim Duncan"})-[e]-(v2) \
    2. RETURN e;
    3. +---------------------------------------------------------------------------+
    4. | e |
    5. +---------------------------------------------------------------------------+
    6. | [:follow "player101"->"player100" @0 {degree: 95}] |
    7. +---------------------------------------------------------------------------+
    8. | [:follow "player102"->"player100" @0 {degree: 75}] |
    9. +---------------------------------------------------------------------------+
    10. | [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
    11. +---------------------------------------------------------------------------+
    12. ...

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

    1. nebula> MATCH ()-[e:follow]-() \
    2. RETURN e;
    3. +-----------------------------------------------------+
    4. | e |
    5. +-----------------------------------------------------+
    6. | [:follow "player113"->"player119" @0 {degree: 99}] |
    7. +-----------------------------------------------------+
    8. | [:follow "player130"->"player149" @0 {degree: 80}] |
    9. +-----------------------------------------------------+
    10. | [:follow "player149"->"player130" @0 {degree: 80}] |
    11. +-----------------------------------------------------+
    12. | [:follow "player136"->"player117" @0 {degree: 90}] |
    13. +-----------------------------------------------------+
    14. | [:follow "player142"->"player117" @0 {degree: 90}] |
    15. +-----------------------------------------------------+
    16. ...

    匹配边的属性

    Note

    匹配边的属性的前提是 Edge type 本身有对应属性的索引,否则,用户无法执行 MATCH 语句匹配该属性。

    用户可以用{<prop_name>: <prop_value>}表示模式中Edge type的属性,例如[e:follow{likeness:95}]

    1. nebula> MATCH (v:player{name:"Tim Duncan"})-[e:follow{degree:95}]->(v2) \
    2. RETURN e;
    3. +--------------------------------------------------------+
    4. | e |
    5. +--------------------------------------------------------+
    6. | [:follow "player100"->"player101" @0 {degree: 95}] |
    7. +--------------------------------------------------------+
    8. | [:follow "player100"->"player125" @0 {degree: 95}] |
    9. +--------------------------------------------------------+

    匹配多个Edge type

    使用|可以匹配多个Edge type,例如[e:follow|:serve]。第一个Edge type前的英文冒号(:)不可省略,后续Edge type前的英文冒号可以省略,例如[e:follow|serve]

    1. nebula> MATCH (v:player{name:"Tim Duncan"})-[e:follow|:serve]->(v2) \
    2. RETURN e;
    3. +---------------------------------------------------------------------------+
    4. | e |
    5. +---------------------------------------------------------------------------+
    6. | [:follow "player100"->"player101" @0 {degree: 95}] |
    7. +---------------------------------------------------------------------------+
    8. | [:follow "player100"->"player125" @0 {degree: 95}] |
    9. +---------------------------------------------------------------------------+
    10. | [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
    11. +---------------------------------------------------------------------------+

    匹配多条边

    用户可以扩展模式,匹配路径中的多条边。

    1. nebula> MATCH (v:player{name:"Tim Duncan"})-[]->(v2)<-[e:serve]-(v3) \
    2. RETURN v2, v3;
    3. +------------------------------------+-----------------------------------------------------------+
    4. | v2 | v3 |
    5. +------------------------------------+-----------------------------------------------------------+
    6. | ("player204" :team{name: "Spurs"}) | ("player101" :player{name: "Tony Parker", age: 36}) |
    7. +------------------------------------+-----------------------------------------------------------+
    8. | ("player204" :team{name: "Spurs"}) | ("player102" :player{name: "LaMarcus Aldridge", age: 33}) |
    9. +------------------------------------+-----------------------------------------------------------+
    10. | ("player204" :team{name: "Spurs"}) | ("player103" :player{age: 32, name: "Rudy Gay"}) |
    11. +------------------------------------+-----------------------------------------------------------+
    12. ...

    匹配定长路径

    用户可以在模式中使用:<edge_type>*<hop>匹配定长路径。hop必须是一个非负整数。

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*2]->(v2) \
    2. RETURN DISTINCT v2 AS Friends;
    3. +-----------------------------------------------------------+
    4. | Friends |
    5. +-----------------------------------------------------------+
    6. | ("player100" :player{name: "Tim Duncan", age: 42}) |
    7. +-----------------------------------------------------------+
    8. | ("player102" :player{name: "LaMarcus Aldridge", age: 33}) |
    9. +-----------------------------------------------------------+
    10. | ("player125" :player{name: "Manu Ginobili", age: 41}) |
    11. +-----------------------------------------------------------+

    如果hop为0,模式会匹配路径上的起始点。

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) -[*0]-> (v2) \
    2. RETURN v2;
    3. +----------------------------------------------------+
    4. | v2 |
    5. +----------------------------------------------------+
    6. | ("player100" :player{age: 42, name: "Tim Duncan"}) |
    7. +----------------------------------------------------+

    匹配变长路径

    openCypher兼容性

    在openCypher中,maxHop是可选项,默认为无穷大。当没有设置时,..可以省略。在nGQL中,maxHop是必选项,而且..不可以省略。

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*1..3]->(v2) \
    2. RETURN v2 AS Friends;
    3. +-----------------------------------------------------------+
    4. | Friends |
    5. +-----------------------------------------------------------+
    6. | ("player100" :player{age: 42, name: "Tim Duncan"}) |
    7. +-----------------------------------------------------------+
    8. | ("player101" :player{age: 36, name: "Tony Parker"}) |
    9. +-----------------------------------------------------------+
    10. | ("player125" :player{age: 41, name: "Manu Ginobili"}) |
    11. +-----------------------------------------------------------+
    12. | ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
    13. +-----------------------------------------------------------+

    用户可以使用DISTINCT关键字聚合重复结果。

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*1..3]->(v2:player) \
    2. RETURN DISTINCT v2 AS Friends, count(v2);
    3. +-----------------------------------------------------------+-----------+
    4. | Friends | count(v2) |
    5. +-----------------------------------------------------------+-----------+
    6. | ("player125" :player{age: 41, name: "Manu Ginobili"}) | 3 |
    7. | ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) | 1 |
    8. +-----------------------------------------------------------+-----------+
    9. | ("player100" :player{age: 42, name: "Tim Duncan"}) | 4 |
    10. +-----------------------------------------------------------+-----------+
    11. | ("player101" :player{age: 36, name: "Tony Parker"}) | 3 |
    12. +-----------------------------------------------------------+-----------+

    如果minHop0,模式会匹配路径上的起始点。与上个示例相比,下面的示例设置为0,因为它是起始点,所以结果集中"Tim Duncan"比上个示例多计算一次。

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*0..3]->(v2:player) \
    2. RETURN DISTINCT v2 AS Friends, count(v2);
    3. +-----------------------------------------------------------+-----------+
    4. | Friends | count(v2) |
    5. +-----------------------------------------------------------+-----------+
    6. | ("player125" :player{age: 41, name: "Manu Ginobili"}) | 3 |
    7. +-----------------------------------------------------------+-----------+
    8. | ("player101" :player{age: 36, name: "Tony Parker"}) | 3 |
    9. +-----------------------------------------------------------+-----------+
    10. | ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) | 1 |
    11. +-----------------------------------------------------------+-----------+
    12. | ("player100" :player{age: 42, name: "Tim Duncan"}) | 5 |
    13. +-----------------------------------------------------------+-----------+

    匹配多个Edge type的变长路径

    用户可以在变长或定长模式中指定多个Edge type。hopminHopmaxHop对所有Edge type都生效。

    检索点或边的信息

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

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) \
    2. RETURN v;
    3. +----------------------------------------------------+
    4. | v |
    5. +----------------------------------------------------+
    6. | ("player100" :player{name: "Tim Duncan", age: 42}) |
    7. +----------------------------------------------------+
    8. nebula> MATCH (v:player{name:"Tim Duncan"})-[e]->(v2) \
    9. RETURN e;
    10. +---------------------------------------------------------------------------+
    11. | e |
    12. +---------------------------------------------------------------------------+
    13. | [:follow "player100"->"player101" @0 {degree: 95}] |
    14. +---------------------------------------------------------------------------+
    15. | [:follow "player100"->"player125" @0 {degree: 95}] |
    16. +---------------------------------------------------------------------------+
    17. | [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
    18. +---------------------------------------------------------------------------+

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

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) \
    2. RETURN id(v);
    3. +-------------+
    4. | id(v) |
    5. +-------------+
    6. | "player100" |
    7. +-------------+

    检索Tag

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

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) \
    2. RETURN labels(v);
    3. +------------+
    4. | labels(v) |
    5. +------------+
    6. | ["player"] |
    7. +------------+

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

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) \
    2. RETURN labels(v)[0];
    3. +--------------+
    4. | labels(v)[0] |
    5. +--------------+
    6. | "player" |
    7. +--------------+

    检索点或边的单个属性

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

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) \
    2. RETURN v.age;
    3. +-------+
    4. | v.age |
    5. +-------+
    6. | 42 |
    7. +-------+

    使用AS设置属性的别名。

    1. nebula> MATCH (v:player{name:"Tim Duncan"}) \
    2. RETURN v.age AS Age;
    3. +-----+
    4. | Age |
    5. +-----+
    6. | 42 |
    7. +-----+

    检索点或边的所有属性

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

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[]->(v2) \
    2. RETURN properties(v2);
    3. +------------------------------------+
    4. | properties(v2) |
    5. +------------------------------------+
    6. | {"name":"Spurs"} |
    7. +------------------------------------+
    8. | {"name":"Tony Parker", "age":36} |
    9. +------------------------------------+
    10. | {"age":41, "name":"Manu Ginobili"} |
    11. +------------------------------------+

    检索Edge type

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

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e]->() \
    2. RETURN DISTINCT type(e);
    3. +----------+
    4. | type(e) |
    5. +----------+
    6. | "follow" |
    7. +----------+
    8. | "serve" |
    9. +----------+

    检索路径

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

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[*3]->() \
    2. RETURN p;
    3. +-------------------------------------------------------------------------------------------------+
    4. | p |
    5. +-------------------------------------------------------------------------------------------------+
    6. | <("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"})> |
    7. +-------------------------------------------------------------------------------------------------+
    8. | <("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"})> |
    9. +-------------------------------------------------------------------------------------------------+
    10. | <("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"})> |
    11. +-------------------------------------------------------------------------------------------------+
    12. ...

    检索路径中的点

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

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[]->(v2) \
    2. RETURN nodes(p);
    3. +---------------------------------------------------------------------------------------------------------------------+
    4. | nodes(p) |
    5. +---------------------------------------------------------------------------------------------------------------------+
    6. | [("player100" :star{} :player{age: 42, name: "Tim Duncan"}), ("player204" :team{name: "Spurs"})] |
    7. +---------------------------------------------------------------------------------------------------------------------+
    8. | [("player100" :star{} :player{age: 42, name: "Tim Duncan"}), ("player101" :player{name: "Tony Parker", age: 36})] |
    9. +---------------------------------------------------------------------------------------------------------------------+
    10. | [("player100" :star{} :player{age: 42, name: "Tim Duncan"}), ("player125" :player{name: "Manu Ginobili", age: 41})] |
    11. +---------------------------------------------------------------------------------------------------------------------+

    检索路径中的边

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

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

    1. nebula> MATCH p=(v:player{name:"Tim Duncan"})-[*..2]->(v2) \
    2. RETURN p AS Paths, length(p) AS Length;
    3. +----------------------------------------------------------------------+--------+
    4. | Paths | Length |
    5. +----------------------------------------------------------------------+--------+
    6. | <("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 |
    7. +----------------------------------------------------------------------+--------+
    8. | <("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 |
    9. +----------------------------------------------------------------------+--------+
    10. | <("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 |
    11. +----------------------------------------------------------------------+--------+
    12. | <("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 |
    13. +----------------------------------------------------------------------+--------+
    14. | <("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 |
    15. +----------------------------------------------------------------------+--------+
    16. | <("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 |
    17. +----------------------------------------------------------------------+--------+
    18. | <("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 |
    19. +----------------------------------------------------------------------+--------+
    20. | <("player100" :player{age: 42, name: "Tim Duncan"})-[:serve@0 {end_year: 2016, start_year: 1997}]->("team204" :team{name: "Spurs"})> | 1 |
    21. +----------------------------------------------------------------------+--------+
    22. | <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})> | 1 |
    23. +----------------------------------------------------------------------+--------+

    Performance

    Nebula Graph 2.5.1 中 MATCH 语句对性能和资源占用进行了初步优化。

    较简单的逻辑可以使用 GO, LOOKUP, | 和 等来替代。