Skip to content

MATCH

The MATCH statement supports searching based on pattern matching.

A MATCH statement defines a search pattern and uses it to match data stored in Nebula Graph and to retrieve them in the form defined in the RETURN clause.

The examples in this topic use the basketballplayer dataset as the sample dataset.

Syntax

The syntax of MATCH is relatively more flexible compared with that of other query statements such as GO or LOOKUP. But generally, it can be summarized as follows.

MATCH <pattern> [<clause_1>] RETURN <output> [<clause_2>];
  • pattern: For the detailed description of patterns, see Patterns. The MATCH statement supports matching one or multiple patterns. Multiple patterns are separated by commas (,). For example: (a)-[]->(b),(c)-[]->(d).
  • clause_1: The WHERE, WITH, UNWIND, and OPTIONAL MATCH clauses are supported, and the MATCH clause can also be used.
  • output: Define the output to be returned. You can rename the output column by using AS.
  • clause_2: The ORDER BY and LIMIT clauses are supported.

Precautions

Legacy version compatibility

Starting from Nebula Graph version 3.0.0, in order to distinguish the properties of different tags, you need to specify a tag name when querying properties. The original statement RETURN variable_name.property_name is changed to RETURN variable_name.<tag_name>.property_name.

Note

Currently the match statement cannot find dangling edges.

  • The MATCH statement retrieves data according to the RETURN clause.
  • The path type of the MATCH statement is trail. That is, only vertices can be repeatedly visited in the graph traversal. Edges cannot be repeatedly visited. For details, see path.
  • In a valid MATCH statement, the VID of a specific vertex must be specified with the id() function in the WHERE clause. There is no need to create an index.
  • When traversing all vertices and edges with MATCH, such as MATCH (v) RETURN v LIMIT N, there is no need to create an index, but you need to use LIMIT to limit the number of output results.
  • When traversing all vertices of the specified Tag or edge of the specified Edge Type, such as MATCH (v:player) RETURN v LIMIT N, there is no need to create an index, but you need to use LIMIT to limit the number of output results.
  • In addition to the foregoing, make sure there is at least one index in the MATCH statement. How to create native indexes, see CREATE INDEX.

Using patterns in MATCH statements

Create indexes

# The following example creates an index on both the name property of the tag player and the edge type follow.
nebula> CREATE TAG INDEX IF NOT EXISTS name ON player(name(20));
nebula> CREATE EDGE INDEX IF NOT EXISTS follow_index on follow();

# The following example rebuilds the index.
nebula> REBUILD TAG INDEX name;
+------------+
| New Job Id |
+------------+
| 121        |
+------------+

nebula> REBUILD EDGE INDEX follow_index;
+------------+
| New Job Id |
+------------+
| 122        |
+------------+


# The following example makes sure the index is rebuilt successfully.
nebula> SHOW JOB 121;
+----------------+---------------------+------------+----------------------------+----------------------------+-------------+
| Job Id(TaskId) | Command(Dest)       | Status     | Start Time                 | Stop Time                  | Error Code  |
+----------------+---------------------+------------+----------------------------+----------------------------+-------------+
| 121            | "REBUILD_TAG_INDEX" | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 | "SUCCEEDED" |
| 0              | "storaged1"         | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 | "SUCCEEDED" |
| 1              | "storaged0"         | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 | "SUCCEEDED" |
| 2              | "storaged2"         | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 | "SUCCEEDED" |
+----------------+---------------------+------------+----------------------------+----------------------------+-------------+

nebula> SHOW JOB 122;
+----------------+----------------------+------------+----------------------------+----------------------------+-------------+
| Job Id(TaskId) | Command(Dest)        | Status     | Start Time                 | Stop Time                  | Error Code  |
+----------------+----------------------+------------+----------------------------+----------------------------+-------------+
| 122            | "REBUILD_EDGE_INDEX" | "FINISHED" | 2021-05-27T02:18:11.000000 | 2021-05-27T02:18:11.000000 | "SUCCEEDED" |
| 0              | "storaged1"          | "FINISHED" | 2021-05-27T02:18:11.000000 | 2021-05-27T02:18:21.000000 | "SUCCEEDED" |
| 1              | "storaged0"          | "FINISHED" | 2021-05-27T02:18:11.000000 | 2021-05-27T02:18:21.000000 | "SUCCEEDED" |
| 2              | "storaged2"          | "FINISHED" | 2021-05-27T02:18:11.000000 | 2021-05-27T02:18:21.000000 | "SUCCEEDED" |
+----------------+----------------------+------------+----------------------------+----------------------------+-------------+

Match vertices

Legacy version compatibility

As of version 3.0.0, nGQL support MATCH (v) RETURN v LIMIT n, there is no need to create an index. But you must use LIMIT to limit the number of output results.

nGQL still does not support MATCH (v) RETURN v.

You can use a user-defined variable in a pair of parentheses to represent a vertex in a pattern. For example: (v).

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"})       |
+-----------------------------------------------------------+

Match tags

Note

In Nebula Graph versions earlier than 3.0.0, the prerequisite for matching a tag is that the tag itself has an index or a certain property of the tag has an index. As of version 3.0.0, there is no need to create an index for matching a tag, but you need to use LIMIT to limit the number of output results.

You can specify a tag with :<tag_name> after the vertex in a pattern.

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"})            |
...

To match vertices with multiple tags, use colons (:).

Note

It is not yet supported to add property conditions when matching vertices with multiple tags.

For example, the statement match (v1:player:team) where v1.player.name=="Tim Duncan" return v1 limit 10; does not work.

nebula> CREATE TAG actor (name string, age int);
nebula> INSERT VERTEX actor(name, age) VALUES "player100":("Tim Duncan", 42);
nebula> MATCH (v:player:actor) \
        RETURN v \
        LIMIT 10;
+----------------------------------------------------------------------------------------+
| v                                                                                      |
+----------------------------------------------------------------------------------------+
| ("player100" :actor{age: 42, name: "Tim Duncan"} :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------------------------------------------+

Match vertex properties

Note

The prerequisite for matching a vertex property is that the tag itself has an index of the corresponding property. Otherwise, you cannot execute the MATCH statement to match the property.

You can specify a vertex property with {<prop_name>: <prop_value>} after the tag in a pattern.

# The following example uses the name property to match a vertex.
nebula> MATCH (v:player{name:"Tim Duncan"}) \
        RETURN v;
+----------------------------------------------------+
| v                                                  |
+----------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------+

The WHERE clause can do the same thing:

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

OpenCypher compatibility

In openCypher 9, = is the equality operator. However, in nGQL, == is the equality operator and = is the assignment operator (as in C++ or Java).

Match VIDs

You can use the VID to match a vertex. The id() function can retrieve the VID of a vertex.

nebula> MATCH (v) \
        WHERE id(v) == 'player101' \
        RETURN v;
+-----------------------------------------------------+
| v                                                   |
+-----------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
+-----------------------------------------------------+

To match multiple VIDs, use WHERE id(v) IN [vid_list].

nebula> MATCH (v:player { name: 'Tim Duncan' })--(v2) \
        WHERE id(v2) IN ["player101", "player102"] \
        RETURN v2;
+-----------------------------------------------------------+
| v2                                                        |
+-----------------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"})       |
| ("player101" :player{age: 36, name: "Tony Parker"})       |
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
+-----------------------------------------------------------+

Match connected vertices

You can use the -- symbol to represent edges of both directions and match vertices connected by these edges.

Legacy version compatibility

In nGQL 1.x, the -- symbol is used for inline comments. Starting from nGQL 2.x, the -- symbol represents an incoming or outgoing edge.

nebula> MATCH (v:player{name:"Tim Duncan"})--(v2) \
        RETURN v2.player.name AS Name;
+---------------------+
| Name                |
+---------------------+
| "Manu Ginobili"     |
| "Manu Ginobili"     |
| "Tiago Splitter"    |
...

You can add a > or < to the -- symbol to specify the direction of an edge.

In the following example, --> represents an edge that starts from v and points to v2. To v, this is an outgoing edge, and to v2 this is an incoming edge.

nebula> MATCH (v:player{name:"Tim Duncan"})-->(v2:player) \
        RETURN v2.player.name AS Name;
+-----------------+
| Name            |
+-----------------+
| "Manu Ginobili" |
| "Tony Parker"   |
+-----------------+

To query the properties of the target vertices, use the CASE expression.

nebula> MATCH (v:player{name:"Tim Duncan"})--(v2) \
        RETURN \
        CASE WHEN v2.team.name IS NOT NULL \
        THEN v2.team.name  \
        WHEN v2.player.name IS NOT NULL \
        THEN v2.player.name END AS Name;
+---------------------+
| Name                |
+---------------------+
| "Manu Ginobili"     |
| "Manu Ginobili"     |
| "Spurs"             |
| "Dejounte Murray"   |
...

To extend the pattern, you can add more vertices and edges.

nebula> MATCH (v:player{name:"Tim Duncan"})-->(v2)<--(v3) \
        RETURN v3.player.name AS Name;
+---------------------+
| Name                |
+---------------------+
| "Dejounte Murray"   |
| "LaMarcus Aldridge" |
| "Marco Belinelli"   |
...

If you do not need to refer to a vertex, you can omit the variable representing it in the parentheses.

nebula> MATCH (v:player{name:"Tim Duncan"})-->()<--(v3) \
        RETURN v3.player.name AS Name;
+---------------------+
| Name                |
+---------------------+
| "Dejounte Murray"   |
| "LaMarcus Aldridge" |
| "Marco Belinelli"   |
...

Match paths

Connected vertices and edges form a path. You can use a user-defined variable to name a path as follows.

nebula> MATCH p=(v:player{name:"Tim Duncan"})-->(v2) \
        RETURN p;
+--------------------------------------------------------------------------------------------------------------------------------------+
| p                                                                                                                                    |
+--------------------------------------------------------------------------------------------------------------------------------------+
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:serve@0 {end_year: 2016, start_year: 1997}]->("team204" :team{name: "Spurs"})> |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})>   |
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player125" :player{age: 41, name: "Manu Ginobili"})> |
+--------------------------------------------------------------------------------------------------------------------------------------+

OpenCypher compatibility

In nGQL, the @ symbol represents the rank of an edge, but openCypher has no such concept.

Match edges

OpenCypher compatibility

In Nebula Graph versions earlier than 3.0.0, the prerequisite for matching a edge is that the edge itself has an index or a certain property of the edge has an index. As of version 3.0.0, there is no need to create an index for matching a edge, but you need to use LIMIT to limit the number of output results and you must specify the direction of the edge.

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}] |
+----------------------------------------------------+

Match edge types

Just like vertices, you can specify edge types with :<edge_type> in a pattern. For example: -[e:follow]-.

OpenCypher compatibility

In Nebula Graph versions earlier than 3.0.0, the prerequisite for matching a edge type is that the edge type itself has an index or a certain property of the edge type has an index. As of version 3.0.0, there is no need to create an index for matching a edge type, but you need to use LIMIT to limit the number of output results and you must specify the direction of the edge.

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}] |
+----------------------------------------------------+

# Before you execute the following statement, you must create an index on the edge type itself or a certain property of the edge type
nebula> MATCH ()-[e:follow]-() \
        RETURN e;
+-----------------------------------------------------+
| e                                                   |
+-----------------------------------------------------+
| [:follow "player126"->"player116" @0 {degree: 13}]  |
| [:follow "player142"->"player117" @0 {degree: 90}]  |
| [:follow "player136"->"player117" @0 {degree: 90}]  |
| [:follow "player136"->"player148" @0 {degree: 85}]  |
···

Match edge type properties

Note

The prerequisite for matching an edge type property is that the edge type itself has an index of the corresponding property. Otherwise, you cannot execute the MATCH statement to match the property.

You can specify edge type properties with {<prop_name>: <prop_value>} in a pattern. For example: [e:follow{likeness:95}].

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

Match multiple edge types

The | symbol can help matching multiple edge types. For example: [e:follow|:serve]. The English colon (:) before the first edge type cannot be omitted, but the English colon before the subsequent edge type can be omitted, such as [e:follow|serve].

Note

It is not yet supported to add property conditions when matching data with multiple tags and multiple edge types at the same time.

For example, the statement MATCH (v)-[e:follow|serve]->(v2) where v.player.name=="Tim Duncan" RETURN e limit 10; does not work. (v) represents a vertex with all its tags.

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

Match multiple edges

You can extend a pattern to match multiple edges in a path.

nebula> MATCH (v:player{name:"Tim Duncan"})-[]->(v2)<-[e:serve]-(v3) \
        RETURN v2, v3;
+----------------------------------+-----------------------------------------------------------+
| v2                               | v3                                                        |
+----------------------------------+-----------------------------------------------------------+
| ("team204" :team{name: "Spurs"}) | ("player104" :player{age: 32, name: "Marco Belinelli"})   |
| ("team204" :team{name: "Spurs"}) | ("player101" :player{age: 36, name: "Tony Parker"})       |
| ("team204" :team{name: "Spurs"}) | ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
...

Match fixed-length paths

You can use the :<edge_type>*<hop> pattern to match a fixed-length path. hop must be a non-negative integer.

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

If hop is 0, the pattern will match the source vertex of the path.

nebula> MATCH (v:player{name:"Tim Duncan"}) -[*0]-> (v2) \
        RETURN v2;
+----------------------------------------------------+
| v2                                                 |
+----------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------+

Note

When you conditionally filter on multi-hop edges, such as -[e:follow*2]->, note that the e is a list of edges instead of a single edge.

For example, the following statement is correct from the syntax point of view which may not get your expected query result, because the e is a list without the .degree property.

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*2]->(v2) \
        WHERE e.degree > 1 \
        RETURN DISTINCT v2 AS Friends;

The correct statement is as follows:

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*2]->(v2) \
        WHERE ALL(e_ in e WHERE e_.degree > 0) \
        RETURN DISTINCT v2 AS Friends;

Further, the following statement is for filtering the properties of the first-hop edge in multi-hop edges:

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*2]->(v2) \
        WHERE e[0].degree > 98 \
        RETURN DISTINCT v2 AS Friends;

Match variable-length paths

You can use the :<edge_type>*[minHop..maxHop] pattern to match variable-length paths.minHop and maxHop are optional and default to 1 and infinity respectively.

Note

When setting bounds, at least one of minHop and maxHop exists.

Caution

If maxHop is not set, it may cause the Graph service to OOM, execute this command with caution.

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*]->(v2) \
        RETURN v2 AS Friends;
+-----------------------------------------------------------+
| Friends                                                   |
+-----------------------------------------------------------+
| ("player125" :player{age: 41, name: "Manu Ginobili"})     |
| ("player101" :player{age: 36, name: "Tony Parker"})       |
...

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*1..3]->(v2) \
        RETURN v2 AS Friends;
+-----------------------------------------------------------+
| Friends                                                   |
+-----------------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"})       |
| ("player125" :player{age: 41, name: "Manu Ginobili"})     |
| ("player100" :player{age: 42, name: "Tim Duncan"})        |
...

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow*1..]->(v2) \
        RETURN v2 AS Friends;
+-----------------------------------------------------------+
| Friends                                                   |
+-----------------------------------------------------------+
| ("player125" :player{age: 41, name: "Manu Ginobili"})     |
| ("player101" :player{age: 36, name: "Tony Parker"})       |
| ("player100" :player{age: 42, name: "Tim Duncan"})        |
...

You can use the DISTINCT keyword to aggregate duplicate results.

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

If minHop is 0, the pattern will match the source vertex of the path. Compared to the preceding statement, the following example uses 0 as the minHop. So in the following result set, "Tim Duncan" is counted one more time than it is in the preceding result set because it is the source vertex.

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

Match variable-length paths with multiple edge types

You can specify multiple edge types in a fixed-length or variable-length pattern. In this case, hop, minHop, and maxHop take effect on all edge types.

nebula> MATCH p=(v:player{name:"Tim Duncan"})-[e:follow|serve*2]->(v2) \
        RETURN DISTINCT v2;
+-----------------------------------------------------------+
| v2                                                        |
+-----------------------------------------------------------+
| ("team204" :team{name: "Spurs"})                          |
| ("player100" :player{age: 42, name: "Tim Duncan"})        |
| ("team215" :team{name: "Hornets"})                        |
| ("player125" :player{age: 41, name: "Manu Ginobili"})     |
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
+-----------------------------------------------------------+

Match multiple patterns

You can separate multiple patterns with commas (,).

nebula> MATCH (v1:player{name:"Tim Duncan"}), (v2:team{name:"Spurs"}) \
        RETURN v1,v2;
+----------------------------------------------------+----------------------------------+
| v1                                                 | v2                               |
+----------------------------------------------------+----------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) | ("team204" :team{name: "Spurs"}) |
+----------------------------------------------------+----------------------------------+

Retrieve with multiple match

Multiple MATCH can be used when different patterns have different filtering criteria and return the rows that exactly match the pattern.

nebula> MATCH (m)-[]->(n) WHERE id(m)=="player100" \
        MATCH (n)-[]->(l) WHERE id(n)=="player125" \
        RETURN id(m),id(n),id(l);
+-------------+-------------+-------------+
| id(m)       | id(n)       | id(l)       |
+-------------+-------------+-------------+
| "player100" | "player125" | "team204"   |
| "player100" | "player125" | "player100" |
+-------------+-------------+-------------+

Retrieve with optional match

See OPTIONAL MATCH.

Performance

In Nebula Graph, the performance and resource usage of the MATCH statement have been optimized. But we still recommend to use GO, LOOKUP, |, and FETCH instead of MATCH when high performance is required.


Last update: August 12, 2022