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 NebulaGraph 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 NebulaGraph 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                  |
+----------------+---------------------+------------+----------------------------+----------------------------+
| 121            | "REBUILD_TAG_INDEX" | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 |
| 0              | "storaged1"         | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 |
| 1              | "storaged0"         | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 |
| 2              | "storaged2"         | "FINISHED" | 2021-05-27T02:18:02.000000 | 2021-05-27T02:18:02.000000 |
+----------------+---------------------+------------+----------------------------+----------------------------+

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

Match vertices

Legacy version compatibility

In NebulaGraph versions earlier than 3.0.0, nGQL does not support MATCH (v) RETURN v.

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 NebulaGraph 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 (:).

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 NebulaGraph 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 NebulaGraph 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].

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.

Parameter Description
minHop Optional. It represents the minimum length of the path. minHop must be a non-negative integer. The default value is 1.
maxHop Required. It represents the maximum length of the path. maxHop must be a non-negative integer. It has no default value.

OpenCypher compatibility

In openCypher, maxHop is optional and defaults to infinity. When no bounds are given, .. can be omitted. However, in nGQL, maxHop is required. And .. cannot be omitted.

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

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 NebulaGraph, 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: March 13, 2023
Back to top