Skip to Content

Match Clause

The MATCH clause is used to search for patterns in the graph database. It allows you to find nodes, edges, and paths that match specific criteria.

Match Nodes

Match Nodes with Single Label

Find all nodes with a specific label. This query returns all nodes labeled as person.

MATCH (p:person) RETURN p;

output:

+-------------------------------------------------------+ | p | +=======================================================+ | {_ID: 0, _LABEL: person, name: marko, age: 29} | +-------------------------------------------------------+ | {_ID: 1, _LABEL: person, name: vadas, age: 27} | +-------------------------------------------------------+ | {_ID: 2, _LABEL: person, name: josh, age: 32} | +-------------------------------------------------------+ | {_ID: 3, _LABEL: person, name: peter, age: 35} | +-------------------------------------------------------+

Match Nodes with Multiple Labels

Find nodes with any of the specified labels. This query returns all nodes labeled as either person or software.

Note: Unlike Neo4j, NeuG does not support multi-label nodes. In Neo4j, (p:person:software) represents nodes that have both person and software labels simultaneously. In NeuG, this syntax represents a union of nodes with either person or software labels.

MATCH (p:person:software) RETURN p;

output:

+-----------------------------------------------------------------------------+ | p | +=============================================================================+ | {_ID: 0, _LABEL: person, name: marko, age: 29} | +-----------------------------------------------------------------------------+ | {_ID: 1, _LABEL: person, name: vadas, age: 27} | +-----------------------------------------------------------------------------+ | {_ID: 2, _LABEL: person, name: josh, age: 32} | +-----------------------------------------------------------------------------+ | {_ID: 3, _LABEL: person, name: peter, age: 35} | +-----------------------------------------------------------------------------+ | {_ID: 72057594037927936, _LABEL: software, name: lop, lang: java} | +-----------------------------------------------------------------------------+ | {_ID: 72057594037927937, _LABEL: software, name: ripple, lang: java} | +-----------------------------------------------------------------------------+

Match Nodes with Any Label

Match nodes without specifying a label. NeuG supports queries without explicit labels and infers unknown labels automatically during compilation based on defined schema constraints.

MATCH (p) RETURN p;

output:

+-----------------------------------------------------------------------------+ | p | +=============================================================================+ | {_ID: 0, _LABEL: person, name: marko, age: 29} | +-----------------------------------------------------------------------------+ | {_ID: 1, _LABEL: person, name: vadas, age: 27} | +-----------------------------------------------------------------------------+ | {_ID: 2, _LABEL: person, name: josh, age: 32} | +-----------------------------------------------------------------------------+ | {_ID: 3, _LABEL: person, name: peter, age: 35} | +-----------------------------------------------------------------------------+ | {_ID: 72057594037927936, _LABEL: software, name: lop, lang: java} | +-----------------------------------------------------------------------------+ | {_ID: 72057594037927937, _LABEL: software, name: ripple, lang: java} | +-----------------------------------------------------------------------------+

Match Nodes with Conditions

In addition to label constraints, you can specify property-based filtering conditions.

MATCH (p:person {name: 'marko'}) RETURN p;

output:

+-------------------------------------------------------+ | p | +=======================================================+ | {_ID: 0, _LABEL: person, name: marko, age: 29} | +-------------------------------------------------------+

Match Edges

Match Edges with Single Label

MATCH (p:person)-[k:knows]->(f:person) RETURN k;

output:

+------------------------------------------------------------------------------------------------------+ | k | +======================================================================================================+ | {_ID: 1, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 1, weight: 0.5} | +------------------------------------------------------------------------------------------------------+ | {_ID: 2, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 2, weight: 1.0} | +------------------------------------------------------------------------------------------------------+

Match Edges with Multiple Labels

MATCH (p:person)-[k:knows|created]->(f) RETURN k;

output:

+--------------------------------------------------------------------------------------------------------------------------------------+ | k | +======================================================================================================================================+ | {_ID: 1, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 1, weight: 0.5} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 2, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 2, weight: 1.0} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103806595072, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 0, _DST_ID: 72057594037927936, weight: 0.4} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103808692224, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 2, _DST_ID: 72057594037927936, weight: 0.4} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103808692225, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 2, _DST_ID: 72057594037927937, weight: 1.0} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103809740800, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 3, _DST_ID: 72057594037927936, weight: 0.2} | +--------------------------------------------------------------------------------------------------------------------------------------+

Match Edges with Any Label

MATCH (p:person)-[k]->(f) RETURN k;

output:

+--------------------------------------------------------------------------------------------------------------------------------------+ | k | +======================================================================================================================================+ | {_ID: 1, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 1, weight: 0.5} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 2, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 2, weight: 1.0} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103806595072, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 0, _DST_ID: 72057594037927936, weight: 0.4} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103808692224, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 2, _DST_ID: 72057594037927936, weight: 0.4} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103808692225, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 2, _DST_ID: 72057594037927937, weight: 1.0} | +--------------------------------------------------------------------------------------------------------------------------------------+ | {_ID: 1103809740800, _LABEL: created, _SRC_LABEL: person, _DST_LABEL: software, _SRC_ID: 3, _DST_ID: 72057594037927936, weight: 0.2} | +--------------------------------------------------------------------------------------------------------------------------------------+

Match Edges with Conditions

Filter edges based on their properties.

MATCH (p:person)-[k:knows {weight: 1.0}]->(f:person) RETURN k;

output:

+------------------------------------------------------------------------------------------------------+ | k | +======================================================================================================+ | {_ID: 2, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 0, _DST_ID: 2, weight: 1.0} | +------------------------------------------------------------------------------------------------------+

Match Repeated Paths

NeuG supports variable-length repeated path exploration, which is a common feature in graph queries.

Match Repeated Path with Variable Length

Find paths with a variable number of hops. This query returns all paths consisting of 1 or 2 edges.

MATCH (p:person)-[k*1..2]->(f) RETURN k;

Match Repeated Paths with Source Conditions

Specify filtering conditions based on the source node’s properties. This query finds 1-hop or 2-hop paths starting from the node with name ‘marko’.

MATCH (p:person {name: 'marko'})-[k*1..2]->(f) RETURN k;

Match Repeated Paths with Target Conditions

Specify filtering conditions based on the target node’s properties. This query finds paths ending at the node with name ‘josh’.

MATCH (p:person {name: 'marko'})-[k*1..2]->(f {name: 'josh'}) RETURN k;

output:

+---------------------------------------------------------------------------------------------------------------------------------------------------+ | k | +===================================================================================================================================================+ | {_ID: 2, _LABEL: person}, {_ID: 2097152, _LABEL: knows, _SRC_LABEL: person, _DST_LABEL: person, _SRC_ID: 2, _DST_ID: 0}, {_ID: 0, _LABEL: person} | +---------------------------------------------------------------------------------------------------------------------------------------------------+

Match Repeated Paths with Edge Conditions

Reference Kuzu’s specification , NeuG also supports property filtering on each edge during the path.

This query requires each edge in the path to satisfy the constraint r.weight < 1.0.

MATCH (p:person {name: 'marko'})-[k:knows*1..2 (r, _ | WHERE r.weight <= 1.0)]->(f:person) Return k;

Match Trail Path

Using the TRAIL option, you can further restrict repeated paths to ensure no edges are repeated, guaranteeing that path expansion iterations terminate without infinite loops.

MATCH (p:person {name: 'marko'})-[k:knows* TRAIL 1..2]->(f:person) Return k;

Match Simple Path

Using the SIMPLE option, you can further restrict repeated paths to ensure no nodes are repeated, guaranteeing output of simple paths.

MATCH (p:person {name: 'marko'})-[k:knows* ACYCLIC 1..2]->(f:person) Return k;

Match Unweighted Shortest Path

Specify the SHORTEST option to output the unweighted shortest path between two given nodes.

MATCH (p:person {name: 'marko'})-[k:knows* SHORTEST 1..2]->(f:person {name: 'josh'}) RETURN k;

Match Patterns

The MATCH clause supports complex pattern matching that combines nodes, edges, and conditions in various ways to express sophisticated graph queries.

Below are some classic graph query patterns that are widely used in various graph query benchmarks:

  • Triangle Pattern
Match (a:person)-[:created]->(b:software), (c:person)-[:created]->(b:software), (a:person)-[:knows]->(c:person) Where a.name <> b.name AND b.name <> c.name Return count(*);
  • Square Pattern
Match (a:person)-[:created]->(b:software), (c:person)-[:created]->(b:software), (a:person)-[:knows]->(d:person), (c:person)<-[:knows]-(d:person) Where a.name <> b.name AND b.name <> c.name AND c.name <> d.name Return count(*);
  • Long Path
Match (a:person)-[:knows]->(b:person), (b:person)-[:knows]->(c:person), (c:person)-[:created]->(d:software), (d:software)<-[:created]-(e:person), (e:person)-[:knows]->(f:person) Where a.name <> b.name AND b.name <> c.name AND c.name <> d.name AND d.name <> e.name Return count(*);
  • Clique Path
Match (a:person)-[:created]->(b:software), (c:person)-[:created]->(b:software), (a:person)-[:knows]->(d:person), (c:person)<-[:knows]-(d:person), (a:person)-[:knows]->(c:person), (d:person)-[:created]->(b:software) Where a.name <> b.name AND b.name <> c.name AND c.name <> d.name Return count(*);

Optional Match

The OPTIONAL MATCH clause allows you to match patterns that may or may not exist in the graph, returning null for parts of the pattern that don’t match.

Here’s how to use Optional Match:

MATCH (a:person)-[:knows]->(b:person) OPTIONAL MATCH (b:person)-[:created]->(c:software) RETURN a.name, b.name, c.name

In the output results above, for each (a, b) pair:

  • If b has connected nodes c, all (a, b, c) triples are returned. For example, for (‘marko’, ‘josh’), the corresponding triples are {(‘marko’, ‘josh’, ‘lop’), (‘marko’, ‘josh’, ‘ripple’)}.
  • If b has no connected nodes c, a row with c=null is preserved for the current (a,b) pair. For example, for (‘marko’, ‘vadas’), the output triple is {(‘marko’, ‘vadas’, null)}.

This is the main purpose of the OPTIONAL MATCH clause - to preserve rows from the main MATCH even when the optional pattern doesn’t match.