Match 子句
MATCH 子句用于在图数据库中搜索模式。它允许你查找符合特定条件的节点、边和路径。
匹配节点
匹配单标签节点
查找具有特定标签的所有节点。此查询返回所有标签为 person 的节点。
MATCH (p:Person) RETURN p;输出:
+-------------------------------------------------------+
| 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} |
+-------------------------------------------------------+匹配具有多个标签的节点
查找具有任意指定标签的节点。此查询返回所有标记为 person 或 software 的节点。
注意:与 Neo4j 不同,NeuG 不支持多标签节点。在 Neo4j 中,(p:Person:Software) 表示同时具有 person 和 software 标签的节点。而在 NeuG 中,此语法表示具有 person 或 software 标签的节点的并集。
MATCH (p:Person:Software) RETURN p;输出:
+-----------------------------------------------------------------------------+
| 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} |
+-----------------------------------------------------------------------------+匹配任意标签的节点
无需指定标签即可匹配节点。NeuG 支持无显式标签的查询,并在编译期间根据已定义的模式约束自动推断未知标签。
MATCH (p) RETURN p;输出:
+-----------------------------------------------------------------------------+
| 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 (p:Person {name: 'marko'}) RETURN p;输出:
+-------------------------------------------------------+
| p |
+=======================================================+
| {_ID: 0, _LABEL: Person, name: marko, age: 29} |
+-------------------------------------------------------+匹配边
匹配具有单一标签的边
MATCH (p:Person)-[k:KNOWS]->(f:Person) RETURN k;输出:
+------------------------------------------------------------------------------------------------------+
| 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 (p:Person)-[k:KNOWS|CREATED]->(f) RETURN k;输出:
+--------------------------------------------------------------------------------------------------------------------------------------+
| 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 (p:Person)-[k]->(f) RETURN k;输出:
+--------------------------------------------------------------------------------------------------------------------------------------+
| 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 (p:Person)-[k:KNOWS {weight: 1.0}]->(f:Person) RETURN k;输出:
+------------------------------------------------------------------------------------------------------+
| k |
+======================================================================================================+
| {_ID: 2, _LABEL: KNOWS, _SRC_LABEL: Person, _DST_LABEL: Person, _SRC_ID: 0, _DST_ID: 2, weight: 1.0} |
+------------------------------------------------------------------------------------------------------+匹配重复路径
NeuG 支持可变长度的重复路径探索,这是图查询中的常见功能。
匹配可变长度的重复路径
查找具有可变跳数的路径。此查询返回所有由 1 条或 2 条边组成的路径。
MATCH (p:Person)-[k*1..2]->(f) RETURN k;匹配带源条件的重复路径
根据源节点的属性指定过滤条件。此查询查找从名称为 ‘marko’ 的节点出发的 1 跳或 2 跳路径。
MATCH (p:Person {name: 'marko'})-[k*1..2]->(f) RETURN k;匹配带有目标条件的重复路径
根据目标节点的属性指定过滤条件。该查询查找终点为名为 ‘josh’ 的节点的路径。
MATCH (p:Person {name: 'marko'})-[k*1..2]->(f {name: 'josh'}) RETURN k;输出:
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| 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} |
+---------------------------------------------------------------------------------------------------------------------------------------------------+匹配带有边条件的重复路径
参考 Kuzu 规范 ,NeuG 还支持在路径中对每条边进行属性过滤。
此查询要求路径中的每条边都满足约束 r.weight < 1.0。
MATCH (p:Person {name: 'marko'})-[k:KNOWS*1..2 (r, _ | WHERE r.weight <= 1.0)]->(f:Person)
RETURN k;匹配 Trail 路径
使用 TRAIL 选项,您可以进一步限制重复路径,确保不重复任何边,从而保证路径扩展迭代能够正常终止,避免陷入无限循环。
MATCH (p:Person {name: 'marko'})-[k:KNOWS* TRAIL 1..2]->(f:Person)
RETURN k;匹配简单路径
使用 ACYCLIC 选项可以进一步限制重复路径,确保不重复访问任何节点,从而保证输出简单路径。
MATCH (p:Person {name: 'marko'})-[k:KNOWS* ACYCLIC 1..2]->(f:Person)
RETURN k;匹配无权最短路径
指定 SHORTEST 选项以输出两个给定节点之间的无权最短路径。
MATCH (p:Person {name: 'marko'})-[k:KNOWS* SHORTEST 1..2]->(f:Person {name: 'josh'})
RETURN k;匹配模式
MATCH 子句支持复杂的模式匹配,能够以多种方式组合节点、边和条件,从而表达复杂的图查询。
以下是各类图查询基准测试中广泛使用的几种经典图查询模式:
- 三角形模式
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(*);- 正方形模式
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(*);- 长路径
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(*);- 团路径
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 子句允许您匹配图中可能存在也可能不存在的模式,对于未匹配的模式部分返回 null。
以下是可选匹配的使用方法:
MATCH (a:Person)-[:KNOWS]->(b:Person)
OPTIONAL MATCH (b:Person)-[:CREATED]->(c:Software)
RETURN a.name, b.name, c.name在上述输出结果中,对于每个 (a, b) 对:
- 如果 b 存在相连的节点 c,则返回所有 (a, b, c) 三元组。例如,对于 (‘marko’, ‘josh’),对应的三元组为 {(‘marko’, ‘josh’, ‘lop’), (‘marko’, ‘josh’, ‘ripple’)}。
- 如果 b 没有相连的节点 c,则为当前的 (a, b) 对保留一行 c=null 的记录。例如,对于 (‘marko’, ‘vadas’),输出的三元组为 {(‘marko’, ‘vadas’, null)}。
这正是 OPTIONAL MATCH 子句的主要目的——即使可选模式未匹配,也能保留主 MATCH 产生的行。