本文档将从以下几个方面比较 openCypher 和 Spanner Graph:
- 术语
- 数据模型
- 架构
- 查询
- Mutation
本文档假定您熟悉 openCypher v9。
准备工作
使用 Google Cloud 控制台设置和查询 Spanner Graph。
术语
| openCypher | Spanner Graph |
|---|---|
| 节点 | 节点 |
| 关系 | 边缘 |
| 节点标签 | 节点标签 |
| 关系类型 | 边缘标签 |
| 子句 | Spanner Graph 使用术语 statement 表示完整的执行单元,使用 clause 表示语句的修饰符。例如, MATCH 是一个语句,而 WHERE 是一个子句。 |
| 关系唯一性 openCypher 不会在单次匹配中返回包含重复边缘的结果。 | TRAIL 路径如果希望在 Spanner Graph 中实现唯一性,请使用 TRAIL 模式在单个匹配中返回唯一边缘。 |
标准合规性
Spanner Graph 采用 ISO Graph Query Language (GQL) 和 SQL/Property Graph Queries (SQL/PGQ) 标准。
数据模型
Spanner Graph 和 openCypher 都采用属性图表数据模型,但存在一些差异。
| openCypher | Spanner Graph |
|---|---|
| 每种关系都有且只有一种关系类型。 | 节点和边都有一个或多个标签。 |
架构
| openCypher | Spanner Graph |
|---|---|
| 图表没有预定义架构。 | 必须使用 CREATE PROPERTY GRAPH 语句明确定义图架构。标签在架构中静态定义。如需更新标签,您需要更新架构。 如需了解详情,请参阅创建、更新或删除 Spanner Graph 架构。 |
查询
Spanner Graph 查询功能与 openCypher 的查询功能类似。本部分介绍了 Spanner Graph 与 openCypher 之间的区别。
指定图表
在 openCypher 中,有一个默认图,查询会在默认图上运行。在 Spanner Graph 中,您可以定义多个图,并且查询必须以 GRAPH 子句开头,以指定要查询的图。例如:
GRAPH FinGraph MATCH (p:Person) RETURN p.name; 如需了解详情,请参阅图表查询语法。
图表模式匹配
Spanner Graph 支持与 openCypher 类似的图表模式匹配功能。以下各部分介绍了这些区别。
关系唯一性和 TRAIL 模式
openCypher 不会在单个匹配中返回重复边缘的结果;这在 openCypher 中称为“关系唯一性”。在 Spanner Graph 中,重复边缘默认会返回。如果需要唯一性,请使用 TRAIL 模式,以确保单个匹配项中不存在重复边缘。如需了解 TRAIL 和其他不同路径模式的详细语义,请参阅路径模式。
以下示例展示了查询结果如何随 TRAIL 模式而变化:
- openCypher 和 Spanner Graph
TRAIL模式查询会返回空结果,因为唯一可能的路径是重复t1两次。 - 默认情况下,Spanner Graph 查询会返回有效路径。
| openCypher | Spanner Graph(TRAIL 模式) | Spanner Graph(默认模式) | ||||
|---|---|---|---|---|---|---|
MATCH (src:Account)-[t1:Transfers]-> (dst:Account)-[t2:Transfers]-> (src)-[t1]->(dst) WHERE src.id = 16 RETURN src.id AS src_id, dst.id AS dst_id; | GRAPH FinGraph MATCH TRAIL (src:Account)-[t1:Transfers]-> (dst:Account)-[t2:Transfers]-> (src)-[t1]->(dst) WHERE src.id = 16 RETURN src.id AS src_id, dst.id AS dst_id; | GRAPH FinGraph MATCH (src:Account)-[t1:Transfers]-> (dst:Account)-[t2:Transfers]-> (src)-[t1]-> (dst) WHERE src.id = 16 RETURN src.id AS src_id, dst.id AS dst_id; | ||||
| 空结果。 | 空结果。 | 结果:
|
以查询结果的形式返回图表元素
| openCypher | Spanner Graph |
|---|---|
MATCH (account:Account) WHERE account.id = 16 RETURN account; | GRAPH FinGraph MATCH (account:Account) WHERE account.id = 16 RETURN TO_JSON(account) AS account; |
在 Spanner Graph 中,查询结果不会返回图表元素。使用 TO_JSON 函数以 JSON 格式返回图表元素。
长度可变的模式匹配和模式量化
openCypher 中长度可变的模式匹配在 Spanner Graph 中称为路径量化。路径量化使用不同的语法,如以下示例所示。如需了解详情,请参阅量化路径模式。
| openCypher | Spanner Graph |
|---|---|
MATCH (src:Account)-[:Transfers*1..2]->(dst:Account) WHERE src.id = 16 RETURN dst.id ORDER BY dst.id; | GRAPH FinGraph MATCH (src:Account)-[:Transfers]->{1,2}(dst:Account) WHERE src.id = 16 RETURN dst.id ORDER BY dst.id; |
长度可变的模式:元素列表
借助 Spanner Graph,您可以直接访问路径量化中使用的变量。在以下示例中,Spanner Graph 中的 e 与 openCypher 中的 edges(p) 相同。
| openCypher | Spanner Graph |
|---|---|
MATCH p=(src:Account)-[:Transfers*1..3]->(dst:Account) WHERE src.id = 16 RETURN edges(p); | GRAPH FinGraph MATCH (src:Account) -[e:Transfers]->{1,3} (dst:Account) WHERE src.id = 16 RETURN TO_JSON(e) AS e; |
最短路径
openCypher 有两个内置函数用于查找节点之间的最短路径:shortestPath 和 allShortestPath。
shortestPath用于查找节点之间的单个最短路径。allShortestPath用于查找节点之间的所有最短路径。可以存在多个长度相同的路径。
Spanner Graph 使用不同的语法来查找节点之间的单个最短路径:ANY SHORTEST(对应于 shortestPath.)。Spanner Graph 不支持 allShortestPath 函数。
| openCypher | Spanner Graph |
|---|---|
MATCH (src:Account {id: 7}), (dst:Account {id: 20}), p = shortestPath((src)-[*1..10]->(dst)) RETURN length(p) AS path_length; | GRAPH FinGraph MATCH ANY SHORTEST (src:Account {id: 7})-[e:Transfers]->{1, 3} (dst:Account {id: 20}) RETURN ARRAY_LENGTH(e) AS path_length; |
语句和子句
下表列出了 openCypher 子句,并指明它们是否在 Spanner Graph 中受支持。
| openCypher | Spanner Graph | |
|---|---|---|
MATCH | 支持。如需了解详情,请参阅图形模式匹配。 | |
OPTIONAL MATCH | 支持。如需了解详情,请参阅图形模式匹配。 | |
RETURN / WITH | 支持。如需了解详情,请参阅 RETURN 语句和 WITH 语句。Spanner Graph 需要为复杂表达式显式设置别名。 | |
支持。 | GRAPH FinGraph MATCH (p:Person) RETURN EXTRACT(YEAR FROM p.birthday) AS birthYear; | |
不支持。 | GRAPH FinGraph MATCH (p:Person) RETURN EXTRACT(YEAR FROM p.birthday); -- No aliasing | |
WHERE | 支持。如需了解详情,请参阅 图表模式的定义。 | |
ORDER BY | 支持。如需了解详情,请参阅 ORDER BY 语句。 | |
SKIP / LIMIT | 支持。如需了解详情,请参阅 SKIP 语句和 LIMIT 语句。Spanner Graph 需要偏移量和上限的常量表达式。 | |
支持。 | GRAPH FinGraph MATCH (n:Account) RETURN n.id SKIP @offsetParameter LIMIT 3; | |
不支持。 | GRAPH FinGraph MATCH (n:Account) RETURN n.id LIMIT VALUE { MATCH (m:Person) RETURN COUNT(*) AS count } AS count; -- Not a constant expression | |
UNION | 支持。如需了解详情,请参阅复合图查询。 | |
UNION ALL | 支持。如需了解详情,请参阅复合图查询。 | |
UNWIND | 受 FOR 语句支持。 | |
GRAPH FinGraph LET arr = [1, 2, 3] FOR num IN arr RETURN num; | ||
MANDATORY MATCH | 不受支持。 | |
CALL[YIELD...] | 不受支持。 | |
CREATE、DELETE、SET、REMOVE、MERGE | 如需了解详情,请参阅变更部分,以及在 Spanner Graph 中插入、更新或删除数据。 | |
数据类型
Spanner Graph 支持所有 GoogleSQL 数据类型。如需了解详情,请参阅 GoogleSQL 中的数据类型。
以下各部分将比较 openCypher 数据类型与 Spanner Graph 数据类型。
结构类型
| openCypher | Spanner Graph |
|---|---|
| 节点 | 节点 |
| Edge | Edge |
| 路径 | 路径 |
属性类型
| openCypher | Spanner Graph |
|---|---|
INT | INT64 |
FLOAT | FLOAT64 |
STRING | STRING |
BOOLEAN | BOOL |
LIST 简单类型的同构列表。 例如, INT 列表、STRING 列表。您不能在单个列表中混用 INT 和 STRING。 | ARRAY |
复合类型
| openCypher | Spanner Graph |
|---|---|
LIST | ARRAY 或 JSON |
MAP | STRUCT 或 JSON |
Spanner Graph 不支持不同类型的异构列表或动态键列表和异构元素值类型的映射。请在这些用例中使用 JSON 文件。
类型强制转换
| openCypher | Spanner Graph |
|---|---|
INT -> FLOAT | 受支持。 |
如需详细了解类型转换规则,请参阅 GoogleSQL 中的转换规则。
函数和表达式
除了图表函数和表达式之外,Spanner Graph 还支持所有 GoogleSQL 内置函数和表达式。
本部分列出了 openCypher 函数和表达式及其在 Spanner Graph 中的等效项。
结构类型函数和表达式
| 类型 | openCypher 函数或表达式 | Spanner Graph 函数或表达式 | |
|---|---|---|---|
节点和边缘 | exists(n.prop) | PROPERTY_EXISTS(n, prop) | |
id(返回整数) | 不受支持。 | ||
properties | TO_JSON | ||
keys(属性类型名称,不是属性值) | PROPERTY_NAMES | ||
labels | LABELS | ||
| Edge | endNode | 不受支持。 | |
startNode | 不受支持。 | ||
type | LABELS | ||
| 路径 | length | 不受支持。 | |
nodes | 不受支持。 | ||
relationships | 不受支持。 | ||
| 节点和边缘 | . | . | |
[] | 不受支持。 | ||
| 表达式形式的模式 | size(pattern) | 不受支持。使用子查询,如下所示
|
属性类型函数和表达式
| 类型 | openCypher 函数或表达式 | Spanner Graph 函数或表达式 | |
|---|---|---|---|
| 标量 | coalesce | COALESCE | |
head | ARRAY_FIRST | ||
last | ARRAY_LAST | ||
size(list) | ARRAY_LENGTH | ||
size(string) | LENGTH | ||
timestamp | UNIX_MILLIS(CURRENT_TIMESTAMP()) | ||
toBoolean/toFloat/toInteger | CAST(expr AS type) | ||
| 汇总 | avg | AVG | |
collect | ARRAY_AGG | ||
count | COUNT | ||
max | MAX | ||
min | MIN | ||
percentileCont | PERCENTILE_CONT | ||
percentileDisc | PERCENTILE_DISC | ||
stDev | STDDEV | ||
stDevP | 不受支持。 | ||
sum | SUM | ||
| 列表 | range | GENERATE_ARRAY | |
reverse | ARRAY_REVERSE | ||
tail | Spanner Graph 不支持 tail。请改用 ARRAY_SLICE 和 ARRAY_LENGTH。 | ||
| 数学 | abs | ABS | |
ceil | CEIL | ||
floor | FLOOR | ||
rand | RAND | ||
round | ROUND | ||
sign | SIGN | ||
e | EXP(1) | ||
exp | EXP | ||
log | LOG | ||
log10 | LOG10 | ||
sqrt | SQRT | ||
acos | ACOS | ||
asin | ASIN | ||
atan | ATAN | ||
atan2 | ATAN2 | ||
cos | COS | ||
cot | COT | ||
degrees | r * 90 / ASIN(1) | ||
pi | ACOS(-1) | ||
radians | d * ASIN(1) / 90 | ||
sin | SIN | ||
tan | TAN | ||
| 字符串 | left | LEFT | |
ltrim | LTRIM | ||
replace | REPLACE | ||
reverse | REVERSE | ||
right | RIGHT | ||
rtrim | RTRIM | ||
split | SPLIT | ||
substring | SUBSTR | ||
tolower | LOWER | ||
tostring | CAST(expr AS STRING) | ||
toupper | UPPER | ||
trim | TRIM | ||
| DISTINCT | DISTINCT | DISTINCT | |
| 数学 | + | + | |
- | - | ||
* | * | ||
/ | / | ||
% | MOD | ||
^ | POW | ||
| 比较 | = | = | |
<> | <> | ||
< | < | ||
> | > | ||
<= | <= | ||
>= | >= | ||
IS [NOT] NULL | IS [NOT] NULL | ||
比较链
| Spanner Graph 不支持比较链。这等同于与 AND 联合的比较。例如:
| ||
| 布尔值 | AND | AND | |
OR | OR | ||
XOR | Spanner Graph 不支持 XOR。使用 <> 编写查询。例如:
| ||
NOT | NOT | ||
| 字符串 | STARTS WITH | STARTS_WITH | |
ENDS WITH | ENDS_WITH | ||
CONTAINS | REGEXP_CONTAINS | ||
+ | CONCAT | ||
| 列表 | + | ARRAY_CONCAT | |
IN | ARRAY_INCLUDES | ||
[] | [] |
其他表达式
| openCypher | Spanner Graph |
|---|---|
| Case 表达式 | 受支持。 |
| Exists 子查询 | 受支持。 |
| 地图投影 | 不受支持。STRUCT 类型提供类似的功能。 |
| 列表推导式 | 不受支持。GENERATE_ARRAY 和 ARRAY_TRANSFORM 涵盖了大多数用例。 |
查询参数
以下查询显示了在 openCypher 和 Spanner Graph 中使用参数的区别。
| openCypher | Spanner Graph | |
|---|---|---|
| 参数 | MATCH (n:Person) WHERE n.id = $id RETURN n.name; | GRAPH FinGraph MATCH (n:Person) WHERE n.id = @id RETURN n.name; |
Mutation
Spanner Graph 使用 GoogleSQL DML 修改节点和边缘输入表。如需了解详情,请参阅插入、更新或删除 Spanner Graph 数据。
创建节点和边缘
| openCypher | Spanner Graph | |
|---|---|---|
| 创建节点和边缘 | CREATE (:Person {id: 100, name: 'John'}); CREATE (:Account {id: 1000, is_blocked: FALSE}); | INSERT INTO Person (id, name) VALUES (100, "John"); |
| 使用查询结果创建节点和边缘 | MATCH (a:Account {id: 1}), (oa:Account) WHERE oa <> a CREATE (a)-[:Transfers {amount: 100, create_time: timestamp()}]->(oa); | INSERT INTO AccountTransferAccount(id, to_id, create_time, amount) SELECT a.id, oa.id, CURRENT_TIMESTAMP(), 100 FROM GRAPH_TABLE( FinGraph MATCH (a:Account {id:1000}), (oa:Account) WHERE oa <> a ); |
在 Spanner Graph 中,标签会根据 CREATE PROPERTY GRAPH DDL 语句进行静态分配。
更新节点和边缘
| openCypher | Spanner Graph | |
|---|---|---|
| 更新属性 | MATCH (p:Person {id: 100}) SET p.country = 'United States'; | UPDATE Person AS p SET p.country = 'United States' WHERE p.id = 100; |
如需更新 Spanner Graph 标签,请参阅创建、更新或删除 Spanner Graph 架构。
合并节点和边缘
| openCypher | Spanner Graph | |
|---|---|---|
| 插入新元素或更新属性 | MERGE (p:Person {id: 100, country: 'United States'}); | INSERT OR UPDATE INTO Person (id, country) VALUES (100, 'United States'); |
删除节点和边缘
删除边缘与删除输入表相同。
| openCypher | Spanner Graph | |
|---|---|---|
| 删除节点和边缘 | MATCH (p:Person {id:100}), (a:Account {id:1000}) DELETE (p)-[:Owns]->(a); | DELETE PersonOwnAccount WHERE id = 100 AND account_id = 1000; |
删除节点需要处理可能存在的悬空边缘。指定 DELETE CASCADE 时,DELETE 会移除节点的关联边缘,与 openCypher 中的 DETACH DELETE 类似。如需了解详情,请参阅 Spanner 架构概览。
| openCypher | Spanner Graph | |
|---|---|---|
| 删除节点和关联的边缘 | DETACH DELETE (:Account {id: 1000}); | DELETE Account WHERE id = 1000; |
返回变更结果
| openCypher | Spanner Graph | |
|---|---|---|
| 在插入或更新后返回结果 | MATCH (p:Person {id: 100}) SET p.country = 'United States' RETURN p.id, p.name; | UPDATE Person AS p SET p.country = 'United States' WHERE p.id = 100 THEN RETURN id, name; |
| 在删除后返回结果 | DELETE (p:Person {id: 100}) RETURN p.country; | DELETE FROM Person WHERE id = 100 THEN RETURN country; |