面向 openCypher 用户的 Spanner Graph 参考文档

本文档将从以下方面比较 openCypher 和 Spanner Graph:

  • 术语
  • 数据模型
  • 架构
  • 查询
  • Mutation

本文档假定您熟悉 openCypher v9

准备工作

使用 Google Cloud 控制台设置和查询 Spanner 图

术语

openCypher Spanner Graph
节点 节点
关系 边缘
节点标签 节点标签
关系类型 边标签
子句 Spanner Graph 使用术语 statement 来表示完整的执行单元,使用 clause 来表示语句修饰符。

例如,MATCH 是语句,而 WHERE 是子句。
关系唯一性

openCypher 不会在单个匹配中返回包含重复边的结果。
TRAIL 路径

如果希望在 Spanner 图中实现唯一性,请使用 TRAIL 模式,以便在单次匹配中返回唯一边。

标准合规性

Spanner Graph 采用 ISO 图查询语言 (GQL) 和 SQL/属性图查询 (SQL/PGQ) 标准。

数据模型

Spanner Graph 和 openCypher 都采用了属性图数据模型,但存在一些差异。

openCypher Spanner Graph
每种关系都有且仅有一个关系类型。
节点和边都有一个或多个标签。

架构

openCypher Spanner Graph
图表没有预定义的架构。 必须使用 CREATE PROPERTY GRAPH 语句明确定义图架构。
标签在架构中静态定义。如需更新标签,您需要更新架构。
如需了解详情,请参阅创建、更新或删除 Spanner 图架构

查询

Spanner Graph 查询功能与 openCypher 的查询功能类似。本部分介绍了 Spanner Graph 和 openCypher 之间的差异。

指定图表

在 openCypher 中,只有一个默认图,查询会对默认图进行操作。在 Spanner Graph 中,您可以定义多个图表,并且查询必须以 GRAPH 子句开头,以指定要查询的图表。例如:

   GRAPH FinGraph
   MATCH (p:Person)
   RETURN p.name
   ORDER BY p.name
   LIMIT 1;

如需了解详情,请参阅图表查询语法

图表模式匹配

Spanner Graph 支持类似于 openCypher 的图模式匹配功能。以下各部分介绍了这些差异。

关系唯一性和 TRAIL 模式

openCypher 不会在单个匹配中返回包含重复边的结果;这在 openCypher 中称为关系唯一性。在 Spanner Graph 中,默认会返回重复边。如需确保唯一性,请使用 TRAIL 模式,以确保单个匹配中不存在重复边。如需详细了解 TRAIL 和其他不同路径模式的语义,请参阅路径模式

以下示例展示了查询结果如何随 TRAIL 模式而变化:

  • openCypher 和 Spanner 图 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;
      
结果为空。 结果为空。 结果
src_id dst_id
16 20

以查询结果的形式返回图表元素

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 图中称为路径量化。路径量化使用不同的语法,如以下示例所示。如需了解详情,请参阅量化路径模式

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 图,您可以直接访问路径量化中使用的变量。在以下示例中,Spanner 图中的 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 有两个内置函数可用于查找节点之间的最短路径:shortestPathallShortestPath

  • 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...] 不受支持。
CREATEDELETESETREMOVEMERGE 如需了解详情,请参阅变更部分以及在 Spanner 图中插入、更新或删除数据

数据类型

Spanner Graph 支持所有 GoogleSQL 数据类型。如需了解详情,请参阅 GoogleSQL 中的数据类型

以下部分将 openCypher 数据类型与 Spanner 图数据类型进行比较。

结构类型

openCypher Spanner Graph
节点 节点
Edge Edge
路径 路径

属性类型

openCypher Spanner Graph
INT INT64
FLOAT FLOAT64
STRING STRING
BOOLEAN BOOL
LIST
由简单类型组成的同质列表。
例如,INT 列表、STRING 列表。
您不能在单个列表中混用 INTSTRING
ARRAY

复合类型

openCypher Spanner Graph
LIST ARRAYJSON
MAP STRUCTJSON

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 不受支持。
节点和边缘 .
property reference
.
[]
dynamic property reference
MATCH (n)
RETURN n[n.name]

不受支持。
将模式用作表达式 size(pattern) 不受支持。使用如下所示的子查询
VALUE {
  MATCH pattern
  RETURN COUNT(*) AS count;
}

属性类型函数和表达式

类型 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_SLICEARRAY_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
比较链
a < b < c

Spanner Graph 不支持比较链。这相当于与 AND 联接的比较。
例如:

      a < b AND b < C
      

布尔值 AND AND
OR OR
XOR
Spanner Graph 不支持 XOR。使用 <> 编写查询。

例如:
      boolean_1 <> boolean_2
      

NOT NOT
字符串 STARTS WITH STARTS_WITH
ENDS WITH ENDS_WITH
CONTAINS REGEXP_CONTAINS
+ CONCAT
列出 + ARRAY_CONCAT
IN ARRAY_INCLUDES
[] []

其他表达式

openCypher Spanner Graph
支持请求表达式 受支持。
Exists 子查询 受支持。
地图投影 不受支持。
STRUCT 类型提供类似的功能。
列表推理 不受支持。
GENERATE_ARRAYARRAY_TRANSFORM 涵盖了大多数用例。

查询参数

以下查询展示了在 openCypher 和 Spanner 图中使用参数的区别。

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 图数据

创建节点和边

openCypher Spanner Graph
创建节点和边
CREATE (:Person {id: 100, name: 'John'});
CREATE (:Account {id: 1000, is_blocked: FALSE});

MATCH (p:Person {id: 100}), (a:Account {id: 1000}) CREATE (p)-[:Owns {create_time: timestamp()}]->(a);
INSERT INTO
Person (id, name)
VALUES (100, "John");

INSERT INTO Account (id, is_blocked) VALUES (1000, FALSE);
INSERT INTO PersonOwnAccount (id, account_id, create_time) VALUES (100, 1000, CURRENT_TIMESTAMP());
使用查询结果创建节点和边
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;

后续步骤