适用于 openCypher 用户的 Spanner Graph 参考文档

本文档从以下几个方面对 openCypher 和 Spanner Graph 进行了比较:

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

本文档假定您熟悉 openCypher v9

准备工作

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

术语

openCypher Spanner Graph
nodes nodes
关系 边缘
节点标签 节点标签
关系类型 边缘标签
子句 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;
      
结果为空。 结果为空。 结果:
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 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 有两个内置函数可用于查找节点之间的最短路径: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 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 列表。
您不能在单个列表中混用 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
Case 表达式 受支持。
Exists 子查询 受支持。
地图投影 不受支持。
STRUCT 类型提供类似的功能。
列表推导 不受支持。
GENERATE_ARRAYARRAY_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});

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;

后续步骤