本文档介绍了 Spanner 图架构,并提供了示例来说明关键概念。如需详细了解 Spanner Graph,请参阅 Spanner Graph 概览。
属性图数据模型
借助属性图,您可以对关联的数据进行建模。它将信息表示为节点和边的网络。节点表示数据环境中的实体,例如客户、产品或地点。边表示这些节点之间的连接,描述“已购买”“关注”或“位于”等关系。
节点和边都可以包含以下信息:
- 标签,用于将节点和边分类到集合中,例如城市。
- 属性,即键值对,例如人口。
图 1 中的示例展示了如何设计图表来对财务活动进行建模。此图包含以下类型的以节点形式建模的实体:
- 个人:表示参与金融交易的个人。
- 账号:表示用于交易的银行账户。
这些实体通过不同类型的关系相连,这些关系由以下有向边表示:
- 拥有:个人拥有一个或多个账号。
- 转账:资金从一个账户转移到另一个账户。
每个有向边都表示从源节点流向目的节点的单向关系。例如,Transfers
边将源 Account
连接到目的地 Account
,表示资金流向。
图 1. 包含多个节点和有向边的图示例。
节点和边可以在属性中包含其他信息。每个属性都有一个名称和一个值。
- Person 节点具有以下属性:
name
(STRING
)id
(INT64
)
- 转移边具有以下属性:
amount
(FLOAT64)
有向边和无向边
示例图表使用有向边,用于指明实体之间关系的特定方向。不过,某些关系(例如社交网络中的好友关系)是无向的,它们表示没有明确起点或终点的互惠连接。在这种情况下,您可以将无向边建模为两个有向边,每个方向一个边。
Spanner Graph 架构设计
借助 Spanner Graph,您可以使用 CREATE PROPERTY GRAPH 语句根据表创建图。用于创建图表的表格称为输入表格。此方法基于 SQL/PGQ(属性图查询),该方法是 SQL:2023 标准的一部分。
在属性图中定义节点
如需定义节点,请在 NODE TABLES 子句中添加节点定义。最简单的节点定义形式仅包含输入表名称。输入表中的行会映射到图节点。
在以下示例中,您使用 NODE TABLES 子句在 FinGraph
属性图中定义 Account
节点。节点定义包含输入表 Account
。
-- First, create an Account table.
CREATE TABLE Account (
id INT64 NOT NULL,
create_time TIMESTAMP,
) PRIMARY KEY (id);
-- Next, use the Account table as input table of Account node definition.
CREATE PROPERTY GRAPH FinGraph
NODE TABLES (
Account
);
默认标签和属性
默认情况下,所有节点都使用输入表名称作为标签,并且输入表中的所有列都会作为节点属性公开。
在前面的示例中,
- 每个账号节点都有
Account
标签。 - 每个账号节点都有从
Account
表列创建的属性[id, create_time]
。
元素键
节点定义还定义了元素键,该键用于唯一标识图节点。
- 默认情况下,元素键是输入表的主键。
- 元素键可以通过
KEY
子句明确定义。 - 具有唯一性约束条件
UNIQUE INDEX
的列可以用作元素键。
以下示例定义了 Account
节点和 Person
节点。
- 默认情况下,
Account
节点使用Account
表的主键作为其元素键。 - 另一方面,
Person
节点使用KEY
子句明确指定id
作为元素键。
CREATE TABLE Person (
id INT64 NOT NULL,
name STRING(MAX),
) PRIMARY KEY (id);
CREATE TABLE Account (
id INT64 NOT NULL,
create_time TIMESTAMP,
) PRIMARY KEY (id);
CREATE PROPERTY GRAPH FinGraph
NODE TABLES (
Person KEY (id),
Account
);
将输入表中的行映射到图表中的节点
- 具有非 null 元素键的每一行都会映射到图中的一个唯一节点(由元素键标识)。
- 系统会忽略元素键为 null 的行。
在属性图中定义边
如需定义边,请将边定义添加到 EDGE TABLES 子句中。最简单的边定义形式仅包含输入表名称。输入表中的行会映射到图边。
边的默认标签和属性的定义方式与节点相同。
每个边的元素键的定义方式与节点相同。
来源和目标节点引用
在以下示例中,您将使用以下内容创建属性图 FinGraph
:
Person
和Account
节点PersonOwnAccount
边缘
CREATE TABLE Person (
id INT64 NOT NULL,
name STRING(MAX),
) PRIMARY KEY (id);
CREATE TABLE Account (
id INT64 NOT NULL,
create_time TIMESTAMP,
) PRIMARY KEY (id);
CREATE TABLE PersonOwnAccount (
id INT64 NOT NULL,
account_id INT64 NOT NULL,
create_time TIMESTAMP,
FOREIGN KEY (account_id) REFERENCES Account (id)
) PRIMARY KEY (id, account_id),
INTERLEAVE IN PARENT Person;
CREATE PROPERTY GRAPH FinGraph
NODE TABLES (
Person,
Account
)
EDGE TABLES (
PersonOwnAccount
SOURCE KEY (id) REFERENCES Person (id)
DESTINATION KEY (account_id) REFERENCES Account (id)
);
边定义必须使用 SOURCE KEY
、DESTINATION KEY
和 REFERENCES
子句定义源节点和目标节点引用。以下示例使用 PersonOwnAccount
的边定义来说明此概念:
EDGE TABLES (
PersonOwnAccount
SOURCE KEY (id) REFERENCES Person (id)
DESTINATION KEY (account_id) REFERENCES Account (id)
)
每个 PersonOwnAccount
边都会将 Person
(源)节点连接到 Account
(目的地)节点。
- 边的源节点是
Person
节点,其id
与边id
相同。 - 边的目标节点是
Account
节点,其id
与边account_id
相同。
此外,对于 PersonOwnAccount
边,以下为真:
- 元素键是
PersonOwnAccount
表的主键,即(id, account_id)
。 - 每个边都具有与
PersonOwnAccount
表中的列相同的一组属性。 - 每个边都有默认的
PersonOwnAccount
标签。
将边输入表中的行映射到图表中的边
- 边输入表中元素键不为 null 的每一行通常会映射到图表中的一个唯一边。
- 一行可能与图表中的零个或多个边对应,例如,当来源节点引用与来源节点表中的零个或多个节点匹配时。
- 您可以在不同的节点或边定义中使用相同的输入表,以创建不同的节点或边集。如需了解详情,请参阅合并节点和边输入表。
自定义标签和属性
您可以使用 LABEL 和 PROPERTIES 子句自定义标签和属性。
在以下示例中,定义了两个节点,即 Person
和 Account
。
Person
节点通过标签Customer
公开address
属性。address
属性由表达式CONCAT(city, ", ", country),
定义,该表达式引用输入表Person
中的city
和country
列。- 对于
Account
,Account
节点通过标签Account
公开id
和create_time
属性。 Person
和Account
具有Entity
标签,其中包含属性 [id, name
]。- 对于
Person
,id
和name
属性来自输入表列。 - 对于
Account
,name
属性引用输入表的nick_name
列。
- 对于
CREATE TABLE Person (
id INT64 NOT NULL,
name STRING(MAX),
birthday TIMESTAMP,
country STRING(MAX),
city STRING(MAX),
) PRIMARY KEY (id);
CREATE TABLE Account (
id INT64 NOT NULL,
create_time TIMESTAMP,
is_blocked BOOL,
nick_name STRING(MAX),
) PRIMARY KEY (id);
CREATE PROPERTY GRAPH FinGraph
NODE TABLES (
Person KEY (id)
LABEL Customer
PROPERTIES (CONCAT(city, ", ", country) AS address)
LABEL Entity PROPERTIES (id, name),
Account KEY (id)
LABEL Account PROPERTIES (id, create_time)
LABEL Entity PROPERTIES (id, nick_name AS name)
);
标签和房源一致性
在图表中,标签和属性通过其名称进行唯一标识。同名标签和属性可以在多个节点或边定义中出现。不过,同名标签和房源必须遵循以下规则:
- 具有相同名称的属性必须具有相同的值类型。
- 同名标签必须公开相同的属性列表。
在前面的示例中,Person
和 Account
节点中都定义了 Entity
标签。在这两种定义中,它们具有一组具有相同值类型的属性名称 [id
、name
]。
图表与其他架构对象之间的依赖关系
CREATE PROPERTY GRAPH
创建的图表依赖于其他架构对象,例如节点和边定义的输入表,以及属性引用的表列。如果架构更改会破坏其中一个依赖项,则不允许进行更改。
以下语句会创建 FinGraph
与 Account
表以及 id
、create_time
列之间的依赖项。
CREATE OR REPLACE PROPERTY GRAPH FinGraph
NODE TABLES (
Account PROPERTIES (id, create_time)
);
以下是您不允许进行的架构更改示例:
- 删除
Account
表,除非您先移除Account
节点定义。如需了解详情,请参阅移除现有节点或边定义。 - 从
Account
表中删除create_time
列,除非您先从Account
节点定义中移除create_time
属性。如需了解详情,请参阅更新现有节点或边定义。
不过,您可以进行以下架构更改:
- 修改
Account
表以及id
和create_time
列架构,前提是其他架构要求允许这样做。如需了解详情,请参阅进行架构更新。