使用 BigQuery Graph 实现供应链可追溯性

1. 简介

在此 Codelab 中,您将学习如何利用 BigQuery Graph 解决复杂的供应链和物流问题。

您将对一个餐饮供应链网络进行建模,重点关注食品安全和质量控制。当食品安全问题出现时(例如供应商提供的食材受到污染),时间就是生命。确定“影响范围”并快速执行精准召回,可以节省成本并保护客户。

餐厅食品安全恐慌

传统的关系型模型需要执行复杂的多步骤 JOIN 操作,才能跟踪商品在多个阶段(供应商 -> 配送中心 -> 供应站 -> 商店 -> 成品)的流转情况。借助 BigQuery Graph,我们可以直接对这些关联进行建模,从而使用 ISO GQL (Graph Query Language) 标准进行直观、快速的查询。

学习内容

  • 如何在现有 BigQuery 表的基础上定义图模型。
  • 如何在 BigQuery 中创建属性图。
  • 如何运行遍历查询,跟踪上游和下游影响。

所需条件

  • 启用了结算功能的 Google Cloud 项目。
  • Google Cloud Shell。

费用估算值

本实验预计会产生不到 5 美元的 BigQuery 分析费用,这完全在新用户的免费层级分配额度内。

2. 设置和要求

打开 Cloud Shell

您将在 Cloud Shell 中完成大部分操作,这是一个预装了使用 Google Cloud 所需的一切工具的环境。

  1. 前往 Google Cloud 控制台。
  2. 点击右上角工具栏中的激活 Cloud Shell 图标。
  3. 如果看到提示,请点击继续。

设置环境变量

在 Cloud Shell 中,设置项目 ID 以简化后续命令。

export PROJECT_ID=$(gcloud config get-value project)

启用 API

运行以下命令可启用所需的 BigQuery API:

gcloud services enable bigquery.googleapis.com

3. 创建架构和表

您将创建一个数据集和多个表,用于表示供应链组件:

  • item:通用商品定义(例如,番茄、鸡肉)。
  • location:设施(供应商、配送中心、咖啡馆)。
  • itemlocation:表示商品目录位置的交集表。
  • bom:物料清单(定义重量关系,例如商品 A 包含在商品 B 中)。
  • makes:将 itemlocation 映射到 item。
  • stored_at:将 itemlocation 映射到 location。

创建数据集

您可以使用 Cloud Shell 或 BigQuery 控制台运行本实验中的 SQL 命令。

如需使用 BigQuery 控制台,请执行以下操作:

  1. 在新标签页中打开 BigQuery 控制台。
  2. 将本实验中的每个 SQL 代码段粘贴到编辑器中,然后点击运行按钮执行。

BigQuery 编辑器

在 Cloud Shell 中运行以下命令,或使用 BigQuery 控制台创建架构。您将在 SQL 中使用节点变量。

BigQuery 数据架构

注意:(1) 如需在 Google Colab 中执行此操作,您还可以使用 BigQuery 魔法命令:%%bigquery。以下代码段会在您的项目中创建餐厅架构,用于存储图数据。(2) 如果您在 Google Colab 中运行,则需要使用 %%bigquery –project <PROJECT_ID>。确保 PROJECT_ID 字段映射到您要使用的相应项目:PROJECT_ID = "argolis-project-340214" # @param {"type":"string"} (3) 如果您使用的是 Colab,则需要根据您的要求安装一些库。如果您要使用图表可视化功能,请务必使用 pip 安装该库:spanner-graph-notebook==1.1.5

Colab 中的 BigQuery 魔法命令

%%bigquery --project=$PROJECT_ID
CREATE SCHEMA IF NOT EXISTS restaurant ;

创建表

执行以下 SQL 代码以构建表。

%%bigquery --project=$PROJECT_ID
-- 1. Item Table
DROP TABLE IF EXISTS `restaurant.item`;
CREATE TABLE `restaurant.item` (
  itemKey STRING,
  itemName STRING,
  itemCategory STRING,
  shelfLifeDays INT64,
  PRIMARY KEY (itemKey) NOT ENFORCED
);

-- 2. Location Table
DROP TABLE IF EXISTS `restaurant.location`;
CREATE TABLE `restaurant.location` (
  locationKey STRING,
  locationType STRING,
  locationCity STRING,
  locationState STRING,
  dunsNumber INT64,
  PRIMARY KEY (locationKey) NOT ENFORCED
);
-- 3. ItemLocation Table
DROP TABLE IF EXISTS `restaurant.itemlocation`;
CREATE TABLE `restaurant.itemlocation` (
  itemLocationKey STRING,
  itemKey STRING,
  locationKey STRING,
  variants INT64,
  PRIMARY KEY (itemLocationKey) NOT ENFORCED,
  -- Foreign Key Definitions
  FOREIGN KEY (itemKey) REFERENCES `restaurant.item`(itemKey) NOT ENFORCED,
  FOREIGN KEY (locationKey) REFERENCES `restaurant.location`(locationKey) NOT ENFORCED
);

-- 4. BOM Table
DROP TABLE IF EXISTS `restaurant.bom`;
CREATE TABLE `restaurant.bom` (
  bomKey INT64,
  parentItemLocation STRING,
  childItemLocation STRING,
  childQuantity FLOAT64,
  PRIMARY KEY (bomKey) NOT ENFORCED
);

-- 5. Makes Table
DROP TABLE IF EXISTS `restaurant.makes`;
CREATE TABLE `restaurant.makes` (
  itemLocationKey STRING,
  itemKey STRING,
  locationKey STRING,
  variants INT64,
  PRIMARY KEY (itemLocationKey) NOT ENFORCED
);

DROP TABLE IF EXISTS `restaurant.stored_at`;
CREATE TABLE `restaurant.stored_at` (
  itemLocationKey STRING,
  itemKey STRING,
  locationKey STRING,
  variants INT64,
  PRIMARY KEY (itemLocationKey) NOT ENFORCED
);

4. 正在加载示例数据

为了使本实验完全独立,您将使用纯 SQL LOAD DATA 语句在表中填充示例数据。这表示一个网络,从供应商开始,经过配送中心 (DC) 和中央厨房,最后到达零售咖啡馆。

运行以下 SQL 查询以加载数据:

BigQuery 数据加载

注意:如果您直接在 BigQuery Studio 中运行,则可以省略 %%bigquery

%%bigquery --project=$PROJECT_ID
-- Load Item
LOAD DATA OVERWRITE `restaurant.item`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/item2.csv'], skip_leading_rows = 1);

-- Load Location
LOAD DATA OVERWRITE `restaurant.location`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/location.csv'], skip_leading_rows = 1);

-- Load ItemLocation
LOAD DATA OVERWRITE `restaurant.itemlocation`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/itemlocation.csv'], skip_leading_rows = 1);

-- Load BOM
LOAD DATA OVERWRITE `restaurant.bom`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/bom2.csv'], skip_leading_rows = 1);

-- Load Makes
LOAD DATA OVERWRITE `restaurant.makes`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/makes.csv'], skip_leading_rows = 1);

-- Load StoredAt
LOAD DATA OVERWRITE `restaurant.stored_at`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/itemlocation.csv'], skip_leading_rows = 1);

5. 添加限制条件和定义图表

在构建图之前,您需要使用标准 SQL 主键和外键约束来声明语义关系。这些键可引导 BigQuery 理解节点标识符,并将边表连接到节点表。

创建属性图

现在,您需要将这些表合并为一个名为 restaurant.bombod 的内聚图结构。

您需要定义:

  • 节点:item、location、itemlocation
  • 边缘:makes、stored_at 和 consists_of (BOM)
%%bigquery --project=$PROJECT_ID

CREATE OR REPLACE PROPERTY GRAPH `restaurant.bombod`
NODE TABLES (
  `restaurant.item` KEY (itemKey) LABEL item PROPERTIES ALL COLUMNS,
  `restaurant.location` KEY (locationKey) LABEL location PROPERTIES ALL COLUMNS,
  `restaurant.itemlocation` KEY (itemLocationKey) LABEL itemlocation PROPERTIES ALL COLUMNS
)
EDGE TABLES (
  `restaurant.makes`
    KEY (itemLocationKey)
    SOURCE KEY (itemLocationKey) REFERENCES `restaurant.itemlocation`(itemLocationKey)
    DESTINATION KEY (itemKey) REFERENCES `restaurant.item`(itemKey)
    LABEL makes PROPERTIES ALL COLUMNS,

  `restaurant.bom`
    KEY (bomKey)
    SOURCE KEY (childItemLocation) REFERENCES `restaurant.itemlocation`(itemLocationKey)
    DESTINATION KEY (parentItemLocation) REFERENCES `restaurant.itemlocation`(itemLocationKey)
    LABEL consists_of PROPERTIES ALL COLUMNS,

  `restaurant.stored_at`
    KEY (itemLocationKey)
    SOURCE KEY (itemLocationKey) REFERENCES `restaurant.itemlocation`(itemLocationKey)
    DESTINATION KEY (locationKey) REFERENCES `restaurant.location`(locationKey)
    LABEL stored_at PROPERTIES ALL COLUMNS
);

6. 直观呈现供应链

您可以运行自上而下的遍历查询,查看整个供应链网络。在支持此功能的标准笔记本或界面(例如 %%bigquery --graph)中,此操作会返回一个可视化地图。

使用绝对图表查询来获取节点和边缘设置。

注意:如前所述,如需在 Google Colab 或 Colab Enterprise Notebooks 中执行此操作,您还可以使用 BigQuery 魔法命令:%%bigquery。此外,如需在 Google Colab 或 Colab Enterprise Notebooks 中直观呈现图表,请添加 –graph 标志,如下所示:%%bigquery –graph

%%bigquery  --project=$PROJECT_ID --graph output

Graph restaurant.bombod

match p=(a:itemlocation)-[c:consists_of]->(b:itemlocation)
match q=(a)-[d:stored_at]->(e:location)
optional match z=(f)-[g:makes]-(b)

return to_json(p) as ppath, to_json(q) as qpath, to_json(z) as zpath

输出:

餐馆供应图表

7. 应用场景 1:跟踪上游投诉

场景:一位顾客投诉纽约门店的三明治中鸡肉的质量问题。您需要反向追踪成品,查看其直接组装阶段。

遍历查询

使用图遍历查询格式运行查询。这会查看将下游组件与上游成分相关联的 consists_of 条边。

%%bigquery --project=$PROJECT_ID --graph

GRAPH restaurant.bombod
MATCH p=(a:itemlocation)-[c:consists_of]->(b:itemlocation)
OPTIONAL MATCH q=(b)-[d:stored_at]-(e)
return to_json(p) as ppath, to_json(q) as qpath

由于 consists_of 边缘表 (Ingredient -> Finished) 中的箭头方向,向上游流动的搜索会产生链接,从而快速隔离依赖的材料和存储位置。

输出:探索鸡肉来源

8. 应用场景 2:影响分析

场景:一场暴风雪导致俄亥俄州哥伦布市的配送中心关闭。您需要知道哪些下游准备工作或成品会立即受到影响。

遍历查询

您从代表配送中心的特定 location 开始,确定其中存储的库存,并查看哪些成品需要这些库存。

# @title Impact of a storm on a DC

%%bigquery  --project=$PROJECT_ID --graph
Graph restaurant.bombod
match path1=(z:itemlocation)-[m:stored_at]->(dc:location) where dc.locationKey like '%DC-Sysco-Columbus-OH%'
match path2=(z:itemlocation)-[c:consists_of]->(b:itemlocation)
match path3=(b:itemlocation)-[n:makes]->(item:item)
optional match path4=(b)-[p:stored_at]->(q:location)
return to_json(path1) as path1, to_json(path2) as path2,to_json(path3) as path3, to_json(path4) as path4


输出:风暴影响

9. 应用场景 3:下游召回

场景:供应商通知您,有一批特定商品受到污染:来自该供应商的藤熟番茄。您需要找出咖啡馆中所有受影响的最终菜单项。

遍历查询

您需要查找受污染原材料的位置,然后向下游执行路径遍历,以找到最终受影响的商品。

%%bigquery  --project=$PROJECT_ID --graph
Graph restaurant.bombod
match path1=(a:itemlocation)-[c:consists_of]->(b:itemlocation)-[e:makes]->(f:item) where f.itemKey like '%Tomato%'
return to_json(path1) as result

此查询会找到与“Tomato”模式匹配的所有商品,并与上游关系交织在一起,从而形成一个强大的映射,该映射会传播以发现必须召回哪些咖啡馆商品。

输出:Bad Tomatoes 下游影响

10. 清理

完成演示步骤后,请删除资源,以免工作区中产生任何剩余费用。

DROP SCHEMA `restaurant` CASCADE;

11. 总结

恭喜!您已使用 BigQuery Graph 对供应链进行建模并执行了影响分析。

小结

您学习了如何:

  1. 使用主键/外键声明以图为中心的关系型关系。
  2. 创建统一的属性图表。
  3. 使用图表查询遍历逻辑高效浏览多节点关系。

如需深入了解图架构,请访问 Google Cloud 文档。