零售商品发现正在从“输入关键词、返回商品列表”转向理解购物意图、商品语义和实体关系。Target 的 Gift Finder 聊天智能体就是一个典型场景:系统不仅要找到语义相近的商品,还要理解品类、品牌、适用年龄、兼容配件和顾客偏好,并在实时交易数据持续变化时保持结果一致。
Target 为此将原本分散在 Elasticsearch、NoSQL 数据库和同步管道中的能力迁移到 Spanner Graph,在同一平台中承载事务、图关系、向量和全文索引。结果不仅是更完整的 GraphRAG 上下文,也让数据库维护时间减少了 50%。
真正的瓶颈不是搜索,而是跨系统一致性
旧架构中的每个组件都有明确用途:Elasticsearch 负责倒排索引和关键词搜索,NoSQL 数据库保存交易状态,向量数据库可以承担语义召回,图数据库则适合多跳关系查询。问题出在这些组件必须共同回答一次购物请求。
例如,顾客询问“给八岁孩子买一个可以继续扩展的科学玩具”,系统可能需要同时完成:
- 用全文搜索识别“科学玩具”等明确词语;
- 用向量相似度理解“可以继续扩展”的语义;
- 沿图关系查找适用年龄、兼容配件和所属系列;
- 检查商品当前是否可售以及价格是否有效;
- 将结果组织成可供大语言模型引用的上下文。
如果这些信息位于四套数据库中,就必须维护变更捕获、重试、幂等写入、索引重建和延迟监控。任何一条同步链路落后,都可能让智能体推荐已经缺货的商品,或者遗漏刚刚建立的配件关系。这里最难解决的不是某一种查询,而是多个数据副本之间的一致性。
用企业本体组织“商品是什么、和谁有关”
Target 在 Spanner Graph 上构建的是一个企业级零售本体,也就是用统一实体和关系描述不同业务域的“graph-of-graphs”。其中可以包含商品、品类、品牌和顾客偏好等节点,以及属于、兼容、适用和偏好等边。
这套架构由三个部分组成:
- 企业数据增强层:聚合多个后端来源的商品目录和元数据,并使用生成式 AI 补充商品属性。
- 统一存储层:在 Spanner 中保存关系表、图节点、边、向量嵌入和全文索引,通过 ACID 事务更新权威状态。
- 编排与 AI 层:执行混合检索,为 Gift Finder 一类会话界面提供结构化上下文,并负责输出评估和负责任 AI 治理。
关键变化是:图、向量和全文能力不再拥有彼此独立的数据副本。开发者可以组合 SQL 和 GQL 查询关系数据与图结构,不需要先通过 ETL 将目录复制到另一套专用数据库。
GraphRAG 比单纯向量召回多解决了什么
传统 RAG 常把商品描述切成文本块,再按照向量距离取回最相似的若干条记录。这适合发现语义相近的商品,却不擅长表达确定关系。
“玩具 A 与扩展包 B 兼容”不是模糊相似性,而是一条需要精确保存和遍历的边。“商品适合 8 至 10 岁”也不应该仅依赖描述文本中的偶然措辞。GraphRAG 可以先通过向量和关键词找到候选商品,再沿图关系扩展出兼容配件、品类、品牌和年龄限制,最后把这些有结构的事实交给模型。
一种可实践的检索顺序是:
- 使用全文和向量查询生成候选集;
- 根据库存、地区和有效时间过滤候选商品;
- 对候选节点执行一到多跳图遍历;
- 为每条关系保留来源、时间戳和置信度;
- 将结构化事实而不是整库原文交给模型生成回答。
这样既控制了上下文长度,也能降低模型把“语义相似”误写成“明确兼容”的风险。
可以这样建模和验证混合检索
下面是一个可改造的 Spanner Graph DDL 示例。它演示商品、品类和商品归属关系的最小模型。表名、主键和属性需要按照实际目录调整;执行前还应对照当前 Spanner Graph 文档确认实例所支持的 DDL 语法。
CREATE TABLE Products (
product_id STRING(36) NOT NULL,
title STRING(512) NOT NULL,
description STRING(MAX),
embedding ARRAY<FLOAT32>(vector_length=>768),
available BOOL NOT NULL,
updated_at TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
) PRIMARY KEY (product_id);
CREATE TABLE Categories (
category_id STRING(36) NOT NULL,
name STRING(256) NOT NULL
) PRIMARY KEY (category_id);
CREATE TABLE ProductCategories (
product_id STRING(36) NOT NULL,
category_id STRING(36) NOT NULL,
relation_source STRING(64),
updated_at TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true),
CONSTRAINT FK_Product FOREIGN KEY (product_id)
REFERENCES Products (product_id),
CONSTRAINT FK_Category FOREIGN KEY (category_id)
REFERENCES Categories (category_id)
) PRIMARY KEY (product_id, category_id);
CREATE PROPERTY GRAPH RetailGraph
NODE TABLES (
Products KEY (product_id) LABEL Product PROPERTIES ALL COLUMNS,
Categories KEY (category_id) LABEL Category PROPERTIES ALL COLUMNS
)
EDGE TABLES (
ProductCategories
SOURCE KEY (product_id) REFERENCES Products (product_id)
DESTINATION KEY (category_id) REFERENCES Categories (category_id)
LABEL BELONGS_TO PROPERTIES (relation_source, updated_at)
);
写入服务应该在一次事务中更新商品事实和关系,而不是先写主库、稍后再异步修补图。下面的伪代码强调事务边界;客户端初始化和具体 mutation API 需要按所用语言的 Spanner SDK 补充:
def upsert_catalog_item(transaction, product, category_ids):
transaction.upsert(
table="Products",
columns=[
"product_id", "title", "description",
"embedding", "available", "updated_at"
],
values=[[
product.id, product.title, product.description,
product.embedding, product.available, "spanner.commit_timestamp()"
]],
)
for category_id in category_ids:
transaction.upsert(
table="ProductCategories",
columns=[
"product_id", "category_id",
"relation_source", "updated_at"
],
values=[[
product.id, category_id,
"catalog-pipeline", "spanner.commit_timestamp()"
]],
)
生产系统还需要为嵌入模型版本建立显式字段。否则模型升级后,新旧向量可能混在同一个索引中,导致相似度无法稳定比较。关系边同样应保存来源和更新时间,方便处理生成式 AI 增强数据的回滚与审计。
零停机迁移应把“正确性”拆成可观测指标
Target 没有一次性替换旧系统,而是依次完成本体映射、实时并行回放、金丝雀放量以及最终切换。这个顺序值得保留,因为搜索迁移不能只比较 HTTP 成功率。
并行阶段至少应持续比较以下指标:
- 同一请求在新旧系统中的候选商品重合率;
- Top-K 排名差异和人工标注相关性;
- 商品、关系、向量及全文索引的更新延迟;
- 图遍历深度增加后的 P95 和 P99 延迟;
- 缺货商品误召回率;
- 智能体回答中可追溯事实的覆盖率;
- 高峰流量下的事务冲突、配额和自动扩缩容行为。
金丝雀流量应按地区、入口或稳定哈希逐步扩大,并准备将读取切回旧平台的开关。只有当语义质量、数据库稳定性和业务指标都经过真实流量验证后,才能删除 Elasticsearch 集群及其同步任务。
采用前要算清的账
统一平台减少的是跨数据库同步、集群维护和数据重复,不代表数据建模本身会自动变简单。团队仍然要治理本体版本、热点主键、图遍历范围、向量成本、全文分词策略以及 AI 生成属性的可信度。
评估类似方案时,可以用四个问题快速判断:
- 一次用户请求是否经常跨事务、关键词、向量和图查询?
- 当前团队是否花费大量时间处理索引同步和结果不一致?
- 图关系是否属于业务事实,而不只是展示层的临时关联?
- 是否具备影子流量、离线相关性评估和快速回滚能力?
如果前两个答案明确为“是”,统一多模型数据平台通常比继续增加单用途数据库更值得验证。Target 的经验表明,收益不仅来自查询能力,还来自删掉同步链路和独立集群之后释放出的工程时间。不过,50% 的维护降幅是其特定架构和组织环境下的结果,其他团队仍应通过并行迁移和可量化指标验证自己的实际收益。