关于 vtex-io-data-access-patterns
面向 VTEX IO 应用开发者的数据访问技能,帮助为数据选择存储位置、明确权威数据源并规划读取方式。重点约束配置存储用途,并避免全量扫描和不必要的数据副本。
主要功能
- 01按数据类型选择存储
- 02明确权威数据源
- 03采用有界查询与分页
- 04制定缓存新鲜度规则
- 05审查数据访问设计
适用场景
- 01设计新应用的数据流
- 02评估 Master Data 或 VBase
- 03审查大数据集读取代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vtex/ skills --skill vtex-io-data-access-patterns安装后在 Claude Code 中输入/vtex-io-data-access-patterns确认已加载。
详细介绍
数据访问与存储模式
适用场景
当主要问题是数据应存放在哪里,以及 VTEX IO 应用应如何读取或写入数据时,使用此技能。
- 为 IO 应用设计新的数据流
- 决定使用应用设置、配置应用、Master Data、VBase 还是 VTEX 核心 API
- 审查读取或写入大型、重复或关键数据集的代码
- 在现有 API 周围引入缓存层或派生的本地视图
以下情况不使用此技能:
- 详细的 Master Data 架构或实体建模
- 应用设置或配置应用的架构设计
- 身份验证令牌或策略,例如
AUTH_TOKEN、STORE_TOKEN或清单权限 - 服务运行时规格或并发调优
决策规则
为每类数据选择合适的存放位置
- 对于由商家或运营人员管理的稳定配置,例如功能开关、凭据、外部基础 URL 和行为开关,使用应用设置或配置应用。
- 对于属于该账户、需要验证、筛选、搜索、分页或生命周期管理的结构化自定义业务记录,使用 Master Data。
- 对于简单的键值文档、辅助快照或类似缓存的 JSON 载荷,通常按键读取而非广泛搜索时,使用 VBase。
- 对于已属于 VTEX 核心领域(如订单、目录、定价或物流)的数据,使用 VTEX 核心 API。
- 对于属于其他系统且 VTEX IO 仅与之集成的数据,使用外部存储或外部 API。
明确数据的唯一真实来源
- 对于订单、产品、价格、库存等核心商务领域,将 VTEX 核心 API 视为唯一真实来源。
- 除非有明确所有权的狭义派生用途,否则不要将完整订单、目录记录、价格或库存镜像到 Master Data 或 VBase。
- 如果 IO 应用需要本地副本,只存储该应用所需的最少字段或派生视图,并在需要时从权威数据源重新获取完整详情。
- 不要将应用设置或配置应用用作通用运营数据存储。
有意设计读取和缓存
- 优先使用 API 级别的筛选、分页、字段选择和有界读取,而不是将完整数据集加载到 Node 中并在内存里筛选。
- 只有在重复读取确有必要,且缓存视图具有明确的失效或新鲜度规则时,才使用缓存。
- 当后台任务或事件流水线需要持久化处理状态时,只存储重试和幂等所需的状态及关联数据。
- 除非用例明确要求持久化且由应用拥有的审计记录,否则不要在 Master Data 和 VBase 中存放长期日志、跟踪记录或无界历史数据。
硬性约束
约束:不得将配置存储用于运营数据存储
应用设置和配置应用必须用于表示配置,不得用于存储事务记录、无界列表或频繁变化的运营状态。
原因
将配置存储用作数据存储会模糊系统边界,使工作区行为更难理解,并破坏依赖设置保持精简且稳定的工具和流程的预期。
检测
如果在 settingsSchema、配置应用载荷或与设置相关的 API 中看到记录数组、日志、历史记录、订单或其他不断增长的运营载荷,请立即停止,并将这些数据迁移到 Master Data、VBase、核心 API 或外部存储中。
正确
{
"settingsSchema": {
"type": "object",
"properties": {
"enableModeration": {
"type": "boolean"
}
}
}
}
错误
{
"settingsSchema": {
"type": "object",
"properties": {
"orders": {
"type": "array"
}
}
}
}
约束:核心系统必须继续作为各自业务领域的事实来源
VTEX 核心系统,例如 Orders、Catalog、Pricing 和 Logistics,必须继续作为各自业务领域的主要事实来源。
重要原因
将本地 IO 副本视为核心业务领域的主要存储,会造成数据对账偏差、读取过时,以及基于过时数据做出业务决策。
检测方法
如果应用将完整的订单载荷、商品文档、库存快照或价格表存储在 Master Data 或 VBase 中,然后将这些副本用作业务决策的主要依据,请立即停止,并围绕权威上游数据源重新设计流程。
正确做法
const order = await ctx.clients.oms.getOrder(orderId)
ctx.body = {
orderId: order.orderId,
status: order.status,
}
错误做法
const cachedOrder = await ctx.clients.masterdata.getDocument({
dataEntity: 'ORD',
id: orderId,
})
ctx.body = cachedOrder
约束:读取大量数据时,必须避免全表扫描和内存过滤
访问大型或不断增长的数据集时,必须使用有界查询、筛选、分页或预先计算的派生视图,而不是全表扫描和大范围内存过滤。
重要原因
无界读取效率低下、难以扩展,并且随着数据集增长,很容易导致服务行为变得脆弱。
检测方法
如果你发现代码会从 Master Data、VTEX API 或外部存储中获取整个集合,然后在 Node 中为常规请求流程筛选或汇总结果,请立即停止,并重新设计访问路径。
正确做法
const documents = await ctx.clients.masterdata.searchDocuments({
dataEntity: 'RV',
fields: ['id', 'status'],
where: 'status=approved',
pagination: {
page: 1,
pageSize: 20,
},
})
错误做法
const allDocuments = await ctx.clients.masterdata.scrollDocuments({
dataEntity: 'RV',
fields: ['id', 'status'],
})
const approved = allDocuments.filter((doc) => doc.status === 'approved')
首选模式
每次设计数据方案时,都先回答以下四个问题:
- 这些数据属于谁?
- 谁是事实来源?
- 应用将如何查询这些数据?
- 应用是否真的需要存储本地副本?
然后有意识地选择:
- 稳定配置信息使用应用设置或配置应用
- 应用领域拥有的结构化自定义记录使用 Master Data
- 简单的键值文档或类似缓存的载荷使用 VBase
- 权威商务数据使用 VTEX 核心 API
- VTEX 之外拥有的数据使用外部存储或 API
如果应用存储本地副本,请确保副本体量小、属于派生数据,并且明确次于权威数据源。
常见失败模式
- 将应用设置用作记录、历史数据或大型列表的通用存储。
- 将完整订单、商品或价格从 VTEX 核心系统镜像到 Master Data 或 VBase,作为并行的事实来源。
- 获取完整数据集后,仅为常规请求流程在内存中筛选、排序或汇总。
- 使用 Master Data 或 VBase 存储无界的调试日志或事件转储。
- 添加缓存,却没有明确的新鲜度、失效或所有权规则。
- 在处理程序中分散临时的数据访问决策,而没有明确事实来源和存储决策。
审查清单
- 这些数据确实属于配置信息吗?还是应该存储在 Master Data、VBase、核心 API 或外部系统中?
- 是否明确了权威事实来源?
- 是否将 VTEX 核心系统视为订单、目录、价格、库存及类似业务领域的权威数据源?
- 本地存储是否仅限于应用真正拥有的数据或范围有限的派生视图?
- 是否在适当情况下通过筛选、字段选择和分页来限制读取范围?
- 缓存或本地副本是否有明确的新鲜度和失效规则?
相关技能
vtex-io-app-settings- 主要需要决定如何建模应用级配置时使用vtex-io-service-configuration-apps- 需要通过ctx.vtex.settings注入共享结构化配置时使用vtex-io-masterdata-strategy- 主要需要决定 Master Data 是否适合作为存储机制,以及如何对其建模时使用
参考资料
- Master Data - 结构化的账户级自定义数据存储
- VBase - 用于 VTEX IO 应用的键值存储和 JSON 数据块
- 使用 VTEX IO 客户端调用 VTEX commerce API - 如何从 VTEX IO 使用 Orders、Catalog、Pricing 和其他核心 API
- 配置应用设置 - 将应用设置用作配置,而非运营存储
- 为应用设置创建界面 - 应用设置的公开与私有之分以及配置边界