mcpField
C
create-cubes

create-cubes

github.com/revosai数据与数据库0123 次安装5 天前更新
代码仓库

关于 create-cubes

为数据工程工作流提供的技能,可将现有 dbt gold 模型转换为 Cube.dev 语义模型 YAML,供 Cube 查询。它强调关系验证和用户确认,不负责构建 gold 模型。

主要功能

  1. 01发现并筛选 gold 模型
  2. 02分析字段、键与关联
  3. 03验证关联键和匹配率
  4. 04生成维度与度量定义
  5. 05按项目约定生成 Cube YAML

适用场景

  1. 01将 BigQuery gold 表暴露为 Cube 模型
  2. 02为多个模型配置并确认关联
  3. 03从 JSON 数组关系建立桥接模型

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/revosai/skills --skill create-cubes

安装后在 Claude Code 中输入/create-cubes确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
bq-pk-fk-conventions.md
cube-examples.md
hubspot-entities.md
jira-entities.md
key-patterns.md
netsuite-entities.md
stripe-entities.md
validation-queries.md

详细介绍

创建 Cube

技能依赖

此技能将 dbt 相关知识委派给 create-dbt-transformations: 项目布局、查找 gold 模型、将 dbt 模型名称解析为 BigQuery 表引用、 从 JSON 数组创建桥接模型,以及 dbt 验证命令。

如果未安装 create-dbt-transformations:直接使用 find dbt/models/gold -name "*.sql" 查找 gold 模型,并跳过桥接模型委派。 警告用户:“未安装 create-dbt-transformations 技能 — 桥接模型创建和 dbt 验证能力有限。”

如果需要探索 BigQuery(列出表、检查架构、预览行), 则按需加载 explore-lakehouse 技能。


用途

将现有 dbt gold 模型公开为可查询的 Cube.dev 语义模型,无需手动编写 YAML 样板代码。Gold 模型可以是表或视图。

每个 cube 都是存储在 cubes/ 中的完整独立定义。不进行修补或合并——文件中的内容就是将要部署的内容。

此技能不会构建 gold 模型。如果缺少所需的 gold 模型,请交由 create-dbt-transformations 处理。


命名约定

为 cube 名称和文件名去掉 gold_ 前缀。在 sql_table(物理表)中保留 gold_。

Cube 标识符是 spec.name(Cube.dev 的 definition.name)——编译器解析的名称,也是 ${CUBE} 和关联所引用的名称。它必须是有效的 SQL/JS 标识符:snake_case(字母、数字、下划线),不能使用连字符——spec.name 中的连字符会导致编译器返回通用的 500 错误,且不提供字段级消息。必须指定 spec.name。

metadata.name 是本地 IaC slug——cubes/<name>.yml 文件名,以及其他文件引用此文件时使用的地址。它永远不会发送到 API,按照惯例使用 kebab-case(hubspot-companies),与其他所有资源的 slug 风格一致。因此,一个 cube 同时具有两种名称:kebab-case slug 和 snake_case 标识符。关联引用 snake_case 标识符(${hubspot_companies}),而不是 slug。

gold SQL file:     dbt/models/gold/gold_hubspot_companies.sql
BigQuery table:    gold_hubspot_companies
cube file:         cubes/hubspot-companies.yml
metadata.name:     hubspot-companies     (local slug — kebab-case)
spec.name:         hubspot_companies     (cube identifier — snake_case, required)
join reference:    ${hubspot_companies}  (references spec.name)
sql_table:         "`<dataset>.gold_hubspot_companies`"

桥接 cube 也遵循同样的规则:gold_deals_companies -> cube 名称 deals_companies,文件 cubes/deals_companies.yml。

Cube sql_table 引用

直接引用仓库中的物理表。Cube 不理解 Jinja——不要使用 dbt ref()。

使用第 2 阶段解析出的字面 dataset 值。用 BigQuery 反引号括起:

sql_table: "`<dataset>.gold_hubspot_companies`"

在 refresh_key.sql 中采用相同的完整限定格式。


用户确认节点

确认节点 1:Gold 模型选择

发现 gold 模型后,展示可用模型并询问用户希望纳入哪些模型。用户选择之前不要继续。例外:如果用户指定了某一个模型,则视为已选中。

确认节点 2a:连接模型审批

当所选模型未直接连接时,搜索其余 gold 模型,查找连接模型。展示连接路径,并在添加前征求用户同意。

确认节点 2b:桥接 / 支持模型审批

检测到多对多关系且不存在合适的桥接模型时,询问是否创建一个。如果用户同意,则委派给 create-dbt-transformations。

确认节点 3:关系确认

展示已验证的关系、关联方向、基数和匹配率。生成 cube 文件前,请用户确认。不要将未经验证的关联标记为已确认——应标记为 validation pending。

确认节点 4:度量确认

生成默认的 count 度量,建议其他度量,并请用户确认或定义自定义度量。


工作流

按顺序执行以下阶段。不要跳步。


阶段 1:发现 Gold 模型并选择范围

  1. 使用 find dbt/models/gold -name "*.sql" 发现 Gold 模型。
  2. 如果没有发现任何模型,则停止,并告知用户先通过 create-dbt-transformations 创建 Gold 模型。
  3. 检查 cubes/ 中 1-2 个现有 cube 文件,识别惯例(extends:、public:、refresh_key 风格)。将识别出的惯例应用于新 cube。始终使用扁平的单 cube YAML(绝不使用 cubes: 或 views: 根节点)。
  4. 如果用户指定了某个模型,则查找该模型。如果未找到,则停止。
  5. 否则,列出发现的所有 Gold 模型,并询问用户希望纳入哪些模型(检查点 1)。
  6. 保留完整的发现列表,以供第 3 阶段搜索连接模型。

阶段 2:分析所选模型的架构和键

先解析环境变量

在生成任何 SQL 或 YAML 之前,将 $REVOS_BQ_DATASET 解析为字面值:

echo "DATASET=$REVOS_BQ_DATASET"

如果为空,则停止并请用户设置该值。在后续所有步骤中都使用这个字面值。

架构发现

检查每个所选 Gold 模型的列和类型。必要时使用 explore-lakehouse。

检查是否存在 _airbyte_extracted_at(refresh_key 所需,也是唯一要公开的 Airbyte 维度)。

键检测

检测主键、次级键、外键以及 JSON/数组键。 有关常见模式和检测规则,请参阅 references/key-patterns.md。

使用 SQL 验证主键的唯一性。请参阅 references/validation-queries.md 的第 1 节。

按照 key-patterns.md 中的格式,为每个模型输出架构摘要。


阶段 3:检测候选关系

构建候选关系图。这些仅为候选关系,必须在第 4 阶段进行验证。

单模型情况

如果只选择了一个模型,且它没有 JSON/数组关系列,则跳至第 6 阶段。如果它有 JSON/数组列,则检查是否需要桥接模型/联结模型。

关系类型和方向

使用 Cube 类型:one_to_one、one_to_many、many_to_one、many_to_many。方向始终以当前 cube 为参照。

基数规则
  1. 源外键可重复,目标键唯一 -> many_to_one / 反向为 one_to_many。
  2. 两侧均唯一 -> one_to_one。
  3. 两侧均可重复,或通过桥接模型关联 -> many_to_many。
  4. 如果无法确定,则先验证再提出。
直接联接检测

查找外键到主键的匹配、次级键匹配、现有桥接模型以及 JSON/数组关系字段。

连接模型搜索

如果所选模型之间不连通:

  1. 在所有已发现的 Gold 模型中搜索连接路径(先搜索长度为 2 的路径,再搜索长度为 3 的路径)。
  2. 检查未选中的模型,仅用于发现关系——这不会将其纳入范围。
  3. 展示连接路径并征求用户批准(检查点 2a)。
  4. 如果获批,则将其纳入范围并进行完整的架构发现。如果未获批,则记录不连通的模型。
桥接模型/联结模型检测

如果在 dbt/models/gold/ 中发现现有桥接模型:

  1. 检查其架构,并验证它是否包含预期的键列。
  2. 如果符合条件,则使用该模型。如果不完全符合,则展示不匹配之处并提供选项(按原样使用、创建新的模型或中止)。

如果不存在桥接模型,且用户批准创建一个(检查点 2b),则委托给 create-dbt-transformations。创建完成后,生成一个 public: false 的桥接 cube。


第 4 阶段:验证候选关系

使用 SQL 对照 BigQuery 验证候选联接是否有效,以及方向是否正确。

对每个候选关系,验证:

  • 键的唯一性
  • 外键匹配率(LEFT JOIN + 匹配百分比)
  • 反向聚合计数
  • 桥接边完整性(两侧)
  • JSON 数组提取匹配率
  • 通过 INFORMATION_SCHEMA 检查类型兼容性

所有 SQL 模板请参阅 references/validation-queries.md。

尽可能验证每个候选关系的两个方向。

不要将未经验证的联接标记为已确认。如果无法运行验证,请标记为 validation pending。


第 5 阶段:呈现已验证的关系

向用户呈现所有已验证的关系:所选模型、已批准的连接器、键、具有基数信息的联接、匹配率和验证证据。

请用户确认或修改(检查点 3)。确认前不要生成文件。

如果某个关系无法验证,但用户仍决定继续,请在生成的 YAML 中为其添加 # UNVALIDATED: <reason> 标记。


第 6 阶段:生成维度

将每个选定的 gold 模型中的所有业务列公开为 Cube 维度。

主要规则:

  1. 包含 PK,并设置 primary_key: true。对于复合 PK,使用合成 CONCAT 维度 — 参见 references/cube-examples.md 中的“复合主键”部分。
  2. 将次级键、名称、状态、时间戳和数值属性作为维度。
  3. 对于 _airbyte_* 列,仅将 _airbyte_extracted_at 作为维度 airbyte_extracted_at 纳入(引用为 ${CUBE}._airbyte_extracted_at)。排除所有其他 _airbyte_* 列。
  4. 不要仅仅因为业务列看起来暂时没有用处就将其移除。
  5. 用于关系的 JSON/数组列应通过桥接模型表示。
  6. 如果模型包含超过 50 个业务列,请在生成前询问用户。

类型映射和维度示例请参阅 references/cube-examples.md。


第 7 阶段:建议并确认度量值

  1. 始终包含默认的 count 度量值。
  2. 根据列名建议有用的其他度量值。请参阅 references/cube-examples.md 中的“度量值建议”部分。
  3. 在 FK 所属的 Cube 中定义 FK 列上的 count_distinct,而不是在父 Cube 中定义。联接会产生扇出,从而扭曲不同计数。
  4. 请用户确认建议的度量值或定义自定义度量值(检查点 4)。
  5. 如果自定义度量值定义不明确,请要求用户澄清。

阶段 8:生成 Cube 文件

在 cubes/ 中创建 Cube.dev YAML 文件。遵循阶段 1 中识别的现有样式。

主要规则:

  1. 每个文件一个 cube,采用 IaC 格式。 每个 cube 文件都是单个文档:apiVersion / kind: Cube / metadata / spec,cube 定义直接放在 spec 下(并将 spec.name 设为标识符)。不要在根级别用 cubes: 或 views: 包装。
  2. 文件名 = metadata.name(kebab-case slug,不带 gold_ 前缀)+ .yml;spec.name 是 snake_case 标识符。
  3. sql_table 使用带 gold_ 前缀的完全限定 BigQuery 引用。
  4. 每个已确认的关系都要在两个方向上添加 joins。
  5. 桥接/联结 cube 使用 public: false。
  6. 每个 cube 必须包含基于 SQL 的 refresh_key。使用 SELECT MAX(<timestamp_col>),并按以下优先级选择列:_airbyte_extracted_at(所有 Airbyte 数据源都有)、updated_at/modified_at(CDC 流)、created_at(仅插入事实表)。只有当表中不存在任何时间戳列时,才将 every: <interval> 作为最后手段——添加 YAML 注释说明原因(例如:# no timestamp column available)。
  7. refresh_key.sql 引用的表必须与 sql_table 相同。
  8. 对未经验证的 joins 添加 # UNVALIDATED: <reason>。
  9. 对于源自 Connection 摄取数据的 cube(即 gold 模型可追溯至通过对 Connection 执行 revos apply 生成的 bronze 表),设置 meta.abConnectionId: <connection-id>。这样可在 UI 中按来源 connection 对 cube 进行分组。使用 revos connections list --json 解析 connection id——根据 gold 模型读取的 bronze 表前缀与 spec.prefix 匹配。基于 connection 来源模型构建的桥接/联结 cube 继承相同的 abConnectionId。源自纯本地数据的 cube(例如,没有上游 connection 的手写 silver/gold 模型)省略 abConnectionId。
  10. 对于行具有自然且易读标签的 cube(公司、联系人、交易、工单、用户、项目等),设置 meta.nameDimension: <short-dimension-name>。该值是简短的维度键(不带 ${CUBE}. 前缀,也不带 cube 名称前缀),例如:properties_name、displayName、dealname。将 cube 添加为表格时,前端会用它选择作为实体名称显示的列(参见前端中的 useCubeFromMeta)。选择用户一眼就能认出是“此对象名称”的维度;如果不存在这样的单一列(纯 join/桥接 cube、事实表、事件日志),则省略 nameDimension。该维度必须存在于此 cube 的 dimensions: 下。
  11. 仅在需要时设置 meta.icon——请参阅下方的**“为每个 cube 选择图标”**。
  12. meta 是封闭的:只允许使用 abConnectionId、nameDimension 和 icon。如果这些字段都不适用,则省略整个 meta 块。

有关规范 cube、桥接 cube、join 方向示例和 refresh key 变体,请参阅 references/cube-examples.md。


为每个 cube 选择图标

桥接/联结 cube(public: false)始终省略 meta.icon。

对于所有其他 cube,判断是否需要 meta.icon:

  1. cube 有 meta.abConnectionId——检查此 connection 背后的数据源是否有品牌图标。 abConnectionId 的值是 RevOS connection ID(与规则 9 中解析出的相同)。 运行 revos connections get <abConnectionId> --json | jq '.spec.source.id' 获取 source id, 然后运行 revos sources get <source-id> --json | jq '.icon'。

    • icon 是非空字符串 → UI 会自动显示集成 Logo。省略 meta.icon。
    • icon 为 null、空值或字段不存在 → 使用下方目录设置 meta.icon。
  2. cube 没有 meta.abConnectionId → 始终使用下方目录设置 meta.icon。

目录键
键含义典型 Cube 名称
users终端用户、客户、账户持有人*users*、*customers*、*accounts*
orders采购订单、交易*orders*、*purchases*、*transactions*
events行为事件、活动日志*events*、*activity*、*logs*
products产品、SKU、商品*products*、*items*、*skus*
sessionsWeb/应用会话*sessions*、*visits*
revenue收入、付款、发票*revenue*、*payments*、*invoices*
companiesB2B 公司、组织*companies*、*organizations*、*accounts*
contacts个人 / CRM 联系人*contacts*、*people*、*persons*
deals销售交易、商机*deals*、*opportunities*
tickets支持工单、问题*tickets*、*issues*、*cases*
campaigns营销活动*campaigns*、*ads*
emails电子邮件*emails*、*messages*
leads销售线索*leads*
tasks任务、待办事项*tasks*、*todos*
三种可接受的形式
meta:
  icon: "users"                                # catalog key (preferred)
  # — or —
  icon: "url:https://cdn.example.com/icon.svg" # explicit external URL
  # — or —
  icon: "data:image/svg+xml;base64,…"          # inline SVG data URI

尽可能使用目录键。只有目录未涵盖的自定义品牌图标才使用 url: 或 data:。 格式错误的值会导致 revos apply 拒绝文件,并显示明确的错误。


阶段 9:验证生成的文件

  1. 如果已调用 create-dbt-transformations(桥接模型),它已验证 dbt 模型。否则运行 dbt parse。
  2. 验证 BigQuery 中的物理表是否存在:bq show <dataset>.<table_name>。如果不存在,请记录为待处理。
  3. 验证生成的 Cube 文件是否符合规范:扁平 YAML、命名正确、sql_table 正确、包含所有维度、包含 refresh_key,并且连接关系是双向的。

最终回复格式

Created cube definitions.

Selected gold models:
- dbt/models/gold/<gold_model_1>.sql

Approved connector models:
- dbt/models/gold/<connector_model>.sql

Bridge/support models created (via create-dbt-transformations):
- dbt/models/gold/<bridge_model>.sql

Cube files:
- cubes/<entity_1>.yml         (cube name: <entity_1>)
- cubes/<bridge_entity>.yml    (cube name: <bridge_entity>, public: false)

Validated relationships:
- <entity_a>.<key> -> <entity_b>.<key> (<relationship_type>)

Measures:
- count
- <approved_measure_1>

Validation:
- dbt: <passed / pending / not run>
- physical tables: <passed / pending>
- join validation: <passed / pending>
- semantic validation: <passed / pending>

Unvalidated joins (tagged with # UNVALIDATED):
- <cube>.<join_target>: <reason>

Assumptions:
- <assumption>

Pending items:
- <pending_item>

Next step:
  revos apply

如果验证尚未完成,请准确说明还有哪些事项待处理。

评论

支持 Markdown