ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Lightdash Jaffle Shop 演示 dbt 项目解析:跨仓库兼容的测试模型、Lightdash 元数据与常见故障排查

Lightdash Jaffle Shop 演示 dbt 项目解析:跨仓库兼容的测试模型、Lightdash 元数据与常见故障排查 Lightdash Jaffle Shop 演示 dbt 项目解析跨仓库兼容的测试模型、Lightdash 元数据与常见故障排查【免费下载链接】lightdashAgentic BI. Analytics at the speed of code ⚡️项目地址: https://gitcode.com/GitHub_Trending/li/lightdash本文基于 Lightdash 仓库中examples/full-jaffle-shop-demo/dbt/目录下的项目说明文档展开讲解这个用于全面测试 Lightdash 功能的 dbt 演示项目从 CSV 种子数据、模型建模规范、Lightdash 参数/Spotlight 集成到通过 Jinja 宏实现 PostgreSQL / Snowflake / BigQuery / Trino / Athena 多仓库兼容的完整方案。读完后你可以直接复用该项目的模型编写模式与类型转换宏在自己的多仓库 dbt 项目中避免 SQL 方言差异问题。项目定位一个面向 Lightdash 功能测试的 dbt 项目该项目的官方定位见 CLAUDE.md是基于经典 jaffle shop 演示数据并额外增加了一批模型用于全面测试 Lightdash 功能。它不是一个通用电商教程而是一个自包含的测试游乐场playground——Lightdash 的维度、指标、参数、Spotlight、跨表关联、跨仓库 SQL 方言等能力都在这个项目的模型上得到验证。与 dbt/README.md 中说明的经典 jaffle_shop 不同这个增强版项目刻意包含了一些真实测试场景需要的内容种子seeds代替 sources让项目自包含、可离线运行覆盖多图表类型、多时间类型、多参数组合的模型通过 dbt_project.yml 中的meta.group_label把模型分组到 Lightdash Catalog 的分组标签fanouts、campaigns、healthcare、funnels、maps 等便于在 Lightdash 中按业务域组织。项目目录结构如下examples/full-jaffle-shop-demo/ ├── dbt/ # dbt 项目根目录 │ ├── data/ # 所有原始 CSV 种子数据 │ │ ├── raw_customers.csv │ │ ├── raw_orders.csv │ │ ├── raw_payments.csv │ │ ├── raw_subscriptions.csv │ │ ├── raw_plan.csv │ │ └── seeds.yml # 种子列类型声明跨仓库兼容关键 │ ├── macros/ │ │ └── casts.sql # 跨仓库类型转换/日期宏 │ ├── models/ # .sql 模型 .yml 模式定义 │ ├── dbt_project.yml │ └── lightdash.config.yml # 全局参数与 Spotlight 配置 ├── profiles/profiles.yml # dbt 连接配置 ├── docker-compose.yml # 本地 Postgres 环境 └── entrypoint.sh数据源CSV 种子与 git add -f 注意事项所有原始数据来自data/目录下的 CSV 文件文档明确列出的核心种子包括文件内容raw_customers.csv客户信息raw_orders.csv订单交易raw_payments.csv支付记录raw_subscriptions.csv订阅数据1000 条记录raw_plan.csv订阅套餐定义重要约定向该目录新增数据文件时必须使用git add -f filename因为这些文件通常被 gitignore 忽略。这一点在文档的 Troubleshooting 一节中再次强调——任何data/目录下的新数据文件都要用git add -f提交否则克隆仓库的人拿不到原始数据模型无法运行。实际的data/目录远不止这 5 个文件从目录清单可见还有raw_events.csv、raw_product_events.csv、raw_timezone_test.csv、raw_geo.csv以及fanout_data/子目录等数十个 CSV对应文档所述额外模型用于全面测试。种子加载时列类型并非自动推断而是由 data/seeds.yml 与 dbt_project.yml 共同声明。例如dbt_project.yml中为raw_orders声明了order_date: date、shipping_cost: numeric等类型而seeds.yml则用 Jinja 条件表达式处理仓库差异典型写法如下- name: raw_product_events config: column_types: event_properties: - {%- if target.type snowflake -%} variant {%- elif target.type in [athena, trino, duckdb, clickhouse] -%} varchar {%- else -%} jsonb {%- endif -%}raw_timezone_test种子更进一步为同一逻辑列声明了时区感知/非时区感知的多种类型映射Snowflake 用timestamp_tz/timestamp_ntzClickHouse 用DateTime64(3, UTC)Trino/Athena 用timestamp with time zone其余默认timestamptz可见该项目同时承担了 Lightdash 时间类型处理功能的测试载体角色。模型模式CTE、别名、描述与测试文档Model Patterns一节规定了该项目遵循的建模规范.sql文件包含模型逻辑带 CTE 的 SELECT 语句.yml文件包含模式定义、测试与 Lightdash 元数据使用 CTEwith语句编写可读 SQL多表连接时使用规范的表别名同时包含原始维度与计算字段为业务用户编写完整的字段描述。以 models/customers.sql 为例可以看到标准写法customers、orders、payments三个 CTE 分别引用 staging 层模型再用customer_orders、customer_payments聚合出终身指标首单/最近订单日期、订单数、累计支付额。值得一提的是该文件内还内嵌了一处仓库方言分支——注释写明 Athena/Trino: USING joins create unqualified columns, cant reference as table.col并通过{% if target.type trino or target.type athena %}切换列引用方式这正是后文Athena 限制 5在真实模型中的落地。文档点名的四个核心模型customers.sql/.yml— 客户维度表含终身指标lifetime metricsorders.sql/.yml— 订单事实表含订单级计算subscriptions.sql/.yml— 订阅模型含真实感 SaaS 指标与参数plan.sql/.yml— 订阅套餐维度表。测试约定包括主键上的unique与not_null测试、业务逻辑自定义测试、事实表与维度表之间的relationships测试。subscriptions.yml 中即可看到subscription_id列同时挂了unique和not_null测试。Lightdash 集成参数、Spotlight 与模型元数据Lightdash 与 dbt 项目的集成点分两层见 lightdash.config.yml第一层全局配置lightdash.config.yml包含三块spotlight定义 Spotlight 分类及其颜色。示例项目中定义了coreCore Metrics, blue、experimentalExperimental Metrics, orange、salesSales, green、revenue_growthRevenue Growth, violet四个分类default_visibility: show控制默认可见性。parameters声明项目级参数被维度/指标的 SQL 以${ld.parameters.name}引用。该文件覆盖了多种参数形态是理解 Lightdash 参数系统的良好样本subscription_statusoptions_from_dimension从subscriptions模型的subscription_status维度动态取选项min_duration_months带allow_custom_values: true和显式选项列表的数值参数plan_typemultiple: true的多选参数选项来自plan模型的plan_name维度time_zoom/metric_type控制 MRR 计算周期与计数 vs 收入切换date_dim_parameter/date_custom_parametertype: date的日期参数前者选项来自orders.order_date维度后者允许自定义输入date_granularity驱动 Liquid 模板演示的动态粒度参数。custom_granularities自定义时间粒度示例包含fiscal_quarter财务季度用EXTRACTINTERVAL 3 months拼接出FYxxxx-Qn字符串与biweekly双周用FLOOR(EXTRACT(EPOCH FROM ...) / 1209600)按 14 天对齐。第二层模型 YML 的config.meta维度、指标与连接全部声明在 YAML 中。以subscriptions.yml为例config.meta下的joins定义了三种连接config: meta: primary_key: subscription_id joins: - join: customers sql_on: ${customers.customer_id} ${subscriptions.customer_id} relationship: many-to-one - join: plan sql_on: ${plan.id} ${subscriptions.plan_id} relationship: many-to-one - join: orders sql_on: ${customers.customer_id} ${orders.customer_id} relationship: one-to-many各列的meta.dimension类型、time_intervals、colors、format与meta.metricscount_distinct、sum、average等聚合类型及format如$#,##0.00、percent共同构成 Lightdash Catalog 的可视化元数据。subscriptions模型还演示了参数驱动的动态 SQL例如按time_zoom参数在weekly_mrr/monthly_mrr/quarterly_mrr之间切换的conditional_mrr_total指标以及按状态/时长/套餐组合过滤的combined_filter_count指标。plan.yml 则展示了additional_dimensions从metadataJSON 列派生created_by维度再级联派生created_by_first_name/created_by_last_nameSPLIT_PART(${created_by}, , 1)说明维度可以引用同模型内其他维度的派生列。数据生成与 MRR 口径文档Data Generation一节说明订阅数据的构造方式订阅套餐分布采用加权抽样40% free、37% silver、14% gold、8% platinum、2% diamond订阅时长采用现实感模式多样的订阅长度MRR 按套餐层级计算。从 models/subscriptions.sql 源码可以看到落地实现plan_id1–5 分别映射到 9.99 / 19.99 / 39.99 / 79.99 / 149.99 美元的monthly_mrr并按* 12 / 52与* 3推导weekly_mrr、quarterly_mrr同时计算duration_days、duration_months天数除以 30 的近似月数、subscription_statusCurrent / Expired / Cancelled 三态与months_remaining。模型本身只依赖raw_subscriptions种子与plan模型的左连接全部时间运算都走下文的跨仓库宏。常用命令文档给出的标准开发命令注意--profiles-dir ../profiles/指向 demo 根目录下的 profiles/profiles.yml其中连接信息通过PGHOST、PGPORT、PGUSER、PGPASSWORD、PGDATABASE等环境变量注入目标 schema 默认为jaffle# 运行全部模型 dbt run --profiles-dir ../profiles/ # 运行指定模型 dbt run --select subscriptions --profiles-dir ../profiles/ # 编译查看生成的 SQL dbt compile --select subscriptions --profiles-dir ../profiles/ # 运行测试 dbt test --profiles-dir ../profiles/其中dbt compile是排查 Lightdash 维度不显示问题的第一手段编译产物直接体现宏展开后的目标方言 SQL。跨仓库兼容Jinja 类型转换宏项目通过 Jinja 宏屏蔽 PostgreSQL 的::type语法与其他仓库CAST(col AS TYPE)语法的差异。macros/casts.sql 中每个宏都按target.type分两支Trino/Athena 走标准CAST其余仓库PostgreSQL、Snowflake、BigQuery 等走::缩写。类型转换宏宏PostgreSQLAthena/Trino备注cast_numeric(col)col::numericCAST(col AS DOUBLE)cast_float(col)col::floatCAST(col AS DOUBLE)cast_decimal(col)col::decimalCAST(col AS DOUBLE)cast_integer(col)col::integerCAST(col AS INTEGER)cast_boolean(col)col::booleanCAST(col AS BOOLEAN)cast_date(col)col::dateCAST(col AS DATE)cast_timestamp(col)col::timestampCAST(col AS TIMESTAMP)cast_time(col)col::timeCAST(col AS VARCHAR)Athena 不支持 TIME 类型cast_json(col)col::jsonCAST(col AS JSON)日期/时间辅助宏宏PostgreSQLAthena/Trino备注date_diff_days(d1, d2)d1::date - d2::dateDATE_DIFF(day, d2, d1)两日期相差天数timestamp_diff_days(t1, t2)EXTRACT(day FROM t1 - t2)DATE_DIFF(day, t2, t1)age_years(date_col)date_part(year, age(...))DATE_DIFF(year, col, CURRENT_DATE)年龄年JSON 提取宏PostgreSQLAthena/Trinojson_extract_string(col, key)col::json-keyJSON_EXTRACT_SCALAR(col, $.key)对照 casts.sql 源码可以看到两处细节与文档表格略有差异值得注意json_extract_string的 PostgreSQL 分支实际生成(col-key)源码注释说明该写法对json与jsonb均有效且额外加了括号以保证对结果做类型转换时运算符优先级正确文件末尾还有一个unsupported(feature_name)宏在 Trino/Athena 下直接渲染为NULL并保留特性名注释其他仓库下通过caller()渲染调用方传入的 SQL 片段——这是为目标方言完全不支持某特性预留的降级占位符。种子列类型与 Athena 兼容性文档强调部分种子必须显式声明列类型以兼容 Athena核心规则jsonb 列Athena 不支持 jsonb声明为varchartime 列Hive metastore 不支持 TIME声明为varcharnumeric 列声明为double避免对小数值的 INT 转换错误date 列Athena 只接受 ISO 格式YYYY-MM-DD不能是 Jan 1, 2024 这类人类可读格式。seeds.yml中的实际例子与文档一致例如raw_generated的time列写作{{ varchar if target.type in [athena, duckdb] else time }}并附注释说明 DuckDB 同样无法自动解析 7:01 AM 格式。Athena 专项限制清单文档整理了 8 条 Athena 限制及对应替代方案是多仓库 dbt 开发中复用价值最高的部分不支持::转换语法— 通过宏使用CAST(col AS TYPE)无 TIME 类型— 用 VARCHAR 存时间字符串无 jsonb 类型— 用 VARCHAR 存储再用 JSON 函数解析无numeric类型— 使用 DOUBLE 或 DECIMAL(p,s)USING 连接后不能使用带表限定的列—JOIN ... USING (col)之后必须写不带限定的col不能写table.colcustomers.sql中即为此做了分支无DISTINCT ON— 改用子查询中ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...)WHERE rn 1无string_agg— 改用array_join(array_agg(distinct col), , )日期/时间行为差异逐项替代日期只接受 ISO 格式YYYY-MM-DD不接受 Jan 1, 2024无age()函数 — 用DATE_DIFF(year, date_col, CURRENT_DATE)日期相减不返回整数返回 INTERVAL— 用DATE_DIFF(day, start_date, end_date)不支持date_col 30整数加减 — 用DATE_ADD(day, 30, date_col)不支持 timestamp 与 varchar 隐式比较 — 用TIMESTAMP 2024-12-31 11:52:45字面量区间语法不同interval 90 days不可用 — 用DATE_ADD(day, 90, date_col)无EXTRACT(epoch FROM ...)— 用DATE_DIFF(second, start, end)取秒数无to_char— 用date_format(date, %W)取星期名、date_format(date, %Y-%m-%d)做格式化。故障排查文档 Troubleshooting 一节给出三条排查路径Lightdash 维度不显示— 先检查该列是否存在于编译后的 SQL 中dbt compile --select model --profiles-dir ../profiles/宏分支或种子类型声明错误都会让列在目标仓库中缺失跨表引用失败— 确保连接存在于 SQL 模型中而不仅仅是 YAML 声明YAML 的joins需要底层模型 SQL 真的产出了相应连接关系新增数据文件不生效— 对data/下的新文件执行git add -f后再提交。小结这个演示项目把如何用 dbt 项目全面支撑一个 BI 产品浓缩在一个可运行样本里CSV 种子保证自包含可复现dbt_project.yml与seeds.yml的column_types处理类型声明与方言差异macros/casts.sql用统一的宏接口抹平 PostgreSQL 与其他仓库的语法鸿沟lightdash.config.yml加模型 YML 的config.meta完成维度/指标/参数/Spotlight 的声明式集成dbt compile与三条排查原则构成调试闭环。若要扩展该项目文档给出的边界也很清楚新增 CSV 数据必须git add -fSQL 方言差异必须经由宏而非直接内联方言语法解决。【免费下载链接】lightdashAgentic BI. Analytics at the speed of code ⚡️项目地址: https://gitcode.com/GitHub_Trending/li/lightdash创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表