构建DBT宏清理URL数值:模型调用失效问题求助
问题:DBT宏调用时无法正确处理URL字段,返回字符串字面量
需求背景
需要构建DBT宏移除URL中包含数值的片段,示例:
- 输入:
cats.com/232/dryfood/3333 - 输出:
cats.com/dryfood
数值在URL中的位置不固定,可能在中间或末尾。
现有问题
原宏逻辑为:按/分割URL为列表,遍历移除含数值的片段后拼接。输入具体字符串时运行正常,但在DBT模型中调用url_cleaner('url')时,返回的是字符串'url'而非字段对应的处理后URL。
原宏代码:
{%- set new_url = [] -%} {%- set url_chunks = url.split('/') -%} {%- for chunk in url_chunks -%} {%- if modules.re.match('^([^0-9]*)$', chunk) -%} {%- do new_url.append( chunk )-%} {%- endif -%} {%- endfor -%} '{{ new_url|join("/") }}' as cleansed {% endmacro %}
错误原因
- 调用宏时将字段名用单引号包裹,宏会把
'url'当成编译阶段的字符串字面量处理,而非引用数据表中的字段。 - 原宏是在DBT编译阶段用Python处理字符串,无法生成能在SQL运行时逐行处理字段值的逻辑。
修正方案
需要让宏生成数据仓库原生的SQL表达式,在SQL运行时处理每一行的URL字段。以下是针对不同仓库的实现:
适配Snowflake/BigQuery等支持数组函数的仓库
修正后的宏:
{% macro url_cleaner(url_col) %} ARRAY_TO_STRING( ARRAY_FILTER( SPLIT({{ url_col }}, '/'), chunk -> NOT REGEXP_LIKE(chunk, '\\d') ), '/' ) AS cleansed {% endmacro %}
正确调用方式(字段名不带单引号):
SELECT url, {{ url_cleaner('url') }} FROM {{ ref('website_model') }}
适配PostgreSQL
{% macro url_cleaner(url_col) %} ARRAY_TO_STRING( ARRAY( SELECT elem FROM unnest(string_to_array({{ url_col }}, '/')) AS elem WHERE elem !~ '\\d' ), '/' ) AS cleansed {% endmacro %}
调用方式同上:
SELECT url, {{ url_cleaner('url') }} FROM {{ ref('website_model') }}
说明
- 修正后的宏通过生成SQL数组、过滤、拼接函数,让数据仓库在运行时处理每一行的URL字段
- 调用时直接传入字段名字符串(无需单引号),宏会将其转换为SQL中的字段引用
内容的提问来源于stack exchange,提问作者Lianne Girard
相关产品推荐
相关产品推荐

