如何将变量解析为 dbt 中的源引用?
How to parse a variable as a source reference in dbt?
我正在构建一个模型,我在其中根据查询结果动态引用 table 名称和架构名称。
{%- set query %}
select * from master_data.event_metadata where game='{{game_name}}'
{% endset -%}
{%- set results = run_query(query) -%}
{%- if execute %}
{%- set record = results.rows[0] -%}
{% else %}
{%- set record = [] -%}
{% endif -%}
其中两个值在 record.SCHEMA_NAME
和 record.TABLE_NAME
中。我可以使用类似
的东西
select
*
from
{{record.SCHEMA_NAME}}.{{record.TABLE_NAME}}
但我宁愿使用 source()
函数,这样我的文档和 DAG 就会很干净。如何将 record.SCHEMA_NAME
和 record.TABLE_NAME
解析为字符串参数。我需要像
这样的东西
select
*
from
{{ source(record.SCHEMA_NAME, record.TABLE_NAME) }}
当我尝试 运行 以上时,出现以下错误:
Server error: Compilation Error in rpc request (from remote system)
The source name (first) argument to source() must be a string, got <class 'jinja2.runtime.Undefined'>
我认为您需要先将这两个对象转换为它们的字符串表示形式,然后再将它们传递给 source
宏。
试试这个
select
*
from
{{ source(record.SCHEMA_NAME|string, record.TABLE_NAME||string) }}
您可能已经找到了解决方法或解决方案,但以防万一其他人遇到同样的情况...
要将值转换为字符串,您可以使用 |string
。例如:
record.SCHEMA_NAME|string
record.TABLE_NAME|string
所以您的查询看起来像这样:
select * from {{ source(record.SCHEMA_NAME|string|lower, record.TABLE_NAME|string|lower) }}
请注意,根据您的查询输出和您定义源文件的方式,您可能必须 lower
或 upper
您的值才能与您的源相匹配。
问题
您的 record
变量是执行 (run_query(query)
) 的结果。当您执行 dbt compile/run
时,dbt 将执行一系列操作,例如读取项目的所有文件,生成一个“manifest.json”文件,并将使用 ref
/source
生成DAG所以在这一点上,没有SQL被执行,换句话说,execute == False
.
在您的示例中,即使您执行了 record.SCHEMA_NAME|string
,您也将无法检索该变量的值,因为没有执行任何操作,并且由于您执行了 if not execute then record = []
,您将收到该消息 ... depends on a source named '.' which was not found
,因为在那一点上,record
是空的。
解决方法是将模型的查询包装在 if execute
块中,如下所示:
{% if execute %}
select * from {{ source(record.TABLE_SCHEMA|string|lower, record.TABLE_NAME|string|lower) }}
{% endif %}
通过这种方法,您将能够动态设置模型的来源。
但不幸的是,这不会像您预期的那样工作,因为它不会为该模型生成 DAG。使用 if execute
块来包装模型的查询将阻止 dbt 为模型生成 DAG。
最后,这与您第一次尝试在没有 source
函数的情况下声明 schema
和 table
是一样的。
更多详细信息,您可以查看有关 execute mode
的 dbt 文档:
https://docs.getdbt.com/reference/dbt-jinja-functions/execute
我正在构建一个模型,我在其中根据查询结果动态引用 table 名称和架构名称。
{%- set query %}
select * from master_data.event_metadata where game='{{game_name}}'
{% endset -%}
{%- set results = run_query(query) -%}
{%- if execute %}
{%- set record = results.rows[0] -%}
{% else %}
{%- set record = [] -%}
{% endif -%}
其中两个值在 record.SCHEMA_NAME
和 record.TABLE_NAME
中。我可以使用类似
select
*
from
{{record.SCHEMA_NAME}}.{{record.TABLE_NAME}}
但我宁愿使用 source()
函数,这样我的文档和 DAG 就会很干净。如何将 record.SCHEMA_NAME
和 record.TABLE_NAME
解析为字符串参数。我需要像
select
*
from
{{ source(record.SCHEMA_NAME, record.TABLE_NAME) }}
当我尝试 运行 以上时,出现以下错误:
Server error: Compilation Error in rpc request (from remote system)
The source name (first) argument to source() must be a string, got <class 'jinja2.runtime.Undefined'>
我认为您需要先将这两个对象转换为它们的字符串表示形式,然后再将它们传递给 source
宏。
试试这个
select
*
from
{{ source(record.SCHEMA_NAME|string, record.TABLE_NAME||string) }}
您可能已经找到了解决方法或解决方案,但以防万一其他人遇到同样的情况...
要将值转换为字符串,您可以使用 |string
。例如:
record.SCHEMA_NAME|string
record.TABLE_NAME|string
所以您的查询看起来像这样:
select * from {{ source(record.SCHEMA_NAME|string|lower, record.TABLE_NAME|string|lower) }}
请注意,根据您的查询输出和您定义源文件的方式,您可能必须 lower
或 upper
您的值才能与您的源相匹配。
问题
您的 record
变量是执行 (run_query(query)
) 的结果。当您执行 dbt compile/run
时,dbt 将执行一系列操作,例如读取项目的所有文件,生成一个“manifest.json”文件,并将使用 ref
/source
生成DAG所以在这一点上,没有SQL被执行,换句话说,execute == False
.
在您的示例中,即使您执行了 record.SCHEMA_NAME|string
,您也将无法检索该变量的值,因为没有执行任何操作,并且由于您执行了 if not execute then record = []
,您将收到该消息 ... depends on a source named '.' which was not found
,因为在那一点上,record
是空的。
解决方法是将模型的查询包装在 if execute
块中,如下所示:
{% if execute %}
select * from {{ source(record.TABLE_SCHEMA|string|lower, record.TABLE_NAME|string|lower) }}
{% endif %}
通过这种方法,您将能够动态设置模型的来源。
但不幸的是,这不会像您预期的那样工作,因为它不会为该模型生成 DAG。使用 if execute
块来包装模型的查询将阻止 dbt 为模型生成 DAG。
最后,这与您第一次尝试在没有 source
函数的情况下声明 schema
和 table
是一样的。
更多详细信息,您可以查看有关 execute mode
的 dbt 文档:
https://docs.getdbt.com/reference/dbt-jinja-functions/execute