О функции ref
select * from {{ ref("node_name") }}
Определение
Эта функция:
- Возвращает Relation для модели, seed или snapshot
- Создает зависимости между ссылочным узлом и текущей моделью, что полезно для документации и выбора узлов
- Компилируется в полное имя объекта в базе данных
Самая важная функция в dbt — это ref()
; невозможно построить даже умеренно сложные модели без нее. ref()
— это способ ссылаться на одну модель внутри другой. Это очень распространенное поведение, так как обычно модели строятся так, чтобы "накладываться" друг на друга. Вот как это выглядит на практике:
select *
from public.raw_data
select *
from {{ref('model_a')}}
ref()
на самом деле выполняет две важные задачи. Во-первых, она интерполирует схему в ваш файл модели, чтобы вы могли изменить схему развертывания через конфигурацию. Во-вторых, она использует эти ссылки между моделями для автоматического построения графа зависимостей. Это позволит dbt развертывать модели в правильном порядке при использовании dbt run
.
Функция {{ ref }}
возвращает объект Relation
, который имеет те же атрибуты table
, schema
и name
, что и переменная {{ this }}.
- Примечание — До версии dbt v1.6, dbt Cloud IDE возвращает
request
как результат{{ ref.identifier }}
.
Продвинутое использование ref
Версионированный ref
Функция ref
поддерживает необязательный аргумент - version
(или v
).
Когда аргумент версии предоставляется функции ref
, dbt возвращает объект Relation
, соответствующий указанной версии ссылочной модели.
Эта функциональность полезна при ссылке на версионированные модели, которые вносят критические изменения, создавая новые версии, но гарантирует отсутствие критических изменений в существующих версиях модели.
Если аргумент version
не предоставлен для ref
версионированной модели, используется последняя версия. Это имеет преимущество автоматического включения последних изменений ссылочной модели, но существует риск включения критических изменений.
Пример:
models:
- name: model_name
latest_version: 2
versions:
- v: 2
- v: 1
-- возвращает объект `Relation`, соответствующий версии 1 model_name
select * from {{ ref('model_name', version=1) }}
-- возвращает объект `Relation`, соответствующий версии 2 (последней версии) model_name
select * from {{ ref('model_name') }}
Ссылка на модели из конкретных проектов
Вы также можете ссылаться на модели из разных проектов, используя двухаргументный вариант функции ref
. Указав как пространство имен (которое может быть проектом или пакетом), так и имя модели, вы обеспечиваете ясность и избегаете двусмысленности в ref
. Это также полезно при работе с моделями из различных проектов или пакетов.
При использовании двух аргументов с проектами (не пакетами) вам также нужно установить зависимости между проектами.
Следующий синтаксис демонстрирует, как ссылаться на модель из конкретного проекта или пакета:
select * from {{ ref('project_or_package', 'model_name') }}
Мы рекомендуем использовать двухаргументный ref
всякий раз, когда вы ссылаетесь на модель, определенную в другом пакете или проекте. Хотя это не требуется во всех случаях, это более явно для вас, для dbt и будущих читателей вашего кода.
Мы особенно рекомендуем использовать двухаргументный ref
, чтобы избежать двусмысленности в случаях, когда имя модели дублируется в нескольких проектах или установленных пакетах. Если вы используете одноаргументный ref
(только model_name
), dbt будет искать модель с таким именем в том же пространстве имен (пакет или проект); если он не найдет ни одной, он выдаст ошибку.
Примечание: project_or_package
должно совпадать с name
проекта/пакета, как определено в его dbt_project.yml
. Это может отличаться от имени репозитория. Оно никогда не включает имя организации репозитория. Например, если вы используете пакет fivetran/stripe
, имя пакета — stripe
, а не fivetran/stripe
.
Принудительные зависимости
В обычном использовании dbt знает правильный порядок выполнения всех моделей на основе использования функции ref
. Однако бывают случаи, когда dbt не знает, когда модель должна быть выполнена. Примером этого является случай, когда модель ссылается только на макрос. В этом случае dbt считает, что модель может быть выполнена первой, так как на этапе компиляции явные ссылки не создаются. Чтобы решить эту проблему, вы можете использовать SQL-комментарий вместе с функцией ref
— dbt поймет зависимость, и скомпилированный запрос все равно будет действительным:
-- depends_on: {{ ref('upstream_parent_model') }}
{{ your_macro('variable') }}
dbt увидит ref
и построит эту модель после указанной ссылки.
Другой пример — когда ссылка появляется внутри условного блока is_incremental()
. Это происходит потому, что макрос is_incremental()
всегда возвращает false
на этапе разбора, поэтому любые ссылки внутри него не могут быть выведены. Чтобы справиться с этим, вы можете и спользовать SQL-комментарий вне условного блока is_incremental()
:
-- depends_on: {{ source('raw', 'orders') }}
{% if is_incremental() %}
select * from {{ source('raw', 'orders') }}
{% endif %}