graph 컨텍스트 변수

graph 컨텍스트 변수

graph 컨텍스트 변수에는 dbt 프로젝트의 노드(node) 에 대한 정보가 들어 있어요. dbt 프로젝트에서 모델, 소스, 테스트, 스냅샷이 모두 노드의 예시랍니다. 이 변수는 파싱된 프로젝트 매니페스트를 바탕으로 노드들의 구조를 미리 파악할 때 유용해요.

출처: 문서

본문

graph 컨텍스트 변수

graph 컨텍스트 변수는 노드 id를 그 노드의 사전 표현(dictionary representation)으로 매핑하는 사전(dictionary)이에요. 간단한 예시는 다음과 같아요:

{
  "nodes": {
    "model.my_project.model_name": {
      "unique_id": "model.my_project.model_name",
      "config": {"materialized": "table", "sort": "id"},
      "tags": ["abc", "123"],
      "path": "models/path/to/model_name.sql",
      ...
    },
    ...
  },
  "sources": {
    "source.my_project.snowplow.event": {
      "unique_id": "source.my_project.snowplow.event",
      "database": "analytics",
      "schema": "analytics",
      "tags": ["abc", "123"],
      "path": "models/path/to/schema.yml",
      ...
    },
    ...
  },
  "exposures": {
    "exposure.my_project.traffic_dashboard": {
      "unique_id": "exposure.my_project.traffic_dashboard",
      "type": "dashboard",
      "maturity": "high",
      "path": "models/path/to/schema.yml",
      ...
    },
    ...
  },
  "metrics": {
    "metric.my_project.count_all_events": {
      "unique_id": "metric.my_project.count_all_events",
      "type": "count",
      "path": "models/path/to/schema.yml",
      ...
    },
    ...
  },
  "groups": {
    "group.my_project.finance": {
      "unique_id": "group.my_project.finance",
      "name": "finance",
      "owner": {
        "email": "[email protected]"
      }
      ...
    },
    ...
  }
}

모델·소스 노드에 대한 정확한 계약(contract)은 아직 문서화되지 않았지만, 앞으로 문서화될 예정이에요.

주의해요 — 파싱 단계에서 graph 변수가 만들어지기 때문에, dbt 프로젝트 실행 중 parsing phase 동안에는 graph 컨텍스트 변수의 일부 속성이 누락되거나 부정확할 수 있어요. 아래 내용을 꼼꼼히 읽고 이 변수를 효과적으로 사용하는 방법을 이해하세요.

모델에 접근하기

graph 사전의 model 항목은 파싱 중에는 불완전하거나 부정확할 수 있어요. graph 변수로 프로젝트의 모델에 접근한다면, 반드시 execute 플래그를 사용해 이 코드가 파싱 시점이 아니라 런타임에만 실행되도록 하세요. DAG를 만들 때 graph 변수를 쓰지 마세요. 그렇게 하면 dbt 동작이 정의되지 않고 아마도 부정확해질 거예요. 사용 예시:

graph-usage.sql


/*
  Print information about all of the models in the Snowplow package
*/

{% if execute %}
  {% for node in graph.nodes.values()
     | selectattr("resource_type", "equalto", "model")
     | selectattr("package_name", "equalto", "snowplow") %}
  
    {% do log(node.unique_id ~ ", materialized: " ~ node.config.materialized, info=true) %}
  
  {% endfor %}
{% endif %}

/*
  Example output
---------------------------------------------------------------
model.snowplow.snowplow_id_map, materialized: incremental
model.snowplow.snowplow_page_views, materialized: incremental
model.snowplow.snowplow_web_events, materialized: incremental
model.snowplow.snowplow_web_page_context, materialized: table
model.snowplow.snowplow_web_events_scroll_depth, materialized: incremental
model.snowplow.snowplow_web_events_time, materialized: incremental
model.snowplow.snowplow_web_events_internal_fixed, materialized: ephemeral
model.snowplow.snowplow_base_web_page_context, materialized: ephemeral
model.snowplow.snowplow_base_events, materialized: ephemeral
model.snowplow.snowplow_sessions_tmp, materialized: incremental
model.snowplow.snowplow_sessions, materialized: table
*/

소스에 접근하기

dbt 프로젝트의 소스에 프로그래밍 방식으로 접근하려면 graph 객체의 sources 속성을 사용하세요.

사용 예시:

models/events_unioned.sql

/*
  Union all of the Snowplow sources defined in the project
  which begin with the string "event_"
*/

{% set sources = [] -%}
{% for node in graph.sources.values() -%}
  {%- if node.name.startswith('event_') and node.source_name == 'snowplow' -%}
    {%- do sources.append(source(node.source_name, node.name)) -%}
  {%- endif -%}
{%- endfor %}

select * from (
  {%- for source in sources %}
    select * from {{ source }} {% if not loop.last %} union all {% endif %}
  {% endfor %}
)

/*
  Example compiled SQL
---------------------------------------------------------------
select * from (
  select * from raw.snowplow.event_add_to_cart union all
  select * from raw.snowplow.event_remove_from_cart union all
  select * from raw.snowplow.event_checkout
)
*/

exposure에 접근하기

dbt 프로젝트의 exposure에 프로그래밍 방식으로 접근하려면 graph 객체의 exposures 속성을 사용하세요.

사용 예시:

models/my_important_view_model.sql

{# Include a SQL comment naming all of the exposures that this model feeds into #}

{% set exposures = [] -%}
{% for exposure in graph.exposures.values() -%}
  {%- if model['unique_id'] in exposure.depends_on.nodes -%}
    {%- do exposures.append(exposure) -%}
  {%- endif -%}
{%- endfor %}

-- HELLO database administrator! Before dropping this view,
-- please be aware that doing so will affect:

{% for exposure in exposures %}
--   * {{ exposure.name }} ({{ exposure.type }})
{% endfor %}

/*
  Example compiled SQL
---------------------------------------------------------------
-- HELLO database administrator! Before dropping this view,
-- please be aware that doing so will affect:

--   * our_metrics (dashboard)
--   * my_sync (application)
*/

metric에 접근하기

dbt 프로젝트의 metric에 프로그래밍 방식으로 접근하려면 graph 객체의 metrics 속성을 사용하세요.

사용 예시:

macros/get_metric.sql

{% macro get_metric_sql_for(metric_name) %}

  {% set metrics = graph.metrics.values() %}
  
  {% set metric = (metrics | selectattr('name', 'equalto', metric_name) | list).pop() %}

  /* Elsewhere, I've defined a macro, get_metric_timeseries_sql, that will return 
     the SQL needed to perform a time-based rollup of this metric's calculation */

  {% set metric_sql = get_metric_timeseries_sql(
      relation = metric['model'],
      type = metric['type'],
      expression = metric['sql'],
      ...
  ) %}

  {{ return(metric_sql) }}

{% endmacro %}

group에 접근하기

dbt 프로젝트의 group에 프로그래밍 방식으로 접근하려면 graph 객체의 groups 속성을 사용하세요.

사용 예시:

macros/get_group.sql


{% macro get_group_owner_for(group_name) %}

  {% set groups = graph.groups.values() %}
  
  {% set owner = (groups | selectattr('owner', 'equalto', group_name) | list).pop() %}

  {{ return(owner) }}

{% endmacro %}

더 알아보기 (Learn more)

  • graph 변수는 주로 execute 플래그와 함께 써서 런타임에만 안전하게 접근해요.
  • 관련 개념: execute 컨텍스트 변수, 모델·소스·exposure·metric 정의 문서.