Une référence de traduction entre les concepts Dataform et dbt. La plupart des concepts ont des équivalents directs. La syntaxe change ; l’intention, non.
Équivalents syntaxiques directs
| Dataform | dbt | Notes |
|---|---|---|
${ref("model")} | {{ ref('model') }} | Même référence pour la construction du DAG |
config { type: "table" } | {{ config(materialized='table') }} | Déclaration de matérialisation |
config { type: "view" } | {{ config(materialized='view') }} | Défaut dans les deux outils |
config { type: "incremental" } | {{ config(materialized='incremental') }} | Voir Modèles incrémentaux dans dbt |
${self()} | {{ this }} | Référence à la table du modèle courant |
${when(incremental(), ...)} | {% if is_incremental() %} ... {% endif %} | Logique incrémentale conditionnelle |
Fichiers .sqlx | Fichiers .sql | Extension de fichier |
definitions/ | models/ | Répertoire des modèles |
includes/ | macros/ | Répertoire du code réutilisable |
dataform.json | dbt_project.yml | Configuration du projet |
Déclarations de sources
C’est là que les outils commencent à diverger. Dataform utilise des fichiers de déclaration JavaScript. dbt utilise des définitions de sources YAML qui regroupent documentation et vérifications de fraîcheur au même endroit.
Dataform :
declare({ database: "my-project", schema: "analytics_123456789", name: "events_*"});dbt :
sources: - name: ga4 database: my-project schema: analytics_123456789 tables: - name: events identifier: "events_*" freshness: warn_after: {count: 24, period: hour} description: "Export d'événements GA4 bruts"La version dbt ajoute la surveillance de la fraîcheur et la documentation dans le même fichier. Dans Dataform, les vérifications de fraîcheur nécessitent une implémentation séparée. La fonction {{ source('ga4', 'events') }} dans dbt remplace ${ref("analytics_123456789", "events_*")} dans Dataform.
Traduction des blocs de configuration
Les blocs de configuration JavaScript de Dataform correspondent aux blocs de configuration Jinja de dbt. Les noms de propriétés changent légèrement.
Dataform :
config { type: "table", schema: "reporting", assertions: { uniqueKey: ["customer_id"], nonNull: ["customer_id", "email"] }}dbt divise cela en un bloc de configuration et un fichier de tests YAML :
{{ config( materialized='table', schema='reporting') }}models: - name: mrt__sales__customers columns: - name: customer_id tests: - unique - not_null - name: email tests: - not_nullCette séparation est intentionnelle. dbt traite les tests comme des objets de première classe avec leur propre exécution et reporting, plutôt que comme des annotations en ligne. Voir Taxonomie des tests dbt pour le modèle de test complet.
Traduction des modèles incrémentaux
La syntaxe incrémentale change significativement. Dataform utilise ${when(incremental(), ...)} pour les blocs conditionnels. dbt utilise {% if is_incremental() %}.
Dataform :
config { type: "incremental", uniqueKey: ["event_id"], updatePartitionFilter: "event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY)"}
SELECT event_id, event_date, event_nameFROM ${ref("base_events")}${when(incremental(), `WHERE event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY)`)}dbt :
{{ config( materialized='incremental', unique_key='event_id', partition_by={ 'field': 'event_date', 'data_type': 'date' }, incremental_strategy='merge') }}
SELECT event_id, event_date, event_nameFROM {{ ref('base__ga4__events') }}{% if is_incremental() %}WHERE event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY){% endif %}Différences clés : dbt requiert un partition_by explicite pour les tables partitionnées BigQuery. L’incremental_strategy est par défaut merge sur BigQuery, mais le rendre explicite améliore la lisibilité. L’updatePartitionFilter de Dataform devient directement partie de votre logique de clause WHERE. Voir Modèles incrémentaux dans dbt pour les détails des stratégies.
Pre/post operations vers hooks
Les pre_operations et post_operations de Dataform correspondent aux pre_hook et post_hook de dbt :
Dataform :
config { type: "table", pre_operations: ["DELETE FROM ${self()} WHERE date < DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)"]}dbt :
{{ config( materialized='table', pre_hook="DELETE FROM {{ this }} WHERE date < DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)") }}Pour les opérations multi-instructions complexes, dbt prend en charge des listes de hooks ou des matérialisations personnalisées. Voir Macros dbt pour les patterns de macros qui remplacent les includes JavaScript de Dataform.
Correspondance de la structure des répertoires
Dataform organise par système source. Les conventions dbt organisent par couche de transformation :
# Dataform # dbtdefinitions/ models/ sources/ base/ staging/ intermediate/ reporting/ marts/includes/ macros/dataform.json dbt_project.ymlLa couche base/ remplace sources/ et le premier staging/. La couche intermediate/ gère les jointures et l’enrichissement. La couche marts/ remplace reporting/. Voir Structure et nommage du projet dbt pour les conventions de nommage détaillées.
Fonctionnalités sans équivalents directs
Certaines capacités existent dans un outil mais pas dans l’autre.
dbt possède, Dataform manque :
- Seeds — Fichiers CSV qui se chargent comme tables en entrepôt. Utiles pour les tables de mapping, les fixtures de test et les données de référence.
- Snapshots — Suivi SCD Type 2 intégré. Voir SCD Type 2 avec les snapshots dbt. Dans Dataform, on le construit manuellement.
- Écosystème de packages — Plus de 200 packages communautaires via le dbt Hub. Dataform n’a pas de système de packages.
- Vérifications de fraîcheur des sources — Surveillance native de la péremption des tables sources.
Dataform possède, dbt manque :
- JavaScript natif — Génération de modèles programmatique complète. Voir JavaScript vs Jinja en analytics engineering pour les implications.
- Tier gratuit sur BigQuery — Aucun coût de licence pour une utilisation BigQuery uniquement.
- Planification intégrée — Intégré avec Google Cloud sans orchestration externe.
Ces écarts conduisent la décision de migration plus que les différences syntaxiques.