Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 31

Création de Workflow ETL : Lecture, Transformation, Écriture en Base de Données

Recommended resources

Bonjour !

Dans la leçon précédente, vous avez brillamment mis en place une micro-API pour créer des enregistrements dans une base de données via un webhook. C'était une excellente introduction à l'écriture de données (Load) dans un contexte transactionnel.

Aujourd'hui, nous allons nous attaquer à un autre pilier de l'automatisation de données : le pipeline ETL (Extract, Transform, Load). C'est un processus fondamental en informatique, utilisé pour la migration de données, la préparation de rapports, ou l'alimentation d'entrepôts de données (data warehouses).

Objectif de la leçon : Construire un workflow qui lit des enregistrements depuis une base de données, les transforme, puis écrit les résultats dans une autre table.

À la fin de cette leçon, vous saurez comment orchestrer un flux de données complet, de l'extraction à l'écriture, en passant par une étape de transformation sur mesure.


1. Préparation de l'Environnement : Deux Tables pour un Pipeline

Pour notre exercice ETL, nous avons besoin d'une source et d'une destination. Nous allons donc créer deux tables dans une base de données PostgreSQL.

Pourquoi PostgreSQL ? C'est une base de données open-source extrêmement puissante et populaire, un excellent ajout à vos compétences. Pour la mettre en place rapidement et gratuitement, nous utiliserons Supabase.

La vidéo suivante, en français, vous montre comment créer un projet sur Supabase et trouver les informations nécessaires pour connecter n8n.

Comment Configurer Supabase et Postgres sur n8n pour un Agent IA RAG (Tutoriel Complet)

Pour cet exercice, nous allons utiliser une base de données PostgreSQL. Supabase offre une instance gratuite et facile à configurer. Cette vidéo vous guidera pas à pas pour créer un projet Supabase et obtenir les informations de connexion nécessaires pour n8n.

Regardez la partie de 01:34 à 04:29. Suivez les étapes pour vous inscrire sur Supabase, créer un nouveau projet, et trouver les informations de connexion à la base de données (Host, Port, Database, User, et Password) dans la section Project Settings > Database. Vous pouvez mettre la vidéo en pause une fois que vous avez ces informations.

Une fois que vous avez vos identifiants Supabase :

  1. Dans n8n, créez de nouveaux credentials de type Postgres. Remplissez les champs avec les informations de Supabase. Pour le port, utilisez bien celui indiqué dans Supabase (souvent 5432 ou 6543 pour le pooler). Activez SSL.
  2. Allez dans l'éditeur SQL de votre projet Supabase (SQL Editor).
  3. Copiez et exécutez le script SQL ci-dessous. Il créera nos deux tables, raw_users (la source) et processed_users (la destination), et insérera des données de test dans la première.
-- Table source avec des données brutes
CREATE TABLE raw_users (
    id SERIAL PRIMARY KEY,
    first_name VARCHAR(50),
    last_name VARCHAR(50),
    email VARCHAR(100),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Table de destination pour les données transformées
CREATE TABLE processed_users (
    id SERIAL PRIMARY KEY,
    full_name VARCHAR(101),
    domain VARCHAR(100),
    processed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Insertion de données de test dans la table source
INSERT INTO raw_users (first_name, last_name, email) VALUES
('charles', 'LECLERC', 'charles.leclerc@ferrari.com'),
('Max', 'verstappen', 'max@redbullracing.com'),
('lewis', 'hamilton', 'sir.lewis@mercedes.com');

Après avoir exécuté le script, vous pouvez vérifier que les données sont bien présentes en exécutant SELECT * FROM raw_users;. Vous devriez voir les 3 enregistrements.



2. Exercice : Construction du Pipeline ETL

Notre workflow suivra trois étapes claires : Extraire, Transformer, Charger.

Étape 1 : Extract - Lire les Données Brutes

  1. Créez un nouveau workflow dans n8n.
  2. Supprimez le nœud Start et ajoutez un déclencheur manuel (nœud Manual Trigger). Cela nous permettra de lancer le workflow à la demande.
  3. Ajoutez un nœud Postgres.
  4. Configurez-le :
    • Credential: Sélectionnez les identifiants Supabase que vous venez de créer.
    • Operation: Execute Query.
    • Query: Entrez la requête SELECT * FROM raw_users;.
  5. Exécutez ce nœud seul (Execute node). Vous devriez voir en sortie la liste des 3 utilisateurs de votre table raw_users.

Étape 2 : Transform - Nettoyer et Enrichir les Données avec le Nœud Code

C'est ici que nous ajoutons de la valeur. Nous allons transformer les données brutes en un format propre et structuré. Pour une flexibilité maximale, nous utiliserons le nœud Code.

Pour comprendre la syntaxe de base de ce nœud, la documentation officielle est votre meilleure alliée.

Understanding the data structure - n8n Docs

Le nœud 'Code' permet d'écrire du JavaScript pour manipuler les données. Cette lecture vous expliquera comment accéder aux données des nœuds précédents et comment formater la sortie pour les nœuds suivants.

Lisez les sections 'Referencing node data with the Code node' et 'Transforming data'. Concentrez-vous sur la manière de lire les données en entrée (par exemple, avec $input.all()) et de retourner un nouveau tableau d'objets.

Maintenant, appliquons ces concepts.

  1. Ajoutez un nœud Code après le nœud Postgres.

  2. Copiez-collez le code JavaScript suivant. Lisez les commentaires pour bien comprendre la logique de transformation.

    // Récupère tous les items (lignes de la BDD) en entrée
    const items = $input.all();
    const transformedItems = [];
    
    // Boucle sur chaque item pour le transformer
    for (const item of items) {
        const firstName = item.json.first_name;
        const lastName = item.json.last_name;
        const email = item.json.email;
        
        // Met en majuscule la première lettre du prénom et du nom, et le reste en minuscule
        const formattedFirstName = firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase();
        const formattedLastName = lastName.charAt(0).toUpperCase() + lastName.slice(1).toLowerCase();
    
        // Ajoute l'item transformé au tableau de résultats
        transformedItems.push({
            json: {
                // Crée un champ 'full_name' en concaténant prénom et nom
                full_name: `${formattedFirstName} ${formattedLastName}`,
                // Extrait le nom de domaine de l'email
                domain: email.substring(email.indexOf('@') + 1)
            }
        });
    }
    
    // Retourne le tableau des items transformés
    return transformedItems;
    
  3. Exécutez le workflow jusqu'au nœud Code. La sortie doit être un tableau de 3 objets JSON, chacun avec les champs full_name et domain correctement formatés.

Étape 3 : Load - Écrire les Données Transformées

La dernière étape consiste à insérer ces nouvelles données propres dans notre table de destination.

  1. Ajoutez un autre nœud Postgres après le nœud Code.
  2. Configurez-le :
    • Credential: Le même que précédemment.
    • Operation: Insert.
    • Table: processed_users.
    • Columns: Mappez les colonnes en utilisant les données du nœud Code.
      • DB Column Name: full_name → Value: {{ $json.full_name }}
      • DB Column Name: domain → Value: {{ $json.domain }}

n8n va automatiquement itérer sur chaque item reçu du nœud Code et exécuter une commande INSERT pour chacun.

n8n Workflow for MySQL and Pipedrive Data Synchronization
Ce workflow, bien que plus complexe et synchronisant MySQL avec un CRM, illustre bien le concept de lecture (Read), transformation (Compare/Set) et écriture (Create/Update) que nous mettons en œuvre.


3. Test final et Validation

Votre workflow complet devrait ressembler à : Manual Trigger → Postgres (SELECT) → Code → Postgres (INSERT).

  1. Cliquez sur Execute Workflow en haut de l'écran pour lancer le pipeline complet.
  2. Tous les nœuds devraient s'exécuter avec succès.
  3. Retournez dans l'éditeur SQL de Supabase et exécutez la requête :
    SELECT * FROM processed_users;
    
  4. Résultat attendu : La table processed_users contient maintenant 3 enregistrements avec des noms complets bien formatés et les domaines extraits.


4. Solution et Contexte Réel

Vous venez de créer un pipeline ETL fonctionnel. Dans le monde professionnel, ce type de workflow est extrêmement courant. L'article ci-dessous (en anglais) présente un cas d'usage très similaire : extraire des données d'une base, les transformer avec un nœud Code pour générer un rapport HTML, puis l'envoyer par e-mail.

Automate SQL Workflows with n8n

Ce que nous venons de construire est la base de nombreux processus de reporting. Cet article illustre parfaitement comment étendre notre pattern 'Lire -> Transformer' pour produire un résultat directement exploitable, comme un rapport HTML.

Parcourez les sections 'Technical Deep Dive' qui expliquent la logique de la requête SQL ('SQL Query Logic') et la transformation en HTML ('HTML Generation Logic'). Cela renforce l'idée que le nœud 'Code' est un outil de transformation puissant et polyvalent.

Pour référence, voici le JSON de la solution complète de notre exercice. Vous pouvez l'importer dans n8n pour comparer avec votre travail.

{
  "name": "ETL Pipeline - Raw to Processed Users",
  "nodes": [
    {
      "parameters": {},
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        840,
        340
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT * FROM raw_users;",
        "options": {}
      },
      "name": "Postgres (SELECT)",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.2,
      "position": [
        1060,
        340
      ],
      "credentials": {
        "postgres": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "Supabase Postgres"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\nconst transformedItems = [];\n\nfor (const item of items) {\n    const firstName = item.json.first_name;\n    const lastName = item.json.last_name;\n    const email = item.json.email;\n    \n    const formattedFirstName = firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase();\n    const formattedLastName = lastName.charAt(0).toUpperCase() + lastName.slice(1).toLowerCase();\n\ntransformedItems.push({\n        json: {\n            full_name: `${formattedFirstName} ${formattedLastName}`,\n            domain: email.substring(email.indexOf('@') + 1)\n        }\n    });\n}\n\nreturn transformedItems;"
      },
      "name": "Code (Transform)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 1,
      "position": [
        1280,
        340
      ]
    },
    {
      "parameters": {
        "table": "processed_users",
        "columns": {
          "column": [
            {
              "column": "full_name",
              "value": "={{$json.full_name}}"
            },
            {
              "column": "domain",
              "value": "={{$json.domain}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Postgres (INSERT)",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.2,
      "position": [
        1500,
        340
      ],
      "credentials": {
        "postgres": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "Supabase Postgres"
        }
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Postgres (SELECT)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres (SELECT)": {
      "main": [
        [
          {
            "node": "Code (Transform)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code (Transform)": {
      "main": [
        [
          {
            "node": "Postgres (INSERT)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}


Conclusion

Félicitations ! Vous maîtrisez maintenant le pattern ETL, l'une des compétences les plus précieuses en automatisation et en gestion de données.

Points clés à retenir :

  • Le pattern Extract-Transform-Load (ETL) est un concept central que n8n modélise parfaitement.
  • Il est simple d'orchestrer des lectures (SELECT) et des écritures (INSERT) vers une ou plusieurs bases de données dans un même flux.
  • Le nœud Code offre une puissance et une flexibilité inégalées pour les transformations de données complexes, un atout majeur pour un profil technique comme le vôtre.
  • L'utilisation d'une base de données comme PostgreSQL via un service comme Supabase est une pratique moderne et efficace.

Dans le prochain module, nous allons changer de décor. Après avoir exploré en profondeur les bases de données, nous nous tournerons vers le monde extérieur : les APIs et les services web. La prochaine leçon vous apprendra à utiliser le nœud HTTP Request, l'outil universel pour communiquer avec la quasi-totalité des services en ligne.