Ce sujet est une adaptation de mon intervention au Club utilisateurs Grist du 15 juin dernier, dont la captation a été perturbée par des problèmes techniques. J’espère que cette version écrite vous sera plus utile !
Les habitué·es du forum Grist ont certainement entendu parler de n8n, un logiciel d’automatisation que vous pouvez découvrir via ce sujet fort complet d’@audezu. Le tutoriel qui suit s’adresse à celles et ceux qui ont déjà utilisé n8n de la façon “ordinaire”, c’est-à-dire en utilisant les nœuds Grist fournis par défaut :
Mais ne vous fiez pas aux apparences : non seulement, il est possible de faire bien plus avec Grist et n8n que ce que ces quatre nœuds proposent, mais surtout, ces derniers s’avèrent parfois inadaptés dans certains cas, notamment lorsque vous avez une grande quantité de données à traiter. C’est pour ces raisons-là qu’il peut être pertinent d’apprendre à interagir avec Grist d’une autre manière : en passant non pas par les nœuds Grist, mais par le nœud plus versatile qu’est HTTP Request :
Si vous avez déjà des notions de développement web, vous aurez compris que ce nœud-là vous permet de faire un appel API à votre instance Grist. C’est également comme ça que les nœuds par défaut fonctionnent, mais les nœuds HTTP Request permettent de personnaliser plus finement les appels que nous voulons émettre. Ils sont donc plus compliqués à paramétrer, mais plus puissants à l’usage.
Prenons un exemple assez courant, le full refresh overwrite : vous voulez synchroniser un tableau avec un autre (tous deux appelés “Gares”), chacun dans un document Grist différent (ici “DocA” et “DocB”), et le contenu du DocB doit correspondre exactement à celui du DocA. Un workflow n8n dédié à cette tâche pourra ressembler à ceci :
Problème : les nœuds par défaut utilisés ici agissent sur vos tables Grist ligne par ligne. Ce qui veut dire que si vous voulez, par exemple, travailler sur une liste de toutes les gares du réseau ferré national français (il y en a plus de 6000), le workflow ci-dessus va alors vider la table “Gares” de votre DocB une ligne après l’autre, 6000 fois, puis la re-remplir avec les 6000 lignes de la table “Gares” de votre DocA, une ligne à la fois. Concrètement, en exécutant votre workflow, vous allez voir votre table Grist s’incrémenter à raison d’une ou deux lignes par seconde. Pendant tout ce temps-là, votre document risque d’être inutilisable, et annuler l’exécution du workflow n’annulera pas l’action côté Grist.
Heureusement, avec des nœuds API correctement configurés, vous n’allez pas envoyer 6000 fois une seule ligne, mais les 6000 lignes en une seule fois. Voici à quoi ressemblera votre workflow ainsi configuré :
Qu’est-ce qui a changé ?
-
nous avons remplacé les nœuds par défaut “Delete rows from a table”, “Read rows from a table” et “Create rows in a table” par trois nœuds HTTP Request. Pour les configurer correctement, nous avons consulté la console de l’API de notre instance (celle de la DINUM, par exemple, aura pour adresse https://grist.numerique.gouv.fr/apiconsole ; vous pouvez accéder à la vôtre depuis la page “Paramètres” de votre document Grist). C’est dans cette console que vous pourrez trouver l’appel API approprié. En l’occurrence :
- dans le premier nœud, nous faisons une requête POST vers
mon-instance-grist.org/docs/{id_de_DocB}/tables/Gares/record/deletepour effacer toutes les lignes de la table en une seule fois (l’URL exacte de la requête peut être reconstituée dans la console, en cliquant sur le bouton “Try it out” ; mais faites attention à ne pas supprimer de données sensibles par accident !)-
Comme l’indique la console de l’API, cette requête a besoin d’un corps (body) qui contient les
iddes lignes à supprimer. C’est pourquoi nous ajoutons un nœud Aggregate juste avant, qui va rassembler lesidde DocB/Gares pour qu’ils soient prêts à l’envoi.
-
- dans le deuxième nœud, nous faisons une requête GET vers
mon-instance-grist.org/docs/{id_de_DocB}/tables/Gares/record(sans/delete), qui sert à récupérer toutes les lignes de DocA/Gares. Contrairement au nœud “Read rows” par défaut, celui-ci va rassembler toutes les lignes dans un même objet JSON. - dans le troisième nœud, nous faisons une autre requête POST vers
mon-instance-grist.org/docs/{id_de_DocB}/tables/Gares/record(sans/delete) pour créer des nouvelles lignes dans la table fraîchement vidée.- Là encore, on a besoin d’envoyer un corps qui contient les données de toutes les lignes à envoyer. Il suffit donc d’y mettre l’objet JSON généré par le nœud précédent, et qui devrait correspondre à la variable
$json.
- Là encore, on a besoin d’envoyer un corps qui contient les données de toutes les lignes à envoyer. Il suffit donc d’y mettre l’objet JSON généré par le nœud précédent, et qui devrait correspondre à la variable
- dans le premier nœud, nous faisons une requête POST vers
-
une différence importante : les nœuds HTTP Request ne savent pas lire les identifiants Grist qu’utilisent les nœuds Grist par défaut. Vous devez alors créer des identifiants “Generic" de type “Bearer Auth”, comme illustré ci-dessous, avant d’y coller votre clé d’API comme avec un identifiant Grist ordinaire :
Ceci dit, envoyer un gros objet de 6000 lignes est certes plus rapide à traiter pour Grist, mais pèse autrement plus lourd sur votre n8n et votre serveur : le premier n’est pas conçu pour charger des objets aussi lourds en une seule fois (et ne manquera pas de vous avertir si vous l’essayez), le second a peut-être des limites de charge d’API mises en place par ses administrateurices. Il faut se montrer plus malin et faire un compromis, en équilibrant la quantité et le poids des objets à transmettre. Fort heureusement, n8n permet facilement de découper les objets en lots (batches), et c’est exactement ce que je vous suggère de faire ici, pour avoir non pas un objet de 6000 lignes, mais plutôt six objets de 1000 lignes :
Que se passe t-il ici ?
- on ne touche pas au nœud HTTP Request qui va récupérer la donnée en un seul objet, c’est exactement le même
- on rajoute un nœud Split Out qui va répartir les 6000 lignes dans un objet chacun (un peu comme le fait le nœud Grist “Read rows” par défaut, mais avec une syntaxe différente qui sera plus facile à manipuler par des nœuds HTTP Request)
- puis le nœud “Loop Over Items (Split in Batches)” va rassembler ces 6000 lignes par paquets de 1000 et les envoyer un par un dans la branche “loop”
- sur cette branche, le nœud d’agrégation va rassembler ces 1000 lignes en un seul objet, puis le nœud HTTP Request va écrire cet objet dans DocB/Gares en une seule fois, exactement comme dans notre workflow précédent
- lorsque les 5 autres paquets de 1000 lignes seront ainsi traités, le workflow partira sur la branche “Done” (le dernier nœud sert juste à vérifier que vous avez bien écrit les 6000 lignes)
Il convient de garder en tête que même en ayant recours à ces nœuds, n8n ne sera pas l’outil adapté : le no-code ne peut pas tout, et si vous avez de très grandes quantités de données à transférer fréquemment, il vaut mieux envisager d’inclure des outils plus sophistiqués dans votre gouvernance de données (je pense à Pygrister ou Airflow, mais je ne suis pas encore expert en la matière). Mais d’un autre côté, nous n’avons ici qu’effleuré les possibilités ouvertes par les nœuds HTTP Request : en exploitant l’API intelligemment, on peut imaginer des nœuds qui récupèrent les pièces jointes dans un Grist et importent leur contenu, ou encore un nœud s’appuyant sur la méthode PUT pour faire de la mise à jour de données sans full refresh overwrite (en attendant que la possibilité soit intégrée aux nœuds par défaut).






