Retour au cours

backend / graphql

Queries : lire des données

Leçon 31 exercice

Explication

Ce que vous allez apprendre

  • Écrire une query GraphQL simple puis imbriquée sur plusieurs niveaux de relations
  • Nommer tes requêtes et comprendre pourquoi c'est indispensable en production
  • Utiliser les alias pour requêter le même champ plusieurs fois avec des arguments différents
  • Factoriser des sélections de champs répétées avec des fragments
  • Sélectionner des champs conditionnellement avec les directives @include et @skip

Dans quel contexte ?

Une page de fiche produit d'un site e-commerce doit afficher le nom, le prix, la catégorie et les trois derniers avis clients avec le nom de leur auteur. Un développeur frontend écrit une seule query GraphQL qui décrit cette arborescence exacte, l'envoie au endpoint /graphql, et reçoit une réponse JSON qui a très exactement cette forme — ni plus, ni moins.

D'abord, la forme la plus simple d'une query

Une query anonyme, entre accolades, sélectionne un champ de Query puis les sous-champs voulus sur le type renvoyé. C'est la structure minimale : un champ racine (produit(id: "42")), suivi des champs scalaires qu'on veut lire dessus (nom, prix).

Une fois cette base acquise, il faut prendre l'habitude de nommer ses requêtes

Une query anonyme fonctionne très bien en test rapide, mais en production, chaque requête devrait porter un nom explicite comme ObtenirProduit. Ce nom apparaît dans les logs serveur, dans les outils de monitoring (Apollo Studio, par exemple) et facilite énormément le debug : sans lui, toutes les requêtes ressemblent à "query anonyme" dans les traces.

Ensuite, la sélection peut s'imbriquer sur plusieurs niveaux

Rien n'empêche de descendre plusieurs niveaux de relations dans une même requête : un produit, sa catégorie, les avis de ce produit, et même l'auteur de chaque avis. C'est exactement ce qui règle le problème du sous-fetching vu à la leçon précédente — mais attention, cette imbrication a un coût serveur qui sera abordé dans la leçon sur le problème N+1.

Il reste un cas particulier : et si je veux le même champ deux fois ?

Sans rien de spécial, GraphQL refuserait une ambiguïté si tu demandais deux fois produit avec des arguments différents dans la même sélection. L'alias résout ça : premier: produit(id: "42") renomme la clé du résultat en premier, permettant de comparer plusieurs produits dans une seule requête.

ConceptSyntaxeUsage typique
Query nomméequery ObtenirProduit { ... }Toujours en production, pour les logs
Aliaspremier: produit(id: "42") { ... }Requêter le même champ avec des arguments différents
Fragmentfragment X on Produit { ... }Factoriser une sélection réutilisée plusieurs fois
Fragment inline... on Produit { ... }Accéder aux champs spécifiques d'une interface/union

Maintenant, un problème de duplication apparaît vite

Dès qu'une même sélection de champs (par exemple id, nom, prix, enStock) est répétée dans plusieurs endroits de la requête, la copier-coller devient une source d'erreurs si le besoin change. Les fragments résolvent ce problème : on les déclare une fois avec fragment InfosProduit on Produit { ... }, puis on les réutilise avec ...InfosProduit partout où c'est nécessaire.

Prérequis

Cette leçon suppose que tu connais déjà la structure d'un schéma (types, Query, nullabilité), vue à la leçon précédente : une query ne peut sélectionner que des champs qui existent réellement dans le schéma.

Enfin, la sélection conditionnelle

Les directives standard @include(if: $condition) et @skip(if: $condition) permettent d'inclure ou d'exclure un champ selon une variable booléenne, sans dupliquer toute la requête en deux versions. C'est utile par exemple pour ne charger les avis d'un produit que si l'utilisateur a explicitement déplié cette section de l'interface.

Piège fréquent

Oublier de nommer ses requêtes en production rend le debug d'un endpoint GraphQL très pénible : impossible de savoir, dans les logs ou le monitoring, quelle partie du frontend a déclenché quelle requête. Prends l'habitude de nommer systématiquement, dès le développement.

Une fois à l'aise avec la lecture de données, la suite naturelle est d'apprendre à les modifier : la prochaine leçon aborde les mutations, la façon standard d'écrire des données en GraphQL.

Commandes & code

Queries : lire des données

graphql
# Query simple, un seul champ
query {
  produit(id: "42") {
    nom
    prix
  }
}

# Query nommée : recommandé en production (debugging, logs, cache client)
query ObtenirProduit {
  produit(id: "42") {
    nom
    prix
  }
}

# Sélection imbriquée sur plusieurs niveaux de relations
query ObtenirProduitAvecAvis {
  produit(id: "42") {
    nom
    categorie {
      nom
      slug
    }
    avis {
      note
      commentaire
      auteur {
        nom
        avatar
      }
    }
  }
}

# Alias : renommer un champ dans la réponse, utile pour requêter le même champ deux fois
query ComparerProduits {
  premier: produit(id: "42") { nom prix }
  second: produit(id: "43") { nom prix }
}

# Fragments : factoriser un ensemble de champs réutilisé plusieurs fois
fragment InfosProduit on Produit {
  id
  nom
  prix
  enStock
}

query ListeProduits {
  produits(limite: 10) {
    ...InfosProduit
  }
  produitsPromotion: produits(limite: 5) {
    ...InfosProduit
  }
}

# Fragments inline sur une interface ou union (voir leçon types complexes)
query DetailsRecherche {
  resultat(id: "42") {
    ... on Produit {
      nom
      prix
    }
    ... on Categorie {
      nom
      description
    }
  }
}

# Directives standard : @include et @skip pour de la sélection conditionnelle
query ObtenirProduit($avecAvis: Boolean!) {
  produit(id: "42") {
    nom
    avis @include(if: $avecAvis) {
      note
    }
  }
}
bash
# Introspection : interroger le schéma lui-même (utilisé par les outils comme GraphiQL)
curl -X POST https://api.exemple.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "{ __schema { types { name } } }"}'

Résumé

  • Toujours nommer les queries en production : elles apparaissent dans les logs et les outils de monitoring.
  • Les fragments (fragment X on Type) évitent la duplication de sélections de champs répétées.
  • @include(if:) et @skip(if:) permettent une sélection de champs conditionnelle sans dupliquer la requête.
  • L'introspection (__schema, __type) permet aux outils de générer de la documentation et de l'autocomplétion.

Exercices pratiques

1 disponible
1

Mission : optimiser une page fiche produit avec fragments et alias

Objectif : Factoriser une sélection de champs répétée et comparer deux produits dans une seule requête, sans dupliquer le texte de la requête.

Contexte

Le back-office e-commerce affiche une liste de produits standards et une liste de produits en promotion côte à côte, avec exactement les mêmes champs (id, nom, prix, enStock). Le product manager demande aussi un mode "comparateur" qui affiche deux produits précis (id 42 et 43) l'un à côté de l'autre dans un seul écran, chargé par une seule requête réseau.

Résoudre l’exercice →