API AEM GraphQL pour l’utilisation des fragments de contenu

Découvrez comment utiliser les fragments de contenu dans Adobe Experience Manager (AEM) avec l’API AEM GraphQL pour la diffusion de contenu en mode découplé.

L’API GraphQL d’AEM utilisée avec les fragments de contenu est fortement basée sur l’API GraphQL standard open source.

L’utilisation de l’API GraphQL dans AEM permet la diffusion efficace de fragments de contenu aux clients JavaScript dans les implémentations CMS découplées :

  • en évitant les demandes d’API itératives comme avec REST ;
  • en veillant à ce que la diffusion soit limitée aux exigences spécifiques ;
  • en permettant de diffuser en bloc exactement ce qui est nécessaire pour le rendu en réponse à une seule requête d’API.
REMARQUE

GraphQL est utilisé dans deux scénarios (distincts) dans Adobe Experience Manager (AEM) :

Prérequis

Les clients qui utilisent GraphQL doivent installer le fragment de contenu AEM avec le package d’index GraphQL 1.0.5. Voir la section Notes de mise à jour pour plus de détails.

L’API GraphQL

GraphQL est :

  • « …un langage de requête pour les API et un environnement d’exécution pour répondre à ces requêtes avec vos données existantes. GraphQL fournit une description complète et compréhensible des données de votre API. Il permet aux clients de demander exactement ce dont ils ont besoin et rien de plus, facilite l’évolution des API au fil du temps et offre des outils de développement puissants.".

    Voir GraphQL.org

  • « …une spécification ouverte pour une couche d’API flexible. Placez GraphQL sur vos arrière-plans existants afin que vous puissiez créer des produits plus rapidement que jamais…".

    Voir Explore GraphQL.

  • "…un langage de requête de données et une spécification développés en interne par Facebook en 2012 avant d’être publiquement open-source en 2015. C’est une alternative aux architectures basées sur REST destinée à accroître la productivité des développeurs et à réduire les quantités de données transférées. GraphQL est utilisé en production par des centaines d’entreprises de toutes tailles… »

    Voir GraphQL Foundation.

Pour plus d’informations sur l’API GraphQL, reportez-vous aux sections suivantes (parmi de nombreuses autres ressources) :

La mise en oeuvre de GraphQL pour AEM repose sur la bibliothèque Java™ GraphQL standard. Voir :

Terminologie GraphQL

GraphQL utilise les éléments suivants :

Voir la Présentation de GraphQL (GraphQL.org) pour des détails complets, y compris les Bonnes pratiques.

Types de requêtes GraphQL

GraphQL permet de réaliser des requêtes pour renvoyer, au choix :

AEM fournit des fonctionnalités pour convertir les requêtes (les deux types) en Requêtes persistantes qui sont mis en cache par Dispatcher et le réseau de diffusion de contenu.

Bonnes pratiques en matière de requêtes GraphQL (Dispatcher et réseau CDN)

Il est recommandé d’utiliser les Requêtes persistantes sur les instances de publication en raison des avantages suivants :

  • Elles sont mises en cache.
  • Elles sont gérées de manière centralisée par AEM
REMARQUE

En règle générale, il n’y a pas de dispatcher/CDN sur l’auteur. Il n’y a donc pas d’gain de performance dans l’utilisation de requêtes persistantes ; à part les tester.

Les requêtes GraphQL utilisant des requêtes POST ne sont pas recommandées, car elles ne sont pas mises en cache. Par conséquent, dans une instance par défaut, Dispatcher est configuré pour bloquer ces requêtes.

Bien que GraphQL prenne également en charge les requêtes de GET, ces requêtes peuvent atteindre des limites (par exemple, la longueur de l’URL) qui peuvent être évitées à l’aide des requêtes persistantes.

REMARQUE

Il se peut que la possibilité d’effectuer des requêtes directes devienne obsolète à un moment donné.

Interface GraphiQL

Une implémentation de l’interface standard GraphiQL est disponible pour être utilisée avec AEM GraphQL.

REMARQUE

GraphiQL est inclus dans tous les environnements d’AEM (mais n’est accessible/visible que lorsque vous configurez vos points de terminaison).

Dans les versions précédentes, vous aviez besoin d’un package pour installer l’IDE GraphiQL. Si ce package est installé, il peut maintenant être supprimé.

Cette interface vous permet de saisir et de tester directement des requêtes.

Par exemple :

  • http://localhost:4502/content/graphiql.html

Elle vous offre des fonctionnalités telles que la mise en surbrillance de la syntaxe, la saisie semi-automatique et la suggestion automatique, ainsi qu’un historique et une documentation en ligne:

Interface GraphiQL

Cas d’utilisation pour les environnements de création et de publication

Les cas d’utilisation peuvent dépendre du type d’environnement AEM :

  • Environnement de publication, utilisé pour :

    • Réaliser des requête de données pour l’application JS (cas d’utilisation standard)
  • Environnement de création, utilisé pour :

    • Réaliser des requêtes de données à des fins de gestion de contenu :
      • GraphQL dans AEM est une API en lecture seule.
      • L’API REST peut être utilisée pour les opérations CR(u)D.

Autorisations

Les autorisations sont requises pour accéder à Assets.

Les requêtes GraphQL sont exécutées avec l’autorisation de l’utilisateur AEM de la requête sous-jacente. Si l’utilisateur ne dispose pas d’un accès en lecture à certains fragments (stockés en tant que ressources), ils ne font pas partie du jeu de résultats.

L’utilisateur doit également avoir accès à un point de terminaison GraphQL pour pouvoir exécuter des requêtes GraphQL.

Création de schémas

GraphQL est une API typée, ce qui signifie que les données doivent être clairement structurées et organisées par type.

La spécification GraphQL fournit une série de directives sur la création d’une API robuste pour interroger les données sur une certaine instance. Pour suivre ces instructions, un client doit récupérer la variable Schéma, qui contient tous les types nécessaires à une requête.

Pour les fragments de contenu, les schémas GraphQL (structure et types) reposent sur des Modèles de fragments de contenu activés et leurs types de données

ATTENTION

Tous les schémas GraphQL (dérivés de modèles de fragments de contenu qui ont été activés) sont lisibles par le point d’entrée GraphQL.

Cette fonctionnalité signifie que vous devez vous assurer qu’aucune donnée sensible n’est disponible, car elle pourrait être divulguée de cette manière. Par exemple, il inclut des informations qui peuvent être présentes en tant que noms de champ dans la définition de modèle.

Par exemple, si un utilisateur ou une utilisatrice crée un modèle de fragment de contenu appelé Article, alors AEM génère un ArticleModel de type GraphQL. Les champs de ce type correspondent aux champs et aux types de données définis dans le modèle. AEM crée également des points d’entrée pour les requêtes qui opèrent sur ce type, comme articleByPath ou articleList.

  1. Un modèle de fragment de contenu :

    Modèle de fragment de contenu à utiliser avec GraphQL
  2. Le schéma GraphQL correspondant (sortie de la documentation automatique GraphiQL) :
    Schéma GraphQL basé sur le modèle de fragment de contenu

    Cette image montre que le type généré ArticleModel contient plusieurs fields.

    • Trois d'entre eux ont été contrôlés par l'utilisateur : author, main, et referencearticle.

    • Les autres champs ont été ajoutés automatiquement par AEM et représentent des méthodes utiles pour fournir des informations sur un certain fragment de contenu. Dans cet exemple, (la variable champ d’assistance) _path, _metadata, _variations.

  3. Après qu’un utilisateur a créé un fragment de contenu reposant sur le modèle d’article, il peut être interrogé via GraphQL. Vous trouverez des exemples à la section Exemples de Requêtes (basée sur un modèle de structure de fragment de contenu à utiliser avec GraphQL).

Dans GraphQL pour AEM, le schéma est flexible. Cette flexibilité signifie qu’il est généré automatiquement chaque fois qu’un modèle de fragment de contenu est créé, mis à jour ou supprimé. Les caches de schémas de données sont également actualisés lorsque vous mettez à jour un modèle de fragment de contenu.

Le service Sites GraphQL écoute (en arrière-plan) toutes les modifications apportées à un modèle de fragment de contenu. Lorsque des mises à jour sont détectées, seule cette partie du schéma est régénérée. Cette optimisation permet de gagner du temps et d’apporter de la stabilité.

Par exemple, si vous :

  1. Installez un package contenant Content-Fragment-Model-1 et Content-Fragment-Model-2 :

    1. Types GraphQL pour Model-1 et Model-2 sont générées.
  2. Puis modifiez Content-Fragment-Model-2 :

    1. Seule la variable Model-2 Le type GraphQL est mis à jour.

    2. Considérant Model-1 reste identique.

REMARQUE

Ce détail est important à noter uniquement au cas où vous souhaitez effectuer des mises à jour en masse sur les modèles de fragment de contenu via l’api REST, ou dans le cas contraire.

Le schéma est desservi par le même point d’entrée que les requêtes GraphQL, le client gérant le fait que le schéma est appelé avec l’extension GQLschema. Par exemple, l’exécution d’une GET requête sur /content/cq:graphql/global/endpoint.GQLschema génère la sortie du schéma avec le type Contenu : text/x-graphql-schema;charset=iso-8859-1.

Génération de schémas – Modèles dépubliés

Lorsque des fragments de contenu sont imbriqués, il se peut qu’un modèle de fragment de contenu parent soit publié, mais pas un modèle référencé.

REMARQUE

L’interface utilisateur AEM empêche cela, mais si la publication est effectuée par programmation ou avec des modules de contenu, elle peut se produire.

Dans ce cas, AEM génère une incomplet Schéma du modèle de fragment de contenu parent. Cela signifie que la référence au fragment, qui dépend du modèle non publié, est supprimée du schéma.

Champs

Au sein du schéma, il existe des champs individuels, de deux catégories de base :

  • Champs que vous générez.

    Une sélection de types de données est utilisée pour créer des champs en fonction de la configuration du modèle de fragment de contenu. Les noms des champs proviennent du champ Nom de la propriété du Type de données.

    • Il y a également la Render As à prendre en compte, car les utilisateurs peuvent configurer certains types de données. Par exemple, un champ de texte d’une seule ligne peut être configuré pour contenir plusieurs textes d’une seule ligne en choisissant multifield dans la liste déroulante.
  • GraphQL pour AEM génère également plusieurs champ d’assistance.

    Ces champs sont utilisés pour identifier un fragment de contenu ou pour obtenir plus d’informations sur un fragment de contenu.

Types de données

GraphQL pour AEM prend en charge une liste de types. Tous les types de données de modèles de fragments de contenu pris en charge et les types GraphQL correspondants sont représentés :

Modèle de fragment de contenu – Type de données Type GraphQL Description
Texte sur une seule ligne String, [String] Utilisé pour les chaînes simples telles que les noms d’auteur et les noms d’emplacement.
Texte multiligne String Utilisé pour la sortie de texte, tel que le corps d’un article
Nombre Float, [Float] Utilisé pour afficher le nombre à virgule flottante et les nombres réguliers
Booléen Boolean Utilisé pour afficher les cases à cocher → simples instructions vrai/faux
Date et heure Calendar Utilisé pour afficher la date et l’heure au format ISO 8086. Selon le type sélectionné, trois versions sont disponibles dans AEM GraphQL : onlyDate, onlyTime, dateTime
Énumération String Utilisé pour afficher une option à partir d’une liste d’options définies lors de la création du modèle
Balises [String] Utilisé pour afficher une liste de chaînes représentant les balises utilisées dans AEM
Référence de contenu String Utilisé pour afficher le chemin vers une autre ressource dans AEM
Référence du fragment Un type de modèle

Champ simple : Model - Type de modèle, référencé directement

Multichamp, avec un type référencé : [Model] - Tableau de type Model, référencé directement à partir du tableau

Multichamp, avec plusieurs types référencés : [AllFragmentModels] - Tableau de tous les types de modèle, référencé à partir d’un tableau avec type d’union
Utilisé pour référencer un ou plusieurs fragments de contenu de certains types de modèle, définis lors de la création du modèle

Champs d’assistance

Outre les types de données pour les champs générés par l’utilisateur, GraphQL pour AEM génère également plusieurs assistance pour identifier un fragment de contenu ou fournir des informations supplémentaires sur ce dernier.

Ces champs d’assistance sont précédés d’un _ pour distinguer ce qui a été défini par l’utilisateur ou l’utilisatrice de ce qui a été généré automatiquement.

Chemin d’accès

Le champ de chemin est utilisé comme identificateur dans AEM GraphQL. Il représente le chemin d’accès de la ressource de fragment de contenu dans le référentiel AEM. Ce chemin d’accès est choisi comme identifiant d’un fragment de contenu, car il :

  • est unique dans AEM ;
  • peut facilement être récupéré.

Le code suivant affiche les chemins d’accès de tous les fragments de contenu créés en fonction du modèle de fragment de contenu. Person.

{
  personList {
    items {
      _path
    }
  }
}

Pour récupérer un seul fragment de contenu d’un type spécifique, vous devez également d’abord déterminer son chemin. Par exemple :

{
  authorByPath(_path: "/content/dam/path/to/fragment/john-doe") {
    item {
      _path
      firstName
      name
    }
  }
}

Voir Exemple de requête – Un fragment de ville unique et spécifique.

Métadonnées

Par le biais de GraphQL, AEM expose également les métadonnées d’un fragment de contenu. Les métadonnées sont les informations qui décrivent un fragment de contenu, telles que :

  • le titre d’un fragment de contenu ;
  • chemin de miniature
  • la description d’un fragment de contenu ;
  • et la date de création, entre autres.

Les métadonnées étant générées par l’éditeur de schémas et n’ayant donc pas de structure spécifique, le type TypedMetaData GraphQL a été implémenté pour exposer les métadonnées d’un fragment de contenu. Le TypedMetaData expose les informations regroupées selon les types scalaires suivants :

Champ
stringMetadata:[StringMetadata]!
stringArrayMetadata:[StringArrayMetadata]!
intMetadata:[IntMetadata]!
intArrayMetadata:[IntArrayMetadata]!
floatMetadata:[FloatMetadata]!
floatArrayMetadata:[FloatArrayMetadata]!
booleanMetadata:[BooleanMetadata]!
booleanArrayMetadata:[booleanArrayMetadata]!
calendarMetadata:[CalendarMetadata]!
calendarArrayMetadata:[CalendarArrayMetadata]!

Chaque type scalaire représente soit une paire nom-valeur unique, soit un tableau de paires nom-valeur, où la valeur d’une paire est du type dans lequel elle a été regroupée.

Par exemple, si vous souhaitez récupérer le titre d’un fragment de contenu, cette propriété est une propriété String. Vous devez donc effectuer une requête pour toutes les métadonnées de chaîne :

Pour rechercher des métadonnées :

{
  personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
    item {
      _path
      _metadata {
        stringMetadata {
          name
          value
        }
      }
    }
  }
}

Vous pouvez afficher tous les types GraphQL de métadonnées si vous affichez le schéma GraphQL généré. Tous les types de modèle ont le même TypedMetaData.

REMARQUE

Différence entre les métadonnées normales et les métadonnées de tableau
Gardez à l’esprit que StringMetadata et StringArrayMetadata se rapportent tous deux à ce qui est stocké dans le référentiel et non à la façon dont vous les récupérez.

Par exemple, en appelant la fonction stringMetadata , vous recevez un tableau de toutes les métadonnées stockées dans le référentiel en tant que String. Et si vous appelez stringArrayMetadata, vous recevez un tableau de toutes les métadonnées stockées dans le référentiel sous la forme String[].

Voir Modèle de recherche de métadonnées – Répertorier les métadonnées des prix intitulés GB.

Variations

Le champ _variations a été implémenté pour simplifier la recherche de variations d’un fragment de contenu. Par exemple :

{
  personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
    item {
      _variations
    }
  }
}
REMARQUE

Le _variations ne contient pas de champ master variation, car techniquement, les données d’origine (référencées comme Principal dans l’interface utilisateur) n’est pas considérée comme une variation explicite.

Voir Modèle de requête – Toutes les villes avec une variante nommée.

REMARQUE

Si la variation donnée n’existe pas pour un fragment de contenu, les données d’origine (également appelées variation principale) sont renvoyées comme valeur par défaut (de secours).

Variables GraphQL

GraphQL permet de placer des variables dans la requête. Pour plus d’informations, voir Documentation GraphQL pour les variables.

Par exemple, pour obtenir tous les fragments de contenu de type Article qui présentent une variation spécifique, vous pouvez spécifier la variable variation dans GraphiQL.

Variables GraphQL
### query
query GetArticlesByVariation($variation: String!) {
    articleList(variation: $variation) {
        items {
            _path
            author
            _variations
        }
    }
}

### in query variables
{
    "variation": "uk"
}

Directives GraphQL

Dans GraphQL, il est possible de modifier la requête en fonction de variables, appelées directives GraphQL.

Par exemple, vous pouvez inclure ici le champ adventurePrice dans une requête pour tous les AdventureModels, en fonction d’une variable includePrice.

Directives GraphQL
### query
query GetAdventureByType($includePrice: Boolean!) {
  adventureList {
    items {
      adventureTitle
      adventurePrice @include(if: $includePrice)
    }
  }
}

### in query variables
{
    "includePrice": true
}

Filtrage

Vous pouvez également utiliser le filtrage dans vos requêtes GraphQL pour renvoyer des données spécifiques.

Le filtrage utilise une syntaxe basée sur des expressions et des opérateurs logiques.

La partie la plus atomique est une expression unique qui peut être appliquée au contenu d’un certain champ. Il compare le contenu du champ avec une valeur constante donnée.

Par exemple, l’expression suivante compare le contenu du champ à la valeur some textet réussissent si le contenu est égal à la valeur . Dans le cas contraire, l’expression échoue :

{
  value: "some text"
  _op: EQUALS
}

Les opérateurs suivants peuvent être utilisés pour comparer les champs à une certaine valeur :

Opérateur Types L’expression réussit si…
EQUALS String, ID, Boolean … la valeur est identique au contenu du champ
EQUALS_NOT String, ID …la valeur n’est pas identique au contenu du champ.
CONTAINS String … le contenu du champ contient la valeur ({ value: "mas", _op: CONTAINS } correspond à Christmas, Xmas, master, …)
CONTAINS_NOT String …le contenu du champ ne contient pas la valeur.
STARTS_WITH ID … l’identifiant commence par une certaine valeur ({ value: "/content/dam/", _op: STARTS_WITH correspond à /content/dam/path/to/fragment, mais pas /namespace/content/dam/something
EQUAL Int, Float … la valeur est identique au contenu du champ
UNEQUAL Int, Float …la valeur n’est pas identique au contenu du champ.
GREATER Int, Float …le contenu du champ est supérieur à la valeur.
GREATER_EQUAL Int, Float …le contenu du champ est supérieur ou égal à la valeur.
LOWER Int, Float …le contenu du champ est inférieur à la valeur.
LOWER_EQUAL Int, Float …le contenu du champ est inférieur ou égal à la valeur.
AT Calendar, Date, Time …le contenu du champ est identique à la valeur (paramètre de fuseau horaire inclus)
NOT_AT Calendar, Date, Time …le contenu du champ n’est pas identique à la valeur.
BEFORE Calendar, Date, Time …le moment indiqué par la valeur est antérieur au moment indiqué par le contenu du champ.
AT_OR_BEFORE Calendar, Date, Time …le moment indiqué par la valeur est antérieur ou égal au moment indiqué par le contenu du champ.
AFTER Calendar, Date, Time …le moment indiqué par la valeur est postérieur au moment indiqué par le contenu du champ.
AT_OR_AFTER Calendar, Date, Time …le moment indiqué par la valeur est postérieur ou égal au moment indiqué par le contenu du champ.

Certains types vous permettent également de spécifier des options supplémentaires qui modifient la manière dont une expression est évaluée :

Option Types Description
_ignoreCase String Ignore la casse d’une chaîne ; par exemple, une valeur de time correspond à TIME, time, tImE, …
_sensitiveness Float Permet une certaine marge pour que les valeurs float soient considérées comme identiques (pour contourner les limitations techniques en raison de la représentation interne des valeurs float). Cette option n’est pas recommandée en raison de son impact négatif sur les performances.

Les expressions peuvent être combinées à un jeu à l’aide d’un opérateur logique (_logOp) :

  • OR - l’ensemble d’expressions réussit si au moins une expression réussit
  • AND : l’ensemble d’expressions réussit si toutes les expressions réussissent (par défaut).

Chaque champ peut être filtré par son propre jeu d’expressions. Les ensembles d’expressions de tous les champs mentionnés dans l’argument filter sont finalement combinés par son propre opérateur logique.

Une définition de filtre (transmise comme l’argument filter dans une requête) contient les éléments suivants :

  • Une sous-définition pour chaque champ (le champ est accessible par son nom, par exemple, il y a une lastName dans le filtre pour la variable lastName champ dans le Type de données (champ)
  • Chaque sous-définition contient la propriété _expressions , fournissant le jeu d’expressions et la variable _logOp champ définissant l’opérateur logique avec lequel les expressions doivent être combinées
  • Chaque expression est définie par la valeur (champ value) et l’opérateur (champ _operator) auxquels le contenu d’un champ doit être comparé.

Vous pouvez omettre _logOp si vous souhaitez combiner des éléments avec AND et _operator si vous souhaitez vérifier l’égalité, car ces valeurs sont des valeurs par défaut.

L’exemple suivant illustre une requête complète qui filtre toutes les personnes dont le lastName est Provo ou contenant sjö, quel que soit le cas :

{
  authorList(filter: {
    lastname: {
      _logOp: OR
      _expressions: [
        {
          value: "sjö",
          _operator: CONTAINS,
          _ignoreCase: true
        },
        {
          value: "Provo"
        }
      ]
    }
  }) {
    items {
      lastName
      firstName
    }
  }
}

Il n’est pas recommandé de filtrer les champs imbriqués (bien que cela soit possible), car cela peut entraîner des problèmes de performances.

Pour accéder à d’autres exemples, voir :

Tri

Cette fonctionnalité vous permet de trier les résultats de la requête en fonction d’un champ spécifié.

Les critères de tri sont les suivants :

  • est une liste de valeurs séparées par des virgules représentant le chemin du champ.
    • le premier champ de la liste définit l’ordre de tri Principal
      • le deuxième champ est utilisé si deux valeurs du critère de tri Principal sont égales
      • le troisième champ est utilisé si les deux premiers critères sont égaux, etc.
    • notation pointillée, c’est-à-dire field1.subfield.subfield, etc…
  • avec un sens d’ordre optionnel,
    • ASC (croissant) ou DESC (décroissant) ; la valeur par défaut est ASC,
    • la direction peut être spécifiée par champ ; cette fonctionnalité signifie que vous pouvez trier un champ par ordre croissant, un autre par ordre décroissant (name, firstName DESC).

Par exemple :

query {
  authorList(sort: "lastName, firstName") {
    items {
      firstName
      lastName
    }
  }
}

Un autre exemple :

{
  authorList(sort: "lastName DESC, firstName DESC") {
    items {
        lastName
        firstName
    }
  }
}

Vous pouvez également trier un champ dans un fragment imbriqué au format nestedFragmentname.fieldname.

REMARQUE

Ce format peut avoir un impact négatif sur les performances.

Par exemple :

query {
  articleList(sort: "authorFragment.lastName")  {
    items {
      title
      authorFragment {
        firstName
        lastName
        birthDay
      }
      slug
    }
  }
}

Pagination

Cette fonctionnalité vous permet d’effectuer une pagination sur les types de requête qui renvoient une liste. Deux méthodes sont proposées :

  • offset et limit dans une requête List
  • first et after dans une requête Paginated

Requête de liste : « offset » et « limit »

Dans une requête ...List, vous pouvez utiliser offset et limit pour renvoyer un sous-ensemble spécifique de résultats :

  • offset : spécifie le premier jeu de données à renvoyer.
  • limit : spécifie le nombre maximal de jeux de données à renvoyer.

Par exemple, pour obtenir la page de résultats contenant jusqu’à cinq articles, en commençant par le cinquième article de la liste complète des résultats, effectuez l’opération suivante :

query {
   articleList(offset: 5, limit: 5) {
    items {
      authorFragment {
        lastName
        firstName
      }
    }
  }
}
REMARQUE
  • La pagination nécessite un ordre de tri stable pour fonctionner correctement sur plusieurs requêtes demandant différentes pages du même jeu de résultats. Par défaut, il utilise le chemin d’accès au référentiel de chaque élément du jeu de résultats pour s’assurer que l’ordre est toujours le même. Si un ordre de tri différent est utilisé et si ce tri ne peut pas être effectué au niveau de la requête JCR, il y a un impact négatif sur les performances. Cela est dû au fait que le jeu de résultats entier doit être chargé en mémoire avant que les pages ne soient déterminées.

  • Plus le décalage est élevé, plus il faut de temps pour ignorer les éléments du jeu de résultats de requête JCR complet. Une autre solution pour les jeux de résultats volumineux consiste à utiliser la requête paginée avec la méthode first et after.

Requête paginée : « first » et « after »

Le type de requête ...Paginated utilise la plupart des fonctionnalités du type de requête ...List (filtrage et tri), mais au lieu d’utiliser les arguments offset/limit, il utilise les arguments first/after tels que définis dans la Spécification des connexions basées sur le curseur GraphQL. Consultez une introduction moins formelle dans la Présentation de GraphQL.

  • first : les n premiers éléments à renvoyer.
    La valeur par défaut est 50.
    La valeur maximale est 100.
  • after: Curseur qui détermine le début de la page demandée. L’élément représenté par le curseur n’est pas inclus dans le jeu de résultats. Le curseur d’un élément est déterminé par la variable cursor du champ edges structure.

Par exemple, vous pouvez afficher la page des résultats contenant jusqu’à cinq aventures, à partir de l’élément donné du curseur dans la liste complète des résultats :

query {
    adventurePaginated(first: 5, after: "ODg1MmMyMmEtZTAzMy00MTNjLThiMzMtZGQyMzY5ZTNjN2M1") {
        edges {
          cursor
          node {
            title
          }
        }
        pageInfo {
          endCursor
          hasNextPage
        }
    }
}
REMARQUE
  • Par défaut, la pagination utilise l’UUID du noeud de référentiel représentant le fragment pour l’ordre afin de s’assurer que l’ordre des résultats est toujours le même. Lorsque sort est utilisé, l’UUID est implicitement utilisé pour assurer un tri unique, même pour deux éléments disposant de clés de tri identiques.

  • En raison de contraintes techniques internes, les performances se dégradent si le tri et le filtrage sont appliqués aux champs imbriqués. Par conséquent, utilisez les champs de filtrage/tri stockés au niveau racine. Cette technique est également recommandée si vous souhaitez interroger des jeux de résultats paginés volumineux.

GraphQL pour AEM – Résumé des extensions

Le fonctionnement de base des requêtes avec GraphQL pour AEM est conforme à la spécification GraphQL standard. Pour les requêtes GraphQL avec AEM, il existe quelques extensions :

Filtre CORS

REMARQUE

Pour un aperçu détaillé de la stratégie de partage des ressources CORS dans AEM, voir Comprendre le partage des ressources cross-origin (CORS).

Pour accéder au point de terminaison GraphQL, configurez une stratégie CORS dans le référentiel Git du client. Cette configuration est effectuée en ajoutant un fichier de configuration OSGi CORS approprié pour un ou plusieurs points de terminaison souhaités.

Cette configuration doit spécifier une origine de site web approuvée alloworigin ou alloworiginregexp pour laquelle l’accès doit être accordé.

Par exemple, pour accorder l’accès au point d’entrée GraphQL et aux requêtes persistantes pour https://my.domain, vous pouvez utiliser :

{
  "supportscredentials":true,
  "supportedmethods":[
    "GET",
    "HEAD",
    "POST"
  ],
  "exposedheaders":[
    ""
  ],
  "alloworigin":[
    "https://my.domain"
  ],
  "maxage:Integer":1800,
  "alloworiginregexp":[
    ""
  ],
  "supportedheaders":[
    "Origin",
    "Accept",
    "X-Requested-With",
    "Content-Type",
    "Access-Control-Request-Method",
    "Access-Control-Request-Headers"
  ],
  "allowedpaths":[
    "/content/_cq_graphql/global/endpoint.json",
    "/graphql/execute.json/.*"
  ]
}

Si vous avez configuré un chemin d’accès Vanity pour le point d’entrée, vous pouvez également l’utiliser dans allowedpaths.

Filtre Référent

Outre la configuration CORS, un filtre Référent doit être configuré pour autoriser l’accès à partir d’hôtes tiers.

Ce filtre est effectué en ajoutant un fichier de configuration de filtre de référent OSGi approprié qui :

  • spécifie un nom d’hôte de site web approuvé ; soit allow.hosts, soit allow.hosts.regexp,
  • accorde l’accès pour ce nom d’hôte.

Par exemple, pour accorder l’accès aux requêtes avec le référent my.domain, vous pouvez :

{
    "allow.empty":false,
    "allow.hosts":[
      "my.domain"
    ],
    "allow.hosts.regexp":[
      ""
    ],
    "filter.methods":[
      "POST",
      "PUT",
      "DELETE",
      "COPY",
      "MOVE"
    ],
    "exclude.agents.regexp":[
      ""
    ]
}
ATTENTION

Il incombe au client de :

  • n’accorder l’accès qu’aux domaines approuvés ;
  • s’assurer qu’aucune information sensible n’est exposée ;
  • ne pas utiliser de caractère générique [*] syntaxe; cette fonctionnalité désactive l’accès authentifié au point de terminaison GraphQL et l’expose également au monde entier.
ATTENTION

Tous les schémas GraphQL (dérivés de modèles de fragments de contenu qui ont été activés) sont lisibles par le point d’entrée GraphQL.

Cette fonctionnalité signifie que vous devez vous assurer qu’aucune donnée sensible n’est disponible, car elle pourrait être divulguée de cette manière. Par exemple, il inclut des informations qui peuvent être présentes en tant que noms de champ dans la définition de modèle.

Authentification

Voir Authentification pour les requêtes distantes AEM GraphQL sur les fragments de contenu.

FAQ

Questions soulevées :

  1. Q : « En quoi l’API GraphQL pour AEM est-elle différente de l’API Query Builder ? »

    • R : « L’API AEM GraphQL offre un contrôle total sur la sortie JSON et est une norme du secteur pour les requêtes de contenu.
      À l’avenir, AEM prévoit d’investir dans l’API GraphQL d’AEM.
      "

Tutoriel – Prise en main d’AEM découplé et de GraphQL

Vous cherchez un tutoriel pratique ? Consulter Prise en main d’AEM sans affichage et GraphQL tutoriel de bout en bout illustrant comment créer et exposer du contenu à l’aide des API GraphQL d’AEM et utilisé par une application externe, dans un scénario CMS sans interface.

Sur cette page