API GraphQL AEM per l’utilizzo con Frammenti di contenuto

Scopri come utilizzare Frammenti di contenuto in Adobe Experience Manager (AEM) as a Cloud Service con l’API GraphQL AEM per la consegna di contenuti headless.

L’API GraphQL AEM as a Cloud Service utilizzata con i Frammenti di contenuto è pesantemente basata sull’API GraphQL standard open source.

L’utilizzo dell’API GraphQL in AEM consente la consegna efficiente di Frammenti di contenuto ai client JavaScript in implementazioni CMS headless:

  • evita richieste API iterative come con REST,
  • garantisce che la consegna sia limitata ai requisiti specifici,
  • consente la consegna in massa di ciò che è esattamente necessario per il rendering come risposta a una singola query API.
NOTA

GraphQL è attualmente utilizzato in due scenari (separati) in Adobe Experience Manager (AEM) as a Cloud Service:

API GraphQL

GraphQL è:

  • …un linguaggio di query per le API e un runtime per l’esecuzione di tali query con i dati esistenti. GraphQL fornisce una descrizione completa e comprensibile dei dati nell’API, offre ai clienti la possibilità di chiedere esattamente ciò di cui hanno bisogno e niente di più, semplifica l’evoluzione delle API nel tempo e abilita potenti strumenti per gli sviluppatori.”.

    Vedi GraphQL.org

  • …una specifica aperta per un livello API flessibile. Posiziona GraphQL sui backend esistenti per costruire prodotti più rapidamente che mai…”.

    Vedi Esplorare GraphQL.

  • “…un linguaggio e una specifica di query di dati sviluppati internamente da Facebook nel 2012 prima di essere resi open source nel 2015. Offre un’alternativa alle architetture basate su REST allo scopo di aumentare la produttività degli sviluppatori e ridurre al minimo le quantità di dati trasferiti. GraphQL viene utilizzato in produzione da centinaia di organizzazioni di tutte le dimensioni…”

    Vedi GraphQL Foundation.

Per ulteriori informazioni sull’API GraphQL, consulta le sezioni seguenti (tra molte altre risorse):

L’implementazione di GraphQL per AEM si basa sulla libreria Java GraphQL standard. Consulta:

Terminologia GraphQL

GraphQL utilizza quanto segue:

  • Query

  • Schemi e tipi:

    • Gli schemi vengono generati da AEM in base ai modelli di Frammenti di contenuto.
    • Utilizzando i tuoi schemi, GraphQL presenta i tipi e le operazioni consentiti per l’implementazione GraphQL per AEM.
  • Campi

  • Endpoint GraphQL

Consulta(GraphQL.org) Introduzione a GraphQL per informazioni complete, che comprendono le Best practice.

Tipi di query GraphQL

Con GraphQL è possibile eseguire query per ottenere:

AEM fornisce funzionalità per convertire le query (entrambi i tipi) in Query persistenti, che possono essere memorizzate nella cache da Dispatcher e CDN.

Best practice per le query GraphQL (Dispatcher e CDN)

Le Query persistenti sono il metodo consigliato da utilizzare nelle istanze di pubblicazione come:

  • vengono memorizzate nella cache;
  • sono gestite centralmente da AEM as a Cloud Service.
NOTA

Di solito non esiste un dispatcher/CDN sull’autore, quindi in quel caso non c’è alcun vantaggio nell’utilizzo di query persistenti; oltre ai test.

Le query GraphQL con l’utilizzo di POST non sono consigliate in quanto non sono memorizzate nella cache. Quindi, in un’istanza predefinita, Dispatcher è configurato per bloccarle.

GraphQL supporta anche le richieste GET, ma queste devono sottostare a limiti (ad esempio la lunghezza dell’URL) che possono essere evitati utilizzando le query persistenti.

NOTA

Per consentire query dirette e/o POST in Dispatcher, puoi chiedere all’amministratore di sistema di:

NOTA

In futuro, la capacità di eseguire query dirette potrebbe diventare obsoleta.

IDE GraphiQL

Puoi testare ed eseguire il debug delle query GraphQL utilizzando IDE GraphiQL.

Casi di utilizzo per ambienti di authoring e pubblicazione

I casi di utilizzo possono dipendere dal tipo di ambiente AEM as a Cloud Service:

  • ambiente di pubblicazione; utilizzato per:

    • effettuare query sui dati per l’applicazione JS (caso di utilizzo standard)
  • ambiente di authoring; utilizzato per:

    • effettuare query sui dati a “scopo di gestione dei contenuti”:
      • GraphQL in AEM as a Cloud Service è attualmente un’API di sola lettura.
      • L’API REST può essere utilizzata per le operazioni CR(u)D.

Autorizzazioni

Le autorizzazioni sono quelle necessarie per accedere ad Assets.

Le query GraphQL vengono eseguite con l’autorizzazione dell’utente AEM della richiesta sottostante. Se l’utente non dispone dell’accesso in lettura ad alcuni frammenti (memorizzati come risorse), questi non faranno parte del set di risultati.

Inoltre, per poter eseguire query GraphQL l’utente deve avere accesso a un endpoint GraphQL.

Generazione schema

GraphQL è un’API fortemente tipizzata, il che significa che i dati devono essere chiaramente strutturati e organizzati per tipo.

La specifica GraphQL fornisce una serie di linee guida su come creare una solida API per l’interrogazione dei dati su una determinata istanza. A questo scopo, un client deve recuperare lo Schema, che contiene tutti i tipi necessari per una query.

Per quanto riguarda i Frammenti di contenuto, gli schemi GraphQL (struttura e tipi) sono basati su modelli di Frammenti di contenuto abilitati e i relativi tipi di dati.

ATTENZIONE

Tutti gli schemi GraphQL (derivati dai modelli di Frammenti di contenuto che sono stati abilitati) sono leggibili attraverso l’endpoint GraphQL.

Ciò significa che devi assicurarti che non siano disponibili dati sensibili, che in questo modo potrebbero trapelare; ad esempio, informazioni che potrebbero essere presenti come nomi di campo nella definizione del modello.

Ad esempio, se un utente ha creato un modello di frammento di contenuto denominato Article, AEM genera un tipo GraphQL ArticleModel. I campi all’interno di questo tipo corrispondono ai campi e ai tipi di dati definiti nel modello. Inoltre, crea alcuni punti di ingresso per le query che operano su questo tipo, come articleByPath o articleList.

  1. Modello di Frammento di contenuto:

    Modello di Frammento di contenuto da utilizzare con GraphQL
  2. Lo schema GraphQL corrispondente (output dalla documentazione automatica GraphiQL):
    Schema GraphQL basato su modello di Frammento di contenuto

    Questo mostra che il tipo ArticleModel generato contiene diversi campi.

    • Tre di essi sono stati controllati dall’utente: author, main e referencearticle.

    • Gli altri campi sono stati aggiunti automaticamente da AEM e rappresentano metodi utili per fornire informazioni su un determinato Frammento di contenuto; in questo esempio (i campi di supporto) _path, _metadata, _variations.

  3. Un Frammento di contenuto basato sul modello di articolo creato da un utente può essere interrogato tramite GraphQL. Per esempi, consulta la sezione Query di esempio (basata su una struttura di Frammento di contenuto di esempio da utilizzare con GraphQL).

In GraphQL per AEM, lo schema è flessibile. Ciò significa che viene generato automaticamente ogni volta che viene creato, aggiornato o eliminato un modello di Frammento di contenuto. Le cache dello schema dati vengono aggiornate anche quando si rivede un modello di Frammento di contenuto.

Le cache dello schema dati vengono aggiornate anche quando si rivede un modello di Frammento di contenuto.

Il servizio GraphQL di Sites ascolta (in background) le modifiche apportate a un modello di Frammento di contenuto. Quando vengono rilevati aggiornamenti, viene rigenerata solo la parte dello schema. Questa ottimizzazione consente di risparmiare tempo e garantisce stabilità.

Ad esempio, se:

  1. Installi un pacchetto contenente Content-Fragment-Model-1 e Content-Fragment-Model-2:

    1. vengono generati dei tipi GraphQL per Model-1 e Model-2.
  2. Poi modifica Content-Fragment-Model-2:

    1. verrà aggiornato solo il tipo GraphQL Model-2.

    2. mentre Model-1 rimarrà lo stesso.

NOTA

Questo è importante da notare nel caso in cui desideri eseguire aggiornamenti in blocco sui modelli di Frammento di contenuto tramite l’API REST o in altro modo.

Lo schema viene gestito attraverso lo stesso endpoint delle query GraphQL, dove il client gestisce il fatto che lo schema viene chiamato con l’estensione GQLschema. Ad esempio, l’esecuzione di una semplice richiesta GET di /content/cq:graphql/global/endpoint.GQLschema si tradurrà nell’output dello schema con il tipo di contenuto: text/x-graphql-schema;charset=iso-8859-1.

Generazione schema: modelli non pubblicati

Quando i frammenti di contenuto sono nidificati, può accadere che venga pubblicato un modello di Frammento di contenuto principale, ma non il modello di riferimento.

NOTA

L’interfaccia utente AEM impedisce che ciò accada, ma se la pubblicazione viene effettuata a livello di programmazione o con pacchetti di contenuto può verificarsi.

In questo caso, AEM genera uno schema incompleto per il modello di Frammento di contenuto principale. Ciò significa che il Riferimento al frammento, che dipende dal modello non pubblicato, viene rimosso dallo schema.

Campi

Nello schema sono presenti singoli campi, di due categorie di base:

  • Campi generati dall’utente.

    Per creare campi in base alla modalità di configurazione del modello di frammento di contenuto, viene utilizzata una selezione di Tipi di dati. I nomi dei campi vengono ricavati dal campo Nome proprietà della scheda Tipo di dati.

    • C'è anche da tenere presente l’impostazione Rendering come, in quanto gli utenti possono configurare determinati tipi di dati. Ad esempio, un campo di testo a riga singola può essere configurato in modo da contenere più testi a riga singola scegliendo multifield dal menu a discesa.
  • GraphQL per AEM genera anche una serie di campi di supporto.

Tipi di dati

GraphQL per AEM supporta un elenco di tipi. Vengono rappresentati tutti i tipi di dati dei modelli di Frammento di contenuto supportati e i corrispondenti tipi GraphQL:

Modello di Frammento di contenuto: tipo di dati Tipo GraphQL Descrizione
Testo su riga singola String, [String] Utilizzato per stringhe semplici come nomi di autore, nomi di posizione, ecc.
Testo su più righe String, [String] Utilizzato per l’output di testo, ad esempio il corpo di un articolo
Numero Float, [Float] Utilizzato per visualizzare il numero a virgola mobile e i numeri regolari
Booleano Boolean Utilizzato per visualizzare le caselle di controllo → semplici istruzioni true/false
Data e ora Calendar Utilizzato per visualizzare la data e l’ora in formato ISO 8601. A seconda del tipo selezionato, sono disponibili tre versioni da utilizzare in AEM GraphQL: onlyDate, onlyTime, dateTime
Enumerazione String Utilizzato per visualizzare un’opzione da un elenco di opzioni definito durante la creazione del modello
Tag [String] Utilizzato per visualizzare un elenco di stringhe che rappresentano tag utilizzati in AEM
Riferimento contenuto String, [String] Utilizzato per visualizzare il percorso per un’altra risorsa in AEM
Riferimento frammento Un tipo di modello

Campo singolo: Model - Tipo di modello, a cui si fa riferimento direttamente

Multicampo, con un tipo di riferimento: [Model] - Array di tipo Model, a cui si fa riferimento direttamente dall'array

Multicampo, con più tipi di riferimento: [AllFragmentModels] - Array di tutti i tipi di modello, a cui si fa riferimento da array con tipo di unione
Utilizzato per fare riferimento a uno o più frammenti di contenuto di alcuni tipi di modelli, definiti al momento della creazione del modello

Campi di supporto

Oltre ai tipi di dati per i campi generati dall’utente, GraphQL for AEM genera anche una serie di campi di supporto per consentire l’identificazione di un frammento di contenuto o per fornire informazioni aggiuntive su un frammento di contenuto.

Tali campi di supporto sono contrassegnati con un _ precedente per distinguere tra ciò che è stato definito dall’utente e ciò che è stato generato automaticamente.

Percorso

In AEM GraphQL, il campo del percorso viene utilizzato come identificatore. Rappresenta il percorso della risorsa Frammenti di contenuto all’interno dell’archivio AEM. Abbiamo scelto questo come identificatore di un frammento di contenuto in quanto:

  • è univoco all’interno di AEM,
  • può essere facilmente recuperato.

Il seguente codice visualizza i percorsi di tutti i frammenti di contenuto creati in base al modello per frammenti di contenuto Author, come indicato nel tutorial WKND.

{
  authorList {
    items {
      _path
    }
  }
}

Inoltre, per recuperare un singolo frammento di contenuto di un tipo specifico, è necessario determinarne prima il percorso. Esempio:

{
  authorByPath(_path: "/content/dam/wknd-shared/en/contributors/sofia-sj-berg") {
    item {
      _path
      firstName
      lastName
    }
  }
}

Vedi Query di esempio: un singolo frammento di città specifico.

Metadati

Tramite GraphQL, AEM espone inoltre i metadati di un frammento di contenuto. I metadati sono informazioni che descrivono un frammento di contenuto, come ad esempio il titolo, il percorso della miniatura, la descrizione, la data di creazione e così via.

Poiché i metadati vengono generati tramite l’Editor schemi e, pertanto, non dispongono di una struttura specifica, il tipo di TypedMetaData GraphQL è stato implementato per esporre i metadati di un frammento di contenuto. TypedMetaData espone le informazioni raggruppate per i seguenti tipi scalari:

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

Ogni tipo scalare rappresenta una coppia nome-valore singola o un array di coppie nome-valore, in cui il valore di tale coppia è del tipo all'interno del quale è stato raggruppato.

Ad esempio, se vuoi recuperare il titolo di un frammento di contenuto, si tratta di una proprietà stringa, pertanto è necessario eseguire una query per tutti i metadati stringa:

Per eseguire una query per i metadati:

{
  authorByPath(_path: "/content/dam/wknd-shared/en/contributors/sofia-sj-berg") {
    item {
      _metadata {
        stringMetadata {
          name
          value
        }
      }
    }
  }
}

Puoi visualizzare tutti i tipi di metadati GraphQL se visualizzi lo schema GraphQL generato. Tutti i tipi di modello hanno lo stesso TypedMetaData.

NOTA

Differenza tra metadati normali e quelli di array
Nota: StringMetadata e StringArrayMetadata si riferiscono a ciò che è memorizzato nell’archivio, non alla modalità di recupero.

Ad esempio, effettuando una chiamata del campo stringMetadata, può essere restituito un array di tutti i metadati memorizzati nell’archivio come una String; se si effettua una chiamata dell’stringArrayMetadata può essere restituito un array di tutti i metadati memorizzati nell’archivio come String[].

Vedi Query di esempio per metadati: elenca i metadati per riconoscimenti con titolo GB.

Varianti

Il campo _variations è stato implementato per semplificare l’esecuzione delle query sulle varianti di un frammento di contenuto. Esempio:

{
  authorByPath(_path: "/content/dam/wknd-shared/en/contributors/ian-provo") {
    item {
      _variations
    }
  }
}
NOTA

Tieni presente che il campo _variations non contiene una variazione master, poiché, tecnicamente, i dati originali (a cui si fa riferimento come primari nell’interfaccia utente) non sono considerati una variante esplicita.

Vedi Query di esempio: tutte le città con una variante denominata.

NOTA

Se per un frammento di contenuto non esiste la variante determinata, i dati originali (noti anche come variante primaria) verranno restituiti come impostazione predefinita (fallback).

Variabili GraphQL

GraphQL consente di inserire variabili nella query. Per ulteriori informazioni, consulta la documentazione di GraphQL per variabili.

Ad esempio, per ottenere tutti i frammenti di contenuto di tipo Author in una variante specifica (se disponibile), puoi specificare l’argomento variation in GraphiQL.

Variabili GraphQL

Query:

query($variation: String!) {
  authorList(variation: $variation) {
    items {
      _variation
      lastName
      firstName
    }
  }
}

Variabili di query:

{
  "variation": "another"
}

Questa query restituirà l’elenco completo degli autori. Autori senza la variazione another torneranno ai dati originali (in questo caso _variation riferirà master).

Se desideri limitare l’elenco agli autori che forniscono la variante specificata (e saltare gli autori che ritornano ai dati originali), devi applicare un filtro:

query($variation: String!) {
  authorList(variation: $variation, filter: {
    _variation: {
      _expressions: {
        value: $variation
      }
    }
  }) {
    items {
      _variation
      lastName
      firstName
    }
  }
}

Direttive GraphQL

In GraphQL è possibile modificare le query basate su variabili, denominate Direttive GraphQL.

Ad esempio, puoi includere il campo adventurePrice in una query per tutti i AdventureModels basati su una variabile includePrice.

Direttive GraphQL

Query:

query GetAdventureByType($includePrice: Boolean!) {
  adventureList {
    items {
      title
      price @include(if: $includePrice)
    }
  }
}

Variabili di query:

{
    "includePrice": true
}

Filtro

Puoi inoltre utilizzare il filtro nelle query GraphQL per restituire dati specifici.

Il filtro utilizza una sintassi basata su operatori ed espressioni di tipo logico.

La parte più atomica è una singola espressione che può essere applicata al contenuto di un determinato campo. Confronta il contenuto del campo con un valore costante specificato.

Ad esempio, l’espressione

{
  value: "some text"
  _op: EQUALS
}

confronta il contenuto del campo con il valore some text e ha successo se il contenuto è uguale al valore. In caso contrario, l’espressione avrà esito negativo.

Per confrontare i campi con un determinato valore è possibile utilizzare i seguenti operatori:

Operatore Tipo/i L’espressione ha esito positivo se …
EQUALS String, ID, Boolean … il valore è esattamente uguale al contenuto del campo
EQUALS_NOT String, ID … il valore not è uguale al contenuto del campo
CONTAINS String … il contenuto del campo contiene il valore ({ value: "mas", _op: CONTAINS } corrisponderà a Christmas, Xmas, master, …)
CONTAINS_NOT String … il contenuto del campo non contiene il valore
STARTS_WITH ID … l’ID inizia con un certo valore ({ value: "/content/dam/", _op: STARTS_WITH corrisponderà a /content/dam/path/to/fragment, ma non a /namespace/content/dam/something
EQUAL Int, Float … il valore è esattamente uguale al contenuto del campo
UNEQUAL Int, Float … il valore non è uguale al contenuto del campo
GREATER Int, Float … il contenuto del campo è maggiore del valore
GREATER_EQUAL Int, Float … il contenuto del campo è maggiore o uguale al valore
LOWER Int, Float … il contenuto del campo è inferiore al valore
LOWER_EQUAL Int, Float … il contenuto del campo è inferiore o uguale al valore
AT Calendar, Date, Time … il contenuto del campo è esattamente uguale al valore (inclusa l’impostazione del fuso orario)
NOT_AT Calendar, Date, Time … il contenuto del campo non è uguale al valore
BEFORE Calendar, Date, Time … il punto nel tempo indicato dal valore è precedente a quello indicato dal contenuto del campo
AT_OR_BEFORE Calendar, Date, Time … il punto nel tempo indicato dal valore è precedente o uguale a quello indicato dal contenuto del campo
AFTER Calendar, Date, Time … il punto nel tempo indicato dal valore è successivo a quello indicato dal contenuto del campo
AT_OR_AFTER Calendar, Date, Time … il punto nel tempo indicato dal valore è successivo o uguale a quello indicato dal contenuto del campo

Alcuni tipi consentono inoltre di specificare opzioni aggiuntive che modificano la modalità di valutazione di un’espressione:

Opzione Tipo/i Descrizione
_ignoreCase String Ignora il caso di una stringa, ad esempio un valore di time corrisponderà a TIME, time, tImE
_sensitiveness Float Consente un certo margine per valori float da considerare uguali (per aggirare i limiti tecnici dovuti alla rappresentazione interna dei valori float; dovrebbe essere evitata, in quanto questa opzione potrebbe avere un impatto negativo sulle prestazioni

Le espressioni possono essere combinate in un set tramite un operatore logico (_logOp):

  • OR: il set di espressioni avrà esito positivo se almeno un’espressione ha esito positivo
  • AND: il set di espressioni avrà esito positivo se tutte le espressioni hanno esito positivo (impostazione predefinita)

Ogni campo può essere filtrato in base al proprio set di espressioni. I set di espressioni di tutti i campi menzionati nell’argomento del filtro verranno infine combinati dal proprio operatore logico.

Una definizione di filtro (passata come argomento filter a una query) contiene:

  • Una sottodefinizione per ciascun campo (a cui è possibile accedere tramite il nome, ad esempio, è disponibile un campo lastName nel filtro per il campo lastName nel Tipo di dati (campo))
  • Ogni sottodefinizione contiene la variabile array _expressions, che fornisce il set di espressioni e campo _logOp che definisce l’operatore logico con cui combinare le espressioni
  • Ciascuna espressione è definita dal valore (campo value) e dall’operatore (campo _operator) con cui il contenuto di un campo deve essere confrontato

È possibile omettere _logOp per combinare gli elementi con AND e _operator se desideri verificare l’uguaglianza, in quanto questi sono i valori predefiniti.

L’esempio seguente illustra una query completa che filtra tutte le persone con una lastName di Provo o contenenti sjö, indipendentemente dal caso:

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

È anche possibile filtrare i campi nidificati, ma non è consigliabile, in quanto potrebbe causare problemi di prestazioni.

Per altri esempi, consulta:

Ordinamento

Questa funzione ti consente di ordinare i risultati della query in base a un campo specificato.

I criteri di ordinamento:

  • è un elenco di valori separati da virgola che rappresenta il percorso del campo
    • il primo campo dell’elenco definisce l’ordinamento primario, il secondo campo viene utilizzato se due valori del criterio di ordinamento primario sono uguali, il terzo se i primi due criteri sono uguali, ecc.
    • notazione tratteggiata, ad esempio field1.subfield.subfield, ecc.
  • con una direzione d’ordine opzionale
    • ASC (crescente) o DESC (decrescente); con l’applicazione di ASC come predefinito
    • la direzione può essere specificata per campo; ciò significa che è possibile ordinare un campo in ordine crescente, un altro in ordine decrescente (name, firstName DESC)

Esempio:

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

Inoltre:

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

È inoltre possibile ordinare in base a un campo all’interno di un frammento nidificato utilizzando il formato nestedFragmentname.fieldname.

NOTA

Questo potrebbe avere un impatto negativo sulle prestazioni.

Esempio:

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

Paging

Questa funzione consente di eseguire il paging sui tipi di query che restituiscono un elenco. Vengono forniti due metodi:

  • offset e limit in una query List
  • first e after in una query Paginated

Query elenco: offset e limite

In una ...Listquery puoi utilizzare offset e limit per ottenere un sottoinsieme specifico di risultati:

  • offset: specifica il primo set di dati da restituire
  • limit: specifica il numero massimo di set di dati da restituire

Ad esempio, per un output con la pagina dei risultati contenente fino a cinque articoli, a partire dal quinto articolo dell’elenco dei risultati completo:

query {
   articleList(offset: 5, limit: 5) {
    items {
      authorFragment {
        lastName
        firstName
      }
    }
  }
}
NOTA
  • Il paging richiede un ordinamento stabile per funzionare correttamente in più query che richiedono pagine diverse dello stesso set di risultati. Per impostazione predefinita, utilizza il percorso dell’archivio di ogni elemento del set di risultati per assicurarsi che l’ordine sia sempre lo stesso. Se viene utilizzato un ordinamento diverso e se tale ordinamento non può essere eseguito a livello di query JCR, ci sarà un impatto negativo sulle prestazioni, poiché l’intero set di risultati deve essere caricato in memoria prima di determinare le pagine.

  • Maggiore è l’offset, più tempo sarà necessario per saltare gli elementi dal set di risultati completo della query JCR. Una soluzione alternativa per i set di risultati di grandi dimensioni è quella di utilizzare la query impaginata con il metodo first e after.

Query impaginata: prima e dopo

Il tipo di query ...Paginated riutilizza la maggior parte delle funzionalità del tipo di query ...List (filtro, ordinamento), ma invece di utilizzare gli argomenti offset/limit utilizza first/after come definiti in Specifica delle connessioni del cursore GraphQL. È possibile trovare un’introduzione meno formale in Introduzione a GraphQL.

  • first: i primi elementi n da restituire.
    Il valore predefinito è 50.
    Il massimo è 100.
  • after: il cursore che determina l’inizio della pagina richiesta; nota che la voce rappresentata dal cursore non è inclusa nel set di risultati; il cursore di un elemento è determinato dal campo cursor della struttura edges.

Ad esempio, restituisce la pagina dei risultati contenenti fino a cinque avventure, a partire dalla voce del cursore specificata nell’elenco dei risultati completo:

query {
    adventurePaginated(first: 5, after: "ODg1MmMyMmEtZTAzMy00MTNjLThiMzMtZGQyMzY5ZTNjN2M1") {
        edges {
          cursor
          node {
            title
          }
        }
        pageInfo {
          endCursor
          hasNextPage
        }
    }
}
NOTA
  • Per impostazione predefinita, il paging utilizza l’UUID del nodo dell’archivio che rappresenta il frammento per l’ordinamento in modo che l’ordine dei risultati sia sempre lo stesso. Quando viene utilizzato sort, l’UUID viene utilizzato implicitamente per garantire un ordinamento univoco; anche per due elementi con chiavi di ordinamento identiche.

  • A causa di vincoli tecnici interni, le prestazioni peggioreranno se l’ordinamento e il filtro vengono applicati ai campi nidificati. Si consiglia pertanto di utilizzare i campi di filtro/ordinamento memorizzati a livello di radice. Questo è anche il modo consigliato per eseguire query su set di risultati impaginati di grandi dimensioni.

Distribuzione di immagini ottimizzate per il web nelle query GraphQL

La distribuzione di immagini ottimizzate per il web consente di utilizzare una query GraphQL per:

  • Richiedere un URL per un’immagine risorsa di AEM

  • Passa i parametri con la query in modo che venga generata e restituita automaticamente una rappresentazione specifica dell’immagine

    NOTA

    La rappresentazione specificata non viene memorizzata in AEM Assets. La rappresentazione viene generata e mantenuta nella cache per un breve periodo.

  • Restituisce l’URL come parte della distribuzione JSON

Puoi utilizzare AEM per:

Ciò significa che i comandi vengono applicati durante l’esecuzione della query, allo stesso modo dei parametri URL sulle richieste GET per quelle immagini.

Questo consente di creare in modo dinamico rappresentazioni di immagini per la distribuzione JSON, evitando di dover creare e archiviare manualmente tali rappresentazioni nell’archivio.

La soluzione GraphQL consente di:

  • utilizzare _dynamicUrl sul riferimento ImageRef

  • aggiungere _assetTransform all’intestazione dell’elenco in cui sono definiti i filtri

Struttura della richiesta di trasformazione

AssetTransform (_assetTransform) viene utilizzato per effettuare le richieste di trasformazione URL.

La struttura e la sintassi sono:

  • format: un'enumerazione con tutti i formati supportati dalla relativa estensione: GIF, PNG, PNG8, JPG, PJPG, BJPG, WEBP, WEBPLL o WEBPLY
  • seoName: una stringa che verrà utilizzata come nome file invece del nome nodo
  • crop: una sottostruttura del frame, se la larghezza o l’altezza sono omesse, vengono utilizzate come lo stesso valore
    • xOrigin: l'origine x del frame ed è obbligatoria
    • yOrigin: l'origine y del frame ed è obbligatoria
    • width: la larghezza del frame
    • height: l’altezza del frame
  • size: una sottostruttura della dimensione, se la larghezza o l’altezza sono omesse, vengono utilizzate come lo stesso valore
    • width: la larghezza della dimensione
    • height: l’altezza della dimensione
  • rotation: un’enumerazione di tutte le rotazioni supportate: R90, R180, R270
  • flip: un’enumerazione di HORIZONTAL, VERTICAL, HORIZONTAL_AND_VERTICAL
  • quality: un numero intero compreso tra 1 e 100 che rileva la percentuale di qualità dell’immagine
  • width: un numero intero che definisce la larghezza dell’immagine di output ma che verrà ignorato dal generatore di immagini
  • preferWebp: un valore booleano che indica se webp è preferito (il valore predefinito è false)

La trasformazione URL è disponibile per tutti i tipi di query: per percorso, elenco o impaginata.

Distribuzione di immagini ottimizzate per il web con parametri completi

Di seguito è riportato un esempio di query con un set completo di parametri:

{
  articleList(
    _assetTransform: {
      format:GIF
      seoName:"test"
      crop:{
        xOrigin:10
        yOrigin:20
        width:50
        height:45
      }
      size:{
        height:100
        width:200
      }
      rotation:R90
      flip:HORIZONTAL_AND_VERTICAL
      quality:55
      width:123
      preferWebp:true
    }
  ) {
    items {
      _path
      featuredImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

Distribuzione di immagini ottimizzate per il web con una singola variabile di query

L’esempio seguente mostra l’utilizzo di una singola variabile di query:

query ($seoName: String!) {
  articleList(
    _assetTransform: {
      format:GIF
      seoName:$seoName
      crop:{
        xOrigin:10
        yOrigin:20
        width:50
        height:45
      }
      size:{
        height:100
        width:200
      }
      rotation:R90
      flip:HORIZONTAL_AND_VERTICAL
      quality:55
      width:123
      preferWebp:true
    }
  ) {
    items {
      _path
      featuredImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

Distribuzione di immagini ottimizzata per il web con più variabili di query

L’esempio seguente mostra l’utilizzo di più variabili di query:

query ($seoName: String!, $format: AssetTransformFormat!) {
  articleList(
    _assetTransform: {
      format:$format
      seoName:$seoName
      crop:{
        xOrigin:10
        yOrigin:20
        width:50
        height:45
      }
      size:{
        height:100
        width:200
      }
      rotation:R90
      flip:HORIZONTAL_AND_VERTICAL
      quality:55
      width:123
      preferWebp:true
    }
  ) {
    items {
      _path
      featuredImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

Richiesta di distribuzione immagini ottimizzate per il web tramite URL

Se salvi la query come query persistente (ad esempio, con il nome dynamic-url-x) è possibile eseguire direttamente la query persistente.

Ad esempio, per eseguire direttamente gli esempi precedenti (salvati come query persistenti), utilizza i seguenti URL:

  • Parametro singolo; Query persistente con nome dynamic-url-x

    • http://localhost:4502/graphql/execute.json/wknd-shared/dynamic-url-x;seoName=xxx

      La risposta sarà simile a:

      Distribuzione delle immagini tramite parametri
  • Parametri multipli; Query persistente con nome dynamic

    • http://localhost:4502/graphql/execute.json/wknd-shared/dynamic;seoName=billiboy;format=GIF;

      ATTENZIONE

      Il finale ;è obbligatorio per terminare in modo pulito l’elenco dei parametri.

Limitazioni della distribuzione delle immagini

Esistono le seguenti limitazioni:

  • Modificatori applicati a tutte le immagini parte della query (parametri globali)

  • Intestazioni di memorizzazione in cache

    • Nessuna memorizzazione in cache sull'authoring
    • Memorizzazione in cache al momento della pubblicazione - tempo massimo di 10 minuti (non può essere modificato dal client)

GraphQL per AEM: riepilogo delle estensioni

Le operazioni di base delle query con GraphQL per AEM sono conformi alle specifiche standard di GraphQL. Per le query GraphQL con AEM sono disponibili alcune estensioni:

Query dell’endpoint di GraphQL da un sito Web esterno

Per accedere all’endpoint di GraphQL da un sito web esterno è necessario configurare i seguenti elementi:

Autenticazione

Vedi Autenticazione per query GraphQL AEM remote su frammenti di contenuto.

Domande frequenti

Domande poste:

  1. D: “quali sono le differenze tra l’API di GraphQL per AEM e l’API di Query Builder?

    • R:
      l’API di GraphQL per AEM offre il controllo totale dell’output JSON ed è uno standard di settore per l’esecuzione di query sui contenuti.
      In futuro, AEM prevede di investire nell’API di GraphQL per AEM.

Tutorial: guida introduttiva ad AEM headless e GraphQL

Cerchi un pratico tutorial? Dai un'occhiata al tutorial Guida introduttiva di headless AEM e GraphQL che illustra come creare ed esporre contenuti, utilizzati da un’app esterna, mediante le API GraphQL di AEM in uno scenario CMS headless.

In questa pagina