API GraphQL do AEM para uso com Fragmentos de conteúdo graphql-api-for-use-with-content-fragments
Saiba como usar Fragmentos de conteúdo no Adobe Experience Manager (AEM) com a API do AEM GraphQL para entrega de conteúdo headless.
A API do GraphQL do AEM usada com Fragmentos de conteúdo é altamente baseada na API padrão de código aberto do GraphQL.
Usar a API GraphQL no AEM permite a entrega eficiente dos Fragmentos de conteúdo aos clientes JavaScript em implementações CMS headless:
- Evitando solicitações de API iterativas como com REST,
- Garantindo que a entrega se limite aos requisitos específicos,
- Permitindo a entrega em massa exatamente daquilo que é necessário para a renderização, como resposta a uma única consulta de API.
- O AEM Commerce consome dados de uma plataforma do Commerce por meio do GraphQL.
- Fragmentos de conteúdo do AEM trabalham em conjunto com a API GraphQL do AEM (uma implementação personalizada, com base no GraphQL padrão), para fornecer conteúdo estruturado para uso em seus aplicativos.
Pré-requisitos prerequisites
Os clientes que usam o GraphQL devem instalar o AEM Content Fragment with GraphQL Index Package 1.0.5. Consulte as Notas de versão para obter mais detalhes.
A API GraphQL graphql-api
O GraphQL é:
-
"…um idioma de consulta para APIs e um tempo de execução para realizar essas consultas com seus dados existentes. O GraphQL fornece uma descrição completa e compreensível dos dados em sua API. Ele dá aos clientes o poder de solicitar exatamente o que precisam e nada mais, facilita a evolução das APIs ao longo do tempo e habilita ferramentas avançadas de desenvolvedor.".
Consulte GraphQL.org
-
"…uma especificação aberta para uma camada de API flexível. Coloque o GraphQL sobre seus back-end existentes para criar produtos mais rápido do que nunca…".
Consulte Explorar GraphQL.
-
"…uma linguagem de consulta de dados e especificação desenvolvidas internamente pela Facebook em 2012, antes de serem disponibilizadas publicamente em 2015. Ele oferece uma alternativa às arquiteturas baseadas em REST, com o objetivo de aumentar a produtividade do desenvolvedor e minimizar as quantidades de dados transferidos. O GraphQL é usado na produção por centenas de organizações de todos os tamanhos…"
Consulte Fundação GraphQL.
Para obter mais informações sobre a API do GraphQL, consulte as seguintes seções (entre muitos outros recursos):
A implementação do GraphQL para AEM é baseada na Biblioteca GraphQL Java™ padrão. Consulte:
Terminologia de GraphQL graphql-terminology
O GraphQL usa o seguinte:
-
- Os esquemas são gerados pelo AEM com base nos modelos de fragmento de conteúdo.
- Usando seus esquemas, o GraphQL apresenta os tipos e as operações permitidas no GraphQL para implementação no AEM.
-
-
O caminho no AEM que responde a consultas de GraphQL e fornece acesso aos esquemas de GraphQL.
-
Consulte Habilitação do endpoint de GraphQL para obter mais detalhes.
-
Consulte a Introdução ao GraphQL (GraphQL.org) para obter detalhes abrangentes, incluindo as Práticas recomendadas.
Tipos de consulta de GraphQL graphql-query-types
Com o GraphQL, é possível executar consultas para retornar:
-
Uma entrada única
O AEM fornece recursos para converter consultas (ambos os tipos) em Consultas Persistentes que são armazenadas em cache pelo Dispatcher e pela CDN.
Práticas recomendadas de consulta GraphQL (Dispatcher e CDN) graphql-query-best-practices
Consultas persistentes são o método recomendado para serem usadas em instâncias de publicação como:
- são armazenadas em cache
- eles são gerenciados centralmente pelo AEM
As consultas GraphQL que utilizam solicitações POST não são recomendadas, pois não são armazenadas em cache. Portanto, em uma instância padrão, o Dispatcher é configurado para bloquear essas consultas.
Embora o GraphQL também seja compatível com solicitações GET, essas solicitações podem atingir limites (por exemplo, o comprimento do URL) que podem ser evitados usando consultas persistentes.
Consulte Habilitar o cache de consultas persistentes para obter mais detalhes.
Interface GraphiQL graphiql-interface
Uma implementação da interface padrão GraphiQL está disponível para uso com o AEM GraphQL.
Essa interface permite inserir e testar diretamente consultas.
Por exemplo:
http://localhost:4502/content/graphiql.html
Ele fornece recursos como realce de sintaxe, preenchimento automático e sugestão automática, juntamente com um histórico e uma documentação online:
Casos de uso para ambientes de Autor e Publicação use-cases-author-publish-environments
Os casos de uso podem depender do tipo de ambiente AEM:
-
Ambiente de publicação; usado para:
- Consultar dados para o aplicativo JS (caso de uso padrão)
-
Ambiente de autor; usado para:
-
Consultar dados para “fins de gerenciamento de conteúdo”:
- O GraphQL no AEM é uma API somente leitura.
- A API REST pode ser usada para operações de CR(u)D.
-
Permissões permission
As permissões são necessárias para acessar o Assets.
As consultas do GraphQL são executadas com a permissão do usuário AEM da solicitação subjacente. Se o usuário não tiver acesso de leitura a alguns fragmentos (armazenados como Assets), eles não se tornarão parte do conjunto de resultados.
Além disso, o usuário deve ter acesso a um endpoint do GraphQL para executar consultas do GraphQL.
Geração de esquemas schema-generation
O GraphQL é uma API tipificada, o que significa que os dados devem ser estruturados e organizados claramente por tipo.
A especificação GraphQL fornece uma série de diretrizes sobre como criar uma API robusta para interrogar dados em uma determinada instância. Para concluir essas diretrizes, um cliente deve buscar o Esquema, que contém todos os tipos necessários para uma consulta.
Para fragmentos de conteúdo, os esquemas de GraphQL (estrutura e tipos) são baseados em modelos de fragmento de conteúdo habilitados e seus tipos de dados.
Por exemplo, se um usuário criar um modelo de fragmento de conteúdo chamado Article
, o AEM gerará um ArticleModel
do tipo GraphQL. Os campos desse tipo correspondem aos campos e tipos de dados definidos no modelo. Além disso, ele cria alguns pontos de entrada para as consultas que operam nesse tipo, como articleByPath
ou articleList
.
-
Um modelo de fragmento de conteúdo:
-
O esquema de GraphQL correspondente (saída da documentação automática do GraphiQL):
Esta imagem mostra que o tipo gerado
ArticleModel
contém vários campos.-
Três deles foram controlados pelo usuário:
author
,main
ereferencearticle
. -
Os outros campos foram adicionados automaticamente pelo AEM e representam métodos úteis para fornecer informações sobre um determinado fragmento de conteúdo. Neste exemplo,
(os campos auxiliares)_path
,_metadata
,_variations
.
-
-
Depois que um usuário cria um fragmento de conteúdo com base no modelo de Artigo, ele pode ser interrogado por meio do GraphQL. Para obter exemplos, consulte Exemplos de consulta (baseado em uma amostra da estrutura do fragmento de conteúdo para uso com GraphQL).
No GraphQL para AEM, o esquema é flexível. Essa flexibilidade significa que ela é gerada automaticamente sempre que um modelo de fragmento de conteúdo é criado, atualizado ou excluído. Os caches do esquema de dados também são atualizados quando você atualiza um modelo de fragmento de conteúdo.
O serviço GraphQL do Sites acompanha (em segundo plano) quaisquer modificações feitas em um modelo de fragmento de conteúdo. Quando as atualizações são detectadas, somente essa parte do esquema é gerada novamente. Essa otimização economiza tempo e oferece estabilidade.
Por exemplo, se você:
-
Instalar um pacote contendo
Content-Fragment-Model-1
eContent-Fragment-Model-2
:- Tipos de GraphQL para
Model-1
eModel-2
são gerados.
- Tipos de GraphQL para
-
Em seguida, o
Content-Fragment-Model-2
é modificado:-
Somente o tipo de GraphQL
Model-2
é atualizado. -
Já
Model-1
permanece o mesmo.
-
O esquema é distribuído por meio do mesmo endpoint das consultas de GraphQL, com o cliente lidando com o fato de que o esquema é chamado com a extensão GQLschema
. Por exemplo, executar uma simples solicitação GET
em /content/cq:graphql/global/endpoint.GQLschema
resulta na saída do esquema com o tipo de conteúdo: text/x-graphql-schema;charset=iso-8859-1
.
Geração de esquema - Modelos não publicados schema-generation-unpublished-models
Quando os fragmentos de conteúdo são aninhados, pode acontecer que um modelo de fragmento de conteúdo principal seja publicado, mas um modelo referenciado não.
Quando isso acontece, o AEM gera um esquema incompleto para o modelo de fragmento de conteúdo principal. Isso significa que a referência do fragmento, que depende do modelo não publicado, é removida do esquema.
Campos fields
Dentro do esquema, há campos individuais de duas categorias básicas:
-
Campos gerados.
Uma seleção de Tipos de dados é usada para criar campos com base em como você configura o modelo de fragmento de conteúdo. Os nomes de campo são retirados do campo Nome da propriedade do Tipo de dados.
- Também há a configuração Renderizar como a ser considerada, pois os usuários podem configurar determinados tipos de dados. Por exemplo, um campo de texto de linha única pode ser configurado para conter vários textos de linha única, escolhendo
multifield
na lista suspensa.
- Também há a configuração Renderizar como a ser considerada, pois os usuários podem configurar determinados tipos de dados. Por exemplo, um campo de texto de linha única pode ser configurado para conter vários textos de linha única, escolhendo
-
O GraphQL para AEM também gera vários campos auxiliares.
Esses campos são usados para identificar um fragmento de conteúdo ou obter mais informações sobre ele.
Tipos de dados data-types
O GraphQL do AEM oferece suporte a uma lista de tipos. Todos os tipos de dados do modelo de fragmento de conteúdo compatíveis e os tipos de GraphQL correspondentes são representados:
String
, [String]
String
Float
, [Float]
Boolean
Calendar
onlyDate
, onlyTime
e dateTime
String
[String]
String
Campo único:
Model
- Tipo de modelo, referenciado diretamenteMulticampo, com um tipo referenciado:
[Model]
- Matriz do tipo Model
, referenciado diretamente da matrizMulticampo, com vários tipos referenciados:
[AllFragmentModels]
- Matriz de todos os tipos de modelo, referenciado da matriz com tipo de uniãoCampos auxiliares helper-fields
Além dos tipos de dados para campos gerados pelo usuário, o GraphQL para AEM também gera vários campos helper para ajudar a identificar um Fragmento de conteúdo ou fornecer informações adicionais sobre um Fragmento de conteúdo.
Esses campos auxiliares estão marcados com um _
precedente, para distinguir entre o que foi definido pelo usuário e o que foi gerado automaticamente.
Caminho path
O campo de caminho é usado como um identificador no GraphQL do AEM. Ele representa o caminho do ativo Fragmento de conteúdo dentro do repositório do AEM. Esse caminho é escolhido como o identificador de um fragmento de conteúdo, pois ele:
- é exclusivo dentro do AEM,
- pode ser buscado facilmente.
O código a seguir exibe os caminhos de todos os Fragmentos de Conteúdo que foram criados com base no Modelo de Fragmento de Conteúdo Person
.
{
personList {
items {
_path
}
}
}
Para recuperar um único Fragmento de conteúdo de um tipo específico, você também deve determinar seu caminho primeiro. Por exemplo:
{
authorByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_path
firstName
name
}
}
}
Consulte Exemplo de consulta - um único fragmento específico de cidade.
Metadados metadata
Por meio do GraphQL, o AEM também expõe os metadados de um Fragmento de conteúdo. Os metadados são as informações que descrevem um fragmento de conteúdo, como o seguinte:
- o título de um fragmento de conteúdo
- o caminho da miniatura
- a descrição de um fragmento de conteúdo
- e a data de criação, entre outras.
Como os metadados são gerados por meio do Editor de esquemas e, como tal, não têm uma estrutura específica, o GraphQL tipo TypedMetaData
foi implementado para expor os metadados de um Fragmento de conteúdo. TypedMetaData
expõe as informações agrupadas pelos seguintes tipos escalares:
stringMetadata:[StringMetadata]!
stringArrayMetadata:[StringArrayMetadata]!
intMetadata:[IntMetadata]!
intArrayMetadata:[IntArrayMetadata]!
floatMetadata:[FloatMetadata]!
floatArrayMetadata:[FloatArrayMetadata]!
booleanMetadata:[BooleanMetadata]!
booleanArrayMetadata:[booleanArrayMetadata]!
calendarMetadata:[CalendarMetadata]!
calendarArrayMetadata:[CalendarArrayMetadata]!
Cada tipo escalar representa um único par de nome-valor ou uma matriz de pares de nome-valor, em que o valor desse par é do tipo em que foi agrupado.
Por exemplo, se você quiser recuperar o título de um fragmento de conteúdo, essa propriedade será uma propriedade de sequência; portanto, consulte todos os metadados de sequência:
Para consultar metadados:
{
personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_path
_metadata {
stringMetadata {
name
value
}
}
}
}
}
É possível exibir todos os tipos de metadados GraphQL, se você exibir o esquema GraphQL gerado. Todos os tipos de modelo têm o mesmo TypedMetaData
.
Lembre-se que
StringMetadata
e StringArrayMetadata
se referem ao que é armazenado no repositório, não a como você os recupera.stringMetadata
, você recebe uma matriz de todos os metadados armazenados no repositório como um String
. E se você chamar stringArrayMetadata
, receberá uma matriz de todos os metadados armazenados no repositório como String[]
.Consulte Exemplo de consulta para metadados - listar os metadados para prêmios denominados GB.
Variações variations
O campo _variations
foi implementado para simplificar a consulta das variações que um Fragmento de conteúdo possui. Por exemplo:
{
personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_variations
}
}
}
_variations
não contém uma variação master
, já que tecnicamente os dados originais (referenciados como Mestre na interface do usuário) não são considerados uma variação explícita.Consulte Exemplo de consulta - todas as cidades com uma variável nomeada.
Variáveis GraphQL graphql-variables
O GraphQL permite que as variáveis sejam colocadas na consulta. Para obter mais informações, consulte Documentação do GraphQL para variáveis.
Por exemplo, para obter todos os Fragmentos de conteúdo do tipo Article
que tenham uma variação específica, é possível especificar a variável variation
no GraphiQL.
### query
query GetArticlesByVariation($variation: String!) {
articleList(variation: $variation) {
items {
_path
author
_variations
}
}
}
### in query variables
{
"variation": "uk"
}
Diretivas GraphQL graphql-directives
No GraphQL, há uma possibilidade de alterar o query com base em variáveis, chamadas de Diretivas do GraphQL.
Por exemplo, é possível incluir o campo adventurePrice
em uma consulta para todos os AdventureModels
, com base em uma variável includePrice
.
### query
query GetAdventureByType($includePrice: Boolean!) {
adventureList {
items {
adventureTitle
adventurePrice @include(if: $includePrice)
}
}
}
### in query variables
{
"includePrice": true
}
Filtragem filtering
Também é possível usar a filtragem em consultas de GraphQL para retornar dados específicos.
A filtragem usa uma sintaxe baseada em operadores lógicos e expressões.
A menor parte é uma expressão única que pode ser aplicada ao conteúdo de um determinado campo. Ela compara o conteúdo do campo com um determinado valor constante.
Por exemplo, a expressão a seguir compararia o conteúdo do campo com o valor some text
e teria êxito se o conteúdo fosse igual ao valor. Caso contrário, a expressão falhará.:
{
value: "some text"
_op: EQUALS
}
Os operadores a seguir podem ser usados para comparar campos com um determinado valor:
EQUALS
String
, ID
, Boolean
EQUALS_NOT
String
, ID
CONTAINS
String
{ value: "mas", _op: CONTAINS }
corresponde a Christmas
, Xmas
, master
, …)CONTAINS_NOT
String
STARTS_WITH
ID
{ value: "/content/dam/", _op: STARTS_WITH
corresponde a /content/dam/path/to/fragment
, mas não a /namespace/content/dam/something
EQUAL
Int
, Float
UNEQUAL
Int
, Float
GREATER
Int
, Float
GREATER_EQUAL
Int
, Float
LOWER
Int
, Float
LOWER_EQUAL
Int
, Float
AT
Calendar
, Date
, Time
NOT_AT
Calendar
, Date
, Time
BEFORE
Calendar
, Date
, Time
AT_OR_BEFORE
Calendar
, Date
, Time
AFTER
Calendar
, Date
, Time
AT_OR_AFTER
Calendar
, Date
, Time
Alguns tipos também permitem especificar opções adicionais que modificam como uma expressão é avaliada:
_ignoreCase
String
time
corresponde a TIME
, time
, tImE
, …_sensitiveness
Float
float
sejam considerados iguais (para contornar limitações técnicas devido à representação interna de valores float
; deve ser evitada, pois essa opção pode ter um impacto negativo no desempenhoAs expressões podem ser combinadas a um conjunto com a ajuda de um operador lógico (_logOp
):
OR
- o conjunto de expressões é bem-sucedido se pelo menos uma expressão for bem-sucedidaAND
- o conjunto de expressões terá êxito se todas as expressões tiverem êxito (padrão)
Cada campo pode ser filtrado por seu próprio conjunto de expressões. Os conjuntos de expressões de todos os campos mencionados no argumento de filtro são eventualmente combinados por seu próprio operador lógico.
Uma definição de filtro (transmitida como o argumento filter
para uma consulta) contém:
- Uma subdefinição para cada campo (o campo pode ser acessado por meio de seu nome; por exemplo, há um campo
lastName
no filtro para o campolastName
no Tipo de dados (campo)) - Cada subdefinição contém a matriz
_expressions
, fornecendo o conjunto de expressões, e o campo_logOp
que define o operador lógico com o qual as expressões devem ser combinadas - Cada expressão é definida pelo valor (campo
value
) e o operador (campo_operator
) com o qual o conteúdo de um campo deve ser comparado
Você pode omitir _logOp
se quiser combinar itens com AND
e _operator
se quiser verificar a igualdade, pois esses valores são o padrão.
O exemplo a seguir demonstra uma consulta completa que filtra todas as pessoas que têm um lastName
igual a Provo
ou que contêm sjö
, independentemente do caso:
{
authorList(filter: {
lastname: {
_logOp: OR
_expressions: [
{
value: "sjö",
_operator: CONTAINS,
_ignoreCase: true
},
{
value: "Provo"
}
]
}
}) {
items {
lastName
firstName
}
}
}
Ao executar uma consulta GraphQL usando variáveis opcionais, se um valor específico for não fornecido para a variável opcional, a variável será ignorada na avaliação do filtro. Ou seja, os resultados da consulta conterão todos os valores, null
e não null
, para a propriedade relacionada à variável de filtro.
null
for explicitamente especificado para essa variável, o filtro corresponderá somente a valores null
para a propriedade correspondente.Por exemplo, na consulta abaixo, onde nenhum valor é especificado para a propriedade lastName
:
query getAuthorsFilteredByLastName($authorLastName: String) {
authorList(filter:
{
lastName: {_expressions: {value: $authorLastName}
}}) {
items {
lastName
}
}
}
Todos os autores serão retornados:
{
"data": {
"authorList": {
"items": [
{
"lastName": "Hammer"
},
{
"lastName": "Provo"
},
{
"lastName": "Wester"
},
{
"lastName": null
},
...
]
}
}
}
Embora também seja possível filtrar em campos aninhados, isso não é recomendado, pois pode causar problemas de desempenho.
Para obter mais exemplos, consulte:
-
detalhes da GraphQL para extensões do AEM
-
Exemplos de consulta usando esta amostra de conteúdo e estrutura
- E a amostra de conteúdo e estrutura preparada para uso em consultas de exemplo
Classificação sorting
Esse recurso permite classificar os resultados da consulta de acordo com um campo especificado.
Os critérios de classificação são:
-
é uma lista de valores separados por vírgulas que representa o caminho do campo
-
o primeiro campo na lista define a ordem de classificação principal
- o segundo campo é usado se dois valores do critério de classificação principal forem iguais
- o terceiro campo é usado se os dois primeiros critérios forem iguais e assim por diante.
-
notação pontilhada, ou seja,
field1.subfield.subfield
e assim por diante.
-
-
com uma direção de ordem opcional
- ASC (crescente) ou DESC (decrescente); como padrão, ASC é aplicado
- a direção pode ser especificada por campo; essa capacidade significa que você pode classificar um campo em ordem crescente, outro em ordem decrescente (nome, nome DESC)
Por exemplo:
query {
authorList(sort: "lastName, firstName") {
items {
firstName
lastName
}
}
}
E também:
{
authorList(sort: "lastName DESC, firstName DESC") {
items {
lastName
firstName
}
}
}
Também é possível classificar um campo dentro de um fragmento aninhado, usando o formato de nestedFragmentname.fieldname
.
Por exemplo:
query {
articleList(sort: "authorFragment.lastName") {
items {
title
authorFragment {
firstName
lastName
birthDay
}
slug
}
}
}
Paginação paging
Esse recurso permite executar a paginação em tipos de consulta que retornam uma lista. Dois métodos são fornecidos:
offset
elimit
em uma consultaList
first
eafter
em uma consultaPaginated
Consulta de lista - offset e limit list-offset-limit
Em uma consulta de ...List
você pode usar offset
e limit
para retornar um subconjunto específico de resultados:
offset
: especifica o primeiro conjunto de dados a ser retornadolimit
: especifica o número máximo de conjuntos de dados a serem retornados
Por exemplo, para exibir uma página de resultados que contém até cinco artigos, começando do quinto artigo da lista de resultados completa:
query {
articleList(offset: 5, limit: 5) {
items {
authorFragment {
lastName
firstName
}
}
}
}
-
A paginação exige uma ordem de classificação estável para funcionar corretamente em várias consultas que solicitam páginas diferentes do mesmo conjunto de resultados. Por padrão, ele usa o caminho do repositório de cada item do conjunto de resultados para garantir que a ordem seja sempre a mesma. Se uma ordem de classificação diferente for usada e se essa classificação não puder ser feita no nível de consulta JCR, haverá um impacto negativo no desempenho. O motivo é que todo o conjunto de resultados deve ser carregado na memória antes que as páginas sejam determinadas.
-
Quanto maior o deslocamento, mais tempo leva para ignorar os itens do conjunto completo de resultados da consulta JCR. Uma solução alternativa para grandes conjuntos de resultados é usar a consulta paginada com os métodos
first
eafter
.
Consulta paginada - first e after paginated-first-after
O tipo de consulta ...Paginated
reutiliza a maioria dos recursos do tipo de consulta ...List
(filtragem, classificação), mas, em vez de usar os argumentos offset
/limit
, ele usa os argumentos first
/after
, definidos pela Especificação de conexões do cursor GraphQL. Você pode encontrar uma introdução mais simplificada na Introdução ao GraphQL.
first
: os primeirosn
itens a serem retornados.
O padrão é50
.
O máximo é100
.after
: o cursor que determina o início da página solicitada. O item representado pelo cursor não está incluído no conjunto de resultados. O cursor de um item é determinado pelo campocursor
da estruturaedges
.
Por exemplo, exibe uma página de resultados contendo até cinco aventuras, começando pelo item de cursor especificado na lista de resultados completa:
query {
adventurePaginated(first: 5, after: "ODg1MmMyMmEtZTAzMy00MTNjLThiMzMtZGQyMzY5ZTNjN2M1") {
edges {
cursor
node {
title
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
-
Por padrão, a paginação usa a UUID do nó do repositório que representa o fragmento para ordenação, garantindo que a ordem dos resultados seja sempre a mesma. Quando
sort
é usado, o UUID será usado implicitamente para garantir uma ordem de classificação exclusiva, mesmo para dois itens com chaves de classificação idênticas. -
Devido a restrições técnicas internas, o desempenho será reduzido se a classificação e a filtragem forem aplicadas em campos aninhados. Portanto, use os campos de filtro/classificação armazenados no nível raiz. Essa técnica também é a maneira recomendada se você quiser consultar grandes conjuntos de resultados paginados.
Consultas persistentes do GraphQL - ativação do armazenamento em cache no Dispatcher graphql-persisted-queries-enabling-caching-dispatcher
O armazenamento em cache de consultas persistentes não é ativado por padrão no Dispatcher. A ativação padrão não é possível, pois os clientes que usam o CORS (Cross-Origin Resource Sharing, Compartilhamento de recursos entre origens) precisam revisar e possivelmente atualizar a configuração do Dispatcher.
Vary
.Habilitar armazenamento em cache de consultas persistentes enable-caching-persisted-queries
Para habilitar o armazenamento em cache de consultas persistentes, as seguintes atualizações dos arquivos de configuração do Dispatcher são necessárias:
-
<conf.d/rewrites/base_rewrite.rules>
code language-xml # Allow the dispatcher to be able to cache persisted queries - they need an extension for the cache file RewriteCond %{REQUEST_URI} ^/graphql/execute.json RewriteRule ^/(.*)$ /$1;.json [PT]
note note NOTE O Dispatcher adiciona o sufixo .json
a todas as URLS de consulta persistentes, para que o resultado possa ser armazenado em cache.Isso garante que a consulta esteja em conformidade com os requisitos do Dispatcher para documentos que podem ser armazenados em cache. Para obter mais detalhes, consulte Como o Dispatcher retorna documentos? -
<conf.dispatcher.d/filters/ams_publish_filters.any>
code language-xml # Allow GraphQL Persisted Queries & preflight requests /0110 { /type "allow" /method '(GET|POST|OPTIONS)' /url "/graphql/execute.json*" }
Configuração do CORS no Dispatcher cors-configuration-in-dispatcher
Clientes que usam solicitações do CORS podem precisar revisar e atualizar sua configuração do CORS no Dispatcher.
-
O cabeçalho
Origin
não deve ser transmitido para a publicação do AEM por meio da Dispatcher:- Verifique o arquivo
clientheaders.any
.
- Verifique o arquivo
-
Em vez disso, as solicitações do CORS devem ser avaliadas para as origens permitidas no nível da Dispatcher. Essa abordagem também garante que os cabeçalhos relacionados ao CORS sejam definidos corretamente, em um local, em todos os casos.
- Essa configuração deve ser adicionada ao arquivo
vhost
. Um exemplo de configuração é fornecido abaixo; para simplificar, somente a parte relacionada ao CORS foi fornecida. Você pode adaptá-la aos seus casos de uso específicos.
code language-xml <VirtualHost *:80> ServerName "publish" # ... <IfModule mod_headers.c> Header add X-Vhost "publish" ################## Start of the CORS specific configuration ################## SetEnvIfExpr "req_novary('Origin') == ''" CORSType=none CORSProcessing=false SetEnvIfExpr "req_novary('Origin') != ''" CORSType=cors CORSProcessing=true CORSTrusted=false SetEnvIfExpr "req_novary('Access-Control-Request-Method') == '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != '' " CORSType=invalidpreflight CORSProcessing=false SetEnvIfExpr "req_novary('Access-Control-Request-Method') != '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != '' " CORSType=preflight CORSProcessing=true CORSTrusted=false SetEnvIfExpr "req_novary('Origin') -strcmatch 'https://%{HTTP_HOST}*'" CORSType=samedomain CORSProcessing=false # For requests that require CORS processing, check if the Origin can be trusted SetEnvIfExpr "%{HTTP_HOST} =~ /(.*)/ " ParsedHost=$1 ################## Adapt the regex to match CORS origin for your environment SetEnvIfExpr "env('CORSProcessing') == 'true' && req_novary('Origin') =~ m#(https://.*.your-domain.tld(:\d+)?$)#" CORSTrusted=true # Extract the Origin header SetEnvIfNoCase ^Origin$ ^https://(.*)$ CORSTrustedOrigin=https://$1 # Flush If already set Header unset Access-Control-Allow-Origin Header unset Access-Control-Allow-Credentials # Trusted Header always set Access-Control-Allow-Credentials "true" "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Allow-Origin "%{CORSTrustedOrigin}e" "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Allow-Methods "GET" "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Max-Age 1800 "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Allow-Headers "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers" "expr=reqenv('CORSTrusted') == 'true'" # Non-CORS or Not Trusted Header unset Access-Control-Allow-Credentials "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" Header unset Access-Control-Allow-Origin "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" Header unset Access-Control-Allow-Methods "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" Header unset Access-Control-Max-Age "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" # Always vary on origin, even if its not there. Header merge Vary Origin # CORS - send 204 for CORS requests which are not trusted RewriteCond expr "reqenv('CORSProcessing') == 'true' && reqenv('CORSTrusted') == 'false'" RewriteRule "^(.*)" - [R=204,L] ################## End of the CORS specific configuration ################## </IfModule> <Directory /> # ... </Directory> # ... </VirtualHost>
- Essa configuração deve ser adicionada ao arquivo
GraphQL para AEM - resumo das extensões graphql-extensions
A operação básica de consultas com o GraphQL para AEM adere à especificação GraphQL padrão. Para consultas do GraphQL com AEM, há algumas extensões:
-
Se você precisar de um único resultado:
- use o nome do modelo; por exemplo, cidade
-
Se você espera uma lista de resultados:
- adicione
List
ao nome do modelo; por exemplo,cityList
- Consulte Exemplo de consulta - Todas as informações sobre todas as cidades
É possível:
-
ASC
: crescenteDESC
: decrescente
-
Retorna uma página de resultados usando uma dessas duas opções:
-
Consulte Exemplo de consulta - Todas as informações sobre todas as cidades
- adicione
-
O filtro
includeVariations
está incluído no tipo de consultaList
. Para recuperar as Variações de Fragmento de Conteúdo nos resultados da consulta, o filtroincludeVariations
deve ser definido comotrue
.note caution CAUTION O filtro includeVariations
não pode ser usado junto com o campo gerado pelo sistema_variation
. -
Se quiser usar um operador OR lógico:
- use
_logOp: OR
- Consulte Exemplo de consulta - Todas as pessoas cujo nome é “Jobs” ou “Smith”
- use
-
O operador AND lógico também existe, mas está (muitas vezes) implícito
-
Você pode consultar nos nomes de campos que correspondem aos campos no modelo de fragmento de conteúdo
-
Além dos campos do modelo, há alguns campos gerados pelo sistema (precedidos por um sublinhado):
-
Para conteúdo:
-
_locale
: para revelar a língua; com base no Gerenciador de idiomas -
_metadata
: para revelar metadados do fragmento -
_model
: permite a consulta para um modelo de fragmento de conteúdo (caminho e título) -
_path
: o caminho para o fragmento de conteúdo no repositório -
_reference
: para revelar referências; incluindo referências em linha no Editor de Rich Text -
_variation
: para revelar variações específicas no fragmento de conteúdonote note NOTE Se a variação especificada não existir para um Fragmento de conteúdo, a variação principal será retornada como padrão (fallback). note caution CAUTION O campo _variation
gerado pelo sistema não pode ser usado junto com o filtroincludeVariations
. -
_tags
: para revelar as IDs dos Fragmentos de Conteúdo ou Variações que contêm marcas; esta lista é uma matriz decq:tags
identificadores.- Consulte Exemplo de consulta - Nomes de todas as cidades marcadas como Cidades para passeio
- Consulte Exemplo de consulta para variações de fragmento de conteúdo de um determinado modelo que tem uma tag específica anexada
note note NOTE As tags também podem ser consultadas listando os metadados de um fragmento de conteúdo.
-
-
E operações:
-
_operator
: aplica operadores específicos;EQUALS
,EQUALS_NOT
,GREATER_EQUAL
,LOWER
,CONTAINS
eSTARTS_WITH
-
_apply
: para aplicar condições específicas; por exemplo,AT_LEAST_ONCE
-
_ignoreCase
: para ignorar se os caracteres são maiúsculos ou minúsculos ao consultar
-
-
-
Os tipos de união GraphQL são compatíveis:
-
Fazer o fallback ao consultar fragmentos aninhados:
- Se a variação solicitada não existir em um fragmento aninhado, a variação Principal será retornada.
Filtro CORS cors-filter
Para acessar o endpoint do GraphQL, configure uma política do CORS no repositório Git do cliente. Essa configuração é feita adicionando um arquivo de configuração OSGi CORS apropriado para um ou mais endpoints desejados.
Esta configuração deve especificar uma origem de site confiável alloworigin
ou alloworiginregexp
para a qual o acesso deve ser concedido.
Por exemplo, para conceder acesso ao endpoint do GraphQL e ao endpoint de consultas persistentes para https://my.domain
, você pode usar:
{
"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/.*"
]
}
Se você tiver configurado um caminho personalizado para o endpoint, também poderá usá-lo no allowedpaths
.
Filtro de referenciador referrer-filter
Além da configuração do CORS, um filtro Referenciador deve ser configurado para permitir acesso de hosts de terceiros.
Esse filtro é feito adicionando um arquivo de configuração de Filtro referenciador OSGi apropriado que:
- especifica um nome de host de site confiável;
allow.hosts
ouallow.hosts.regexp
- concede acesso a esse nome de host.
Por exemplo, para conceder acesso a solicitações com o referenciador my.domain
, é possível:
{
"allow.empty":false,
"allow.hosts":[
"my.domain"
],
"allow.hosts.regexp":[
""
],
"filter.methods":[
"POST",
"PUT",
"DELETE",
"COPY",
"MOVE"
],
"exclude.agents.regexp":[
""
]
}
- conceder acesso somente a domínios confiáveis
- certificar-se de que nenhuma informação sensível seja exposta
- não usar uma sintaxe [*] curinga; essa funcionalidade desabilita o acesso autenticado ao ponto de extremidade do GraphQL e também o expõe ao mundo inteiro.
Limitações limitations
Para se proteger contra possíveis problemas, há limitações padrão impostas às consultas:
- A consulta não pode conter mais de 1 milhão (1024 * 1024) de caracteres
- A consulta não pode conter mais de 15.000 tokens
- A consulta não pode conter mais de 200.000 tokens de espaço em branco
Você também precisa estar ciente de:
-
Um erro de conflito de campo será retornado quando sua consulta do GraphQL contiver campos com o mesmo nome em dois (ou mais) modelos, e as seguintes condições forem atendidas:
-
Assim, onde:
- Dois (ou mais) modelos são usados como possíveis referências; quando eles são definidos como um Tipo de modelo permitido na referência de Fragmento de conteúdo.
e:
- Esses dois modelos têm campos com um nome comum; ou seja, o mesmo nome ocorre em ambos os modelos.
e
- Esses campos são de tipos de dados diferentes.
-
Por exemplo:
-
Quando dois (ou mais) fragmentos com modelos diferentes (por exemplo,
M1
,M2
) são usados como possíveis referências (Referência de conteúdo ou Referência de fragmento) de outro fragmento; por exemplo,Fragment1
MultiField/List
-
E esses dois fragmentos com modelos diferentes (
M1
,M2
) têm campos com o mesmo nome, mas tipos diferentes.
Para ilustrar:M1.Title
comoText
M2.Title
comoText/MultiField
-
Um erro de conflito de campo ocorrerá se a consulta GraphQL contiver o campo
Title
.
-
-
Autenticação authentication
Consulte Autenticação para consultas de GraphQL remotas do AEM sobre fragmentos de conteúdo.
Perguntas frequentes faqs
Perguntas que surgiram:
-
P: “Qual a diferença entre a API GraphQL do AEM e a API do Construtor de consultas?”
- R: “A API GraphQL do AEM oferece controle total sobre a saída em JSON e é um padrão do setor para consulta de conteúdo.
No futuro, o AEM planeja investir na API AEM GraphQL."
- R: “A API GraphQL do AEM oferece controle total sobre a saída em JSON e é um padrão do setor para consulta de conteúdo.
Tutorial - Introdução ao AEM Headless e GraphQL tutorial
Procurando um tutorial prático? Veja o tutorial completo de Introdução ao AEM Headless e GraphQL que ilustra como criar e expor conteúdo usando as APIs GraphQL do AEM e consumi-lo por meio de um aplicativo externo, em um cenário de CMS headless.