用于内容片段的 AEM GraphQL API graphql-api-for-use-with-content-fragments
了解如何在Adobe Experience Manager (AEM)中将内容片段与AEM GraphQL API用于Headless内容投放。
与内容片段一起使用的AEM GraphQL API很大程度上依赖于标准的开源GraphQL API。
在 AEM 中使用 GraphQL API 可以在 Headless CMS 实施中,高效地将内容片段投放到 JavaScript 客户端:
- 避免 REST 中的迭代 API 请求,
- 确保将投放限制到特定要求,
- 允许作为对单个 API 查询的响应,批量精确投放所需呈现的内容。
- AEM Commerce 通过 GraphQL 使用来自 Commerce 平台的数据。
- AEM 内容片段与 AEM GraphQL API(一种自定义实施,基于标准 GraphQL)配合使用,提供结构化内容用于您的应用程序。
先决条件 prerequisites
使用GraphQL的客户应安装AEM内容片段和GraphQL索引包1.0.5。有关详细信息,请参阅发行说明。
GraphQL API graphql-api
GraphQL 是:
-
“…一种用于 API 和运行时的查询语言,使用您的现有数据满足这些查询。GraphQL提供了API中数据的完整且可理解的描述。 它使客户端能够精确地请求他们所需的内容,而不用再请求其他内容,使API更容易随时间演进,并提供了强大的开发人员工具。”
请参阅 GraphQL.org。
-
“…一种面向灵活 API 层的开发规格。将GraphQL放在现有后端之上,以便您能够以比以往更快的速度构建产品…”。
请参阅探索 GraphQL。
-
“”……一种数据查询语言和规范,由Facebook在2012年内部开发,然后在2015年公开开源发布。 它提供了对基于 REST 的架构的替代,其目的是为了提高开发人员的工作效率并尽可能减少传输的数据量。GraphQL 已由各种规模的数百家组织用于生产环境中…”
请参阅 GraphQL 基础。
有关GraphQL API的更多信息,请参阅以下部分(以及其他许多资源):
-
位于 graphql.org:
-
位于 graphql.com:
GraphQL for AEM实施基于标准GraphQL Java™库。 请参阅:
-
GitHub上的GraphQL Java™
GraphQL 术语 graphql-terminology
GraphQL 使用以下对象:
-
- AEM 基于内容片段模型来生成架构。
- 使用您的架构,GraphQL 呈现允许用于 GraphQL for AEM 实施的类型和操作。
-
-
AEM 中的路径,对应于 GraphQL 查询,提供对 GraphQL 架构的访问。
-
有关更多详细信息,请参阅启用 GraphQL 端点。
-
请参阅 (GraphQL.org) GraphQL 简介获取全面的详细信息,包括最佳实践。
GraphQL 查询类型 graphql-query-types
使用 GraphQL,您可以执行查询以返回:
-
单个条目
AEM提供将查询(两种类型)转换为Dispatcher和CDN缓存的持久查询的功能。
GraphQL 查询最佳实践(Dispatcher 和 CND) graphql-query-best-practices
持久查询是推荐用于发布实例的方法:
- 它们被缓存
- 它们由AEM集中管理
不建议使用 POST 请求的 GraphQL 查询,因为它们未缓存,因此在默认实例中,Dispatcher 配置为阻止此类查询。
虽然GraphQL也支持GET请求,但这些请求可能会达到限制(例如URL的长度),而使用持久查询可以避免这些限制。
有关更多详细信息,请参阅启用持久化查询缓存。
GraphiQL接口 graphiql-interface
标准GraphiQL接口的实现可用于AEM GraphQL。
利用此界面,可直接输入和测试查询。
例如:
http://localhost:4502/content/graphiql.html
它提供语法突出显示、自动完成、自动建议等功能,以及历史记录和在线文档:
针对创作环境和发布环境的用例 use-cases-author-publish-environments
用例可以取决于AEM环境的类型:
-
发布环境;用于:
- 查询 JS 应用程序的数据(标准用例)
-
创作环境;用于:
-
查询用于“内容管理用途”的数据:
- AEM中的GraphQL是一个只读API。
- REST API 可用于 CR(u)D 操作。
-
权限 permission
访问Assets需要权限。
GraphQL查询是在基础请求的AEM用户的权限下运行的。 如果用户对某些片段(存储为Assets)没有读取权限,它们就不会成为结果集的一部分。
此外,用户必须有权访问GraphQL端点才能运行GraphQL查询。
架构生成 schema-generation
GraphQL是一种类型的API,这意味着数据必须清楚地按类型构建和组织结构。
GraphQL 规范提供了一系列准则,说明如何创建可靠的 API 用于询问特定实例上的数据。要完成这些准则,客户端必须提取架构,其中包含查询所需的所有类型。
对于内容片段,GraphQL 架构(结构和类型)基于 已启用 内容片段模型及其数据类型。
例如,如果创建内容片段模型的用户调用 Article
,则 AEM 生成 GraphQL 类型 ArticleModel
。此类型中的字段对应于在模型中定义的字段和数据类型。此外,它还为操作此类型的查询创建一些入口点,例如 articleByPath
或 articleList
。
-
内容片段模型:
-
对应的 GraphQL 架构(来自 GraphiQL 自动文档的输出):
此图像显示生成的类型
ArticleModel
包含多个字段。-
其中三个由用户控制:
author
、main
和referencearticle
。 -
其他字段由AEM自动添加,表示用于提供有关特定内容片段的有用方法。 在此示例中,
(帮助程序字段)_path
、_metadata
、_variations
。
-
-
用户基于 Article 模型创建内容片段之后,可以通过 GraphQL 询问该模型。例如,请参阅示例查询(基于用于 GraphQL 的示例内容片段结构)。
在 GraphQL for AEM 中,架构是灵活的。这种灵活性意味着每次创建、更新或删除内容片段模型时都会自动生成架构。 数据架构缓存还可在更新内容片段模型时刷新。
Sites GraphQL 服务监听(在后台)对内容片段模型所作的任何更改。检测到更新时,仅重新生成架构的该部分。此优化可节省时间并提供稳定性。
例如,如果您:
-
安装包含
Content-Fragment-Model-1
和Content-Fragment-Model-2
的软件包:- 生成用于
Model-1
和Model-2
的 GraphQL 类型。
- 生成用于
-
然后修改
Content-Fragment-Model-2
:-
只更新
Model-2
个GraphQL类型。 -
而
Model-1
保持不变。
-
架构通过与 GraphQL 查询相同的端点提供,客户端处理使用扩展 GQLschema
调用架构的实际情况。例如,对/content/cq:graphql/global/endpoint.GQLschema
执行简单的GET
请求会导致架构的输出具有内容类型: text/x-graphql-schema;charset=iso-8859-1
。
架构生成 – 未发布的模型 schema-generation-unpublished-models
当内容片段嵌套时,可能会出现的情况是发布了父内容片段模型,但未发布引用的模型。
发生这种情况时,AEM为父内容片段模型生成一个 不完整的 架构。 这意味着依赖于未发布模型的片段引用将从架构中删除。
字段 fields
在架构中,有两个基本类别的单独字段:
数据类型 data-types
GraphQL for AEM 支持一个类型列表。所有支持的内容片段模型数据类型和对应的 GraphQL 类型呈现如下:
String
、[String]
String
Float
,[Float]
Boolean
Calendar
onlyDate
、onlyTime
、dateTime
String
[String]
String
单个字段:
Model
— 直接引用的模型类型多字段,具有一个引用的类型:
[Model]
— 直接从数组引用的类型为
Model
的数组多字段,具有多个引用的类型: [AllFragmentModels]
— 从具有合并类型的数组引用的所有模型类型的数组帮助程序字段 helper-fields
在用户生成的字段数据类型之外,GraphQL for AEM还生成了多个 帮助程序 字段,用于帮助标识内容片段,或提供有关内容片段的更多信息。
这些帮助程序字段使用前缀 _
标记,用于区分哪些字段由用户定义,哪些字段为自动生成。
路径 path
路径字段用作 AEM GraphQL 中的标识符。它代表 AEM 存储库中内容片段资源的路径。此路径被选为内容片段的标识符,因为它:
- 在 AEM 中唯一
- 可以轻松地提取
以下代码显示基于内容片段模型Person
创建的所有内容片段的路径。
{
personList {
items {
_path
}
}
}
要检索特定类型的单个内容片段,您还必须先确定其路径。 例如:
{
authorByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_path
firstName
name
}
}
}
请参阅示例查询 – 一个特定城市片段。
元数据 metadata
通过 GraphQL,AEM 还可以公开内容片段的元数据。元数据是描述内容片段的信息,如下所示:
- 内容片段的标题
- 缩略图路径
- 内容片段的描述
- 以及创建日期,等等。
由于元数据通过架构编辑器生成,因此没有特定结构,所以实施了 TypedMetaData
GraphQL 类型以公开内容片段的元数据。TypedMetaData
公开按以下标量类型分组的信息:
stringMetadata:[StringMetadata]!
stringArrayMetadata:[StringArrayMetadata]!
intMetadata:[IntMetadata]!
intArrayMetadata:[IntArrayMetadata]!
floatMetadata:[FloatMetadata]!
floatArrayMetadata:[FloatArrayMetadata]!
booleanMetadata:[BooleanMetadata]!
booleanArrayMetadata:[booleanArrayMetadata]!
calendarMetadata:[CalendarMetadata]!
calendarArrayMetadata:[CalendarArrayMetadata]!
每个标量类型表示一个名称-值对或者名称-值对数组,而该对的值是它所分组到的类型。
例如,如果您要检索内容片段的标题,此属性是字符串属性,因此您将查询所有字符串元数据:
要查询元数据,请执行以下操作:
{
personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_path
_metadata {
stringMetadata {
name
value
}
}
}
}
}
如果您查看生成的 GraphQL 架构,可以查看所有元数据 GraphQL 类型。所有模型类型具有相同的 TypedMetaData
。
请记住,
StringMetadata
和 StringArrayMetadata
均引用存储在存储库中的内容,而非您如何检索它们。stringMetadata
字段,您将以String
的形式接收存储在存储库中所有元数据的数组。 如果您调用stringArrayMetadata
,则会以String[]
的形式接收存储在存储库中的所有元数据的数组。请参阅元数据的示例查询 – 列出标题为 GB 的奖励的元数据。
变体 variations
_variations
字段已实施以简化查询内容片段具有的变体。例如:
{
personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_variations
}
}
}
_variations
字段不包含master
变量,从技术上讲,原始数据(在UI中称为 主变量)不被视为显式变量。GraphQL 变量 graphql-variables
GraphQL 允许在查询中放入变量。有关详细信息,请参阅 GraphQL 的变量文档。
例如,要获取具有特定变体的类型为 Article
的所有内容片段,您可以在 GraphiQL 中指定变量 variation
。
### query
query GetArticlesByVariation($variation: String!) {
articleList(variation: $variation) {
items {
_path
author
_variations
}
}
}
### in query variables
{
"variation": "uk"
}
GraphQL 指令 graphql-directives
在GraphQL中,可以根据变量更改查询,这称为GraphQL指令。
例如,您可在针对所有 AdventureModels
、基于变量 includePrice
的查询中包含 adventurePrice
字段。
### query
query GetAdventureByType($includePrice: Boolean!) {
adventureList {
items {
adventureTitle
adventurePrice @include(if: $includePrice)
}
}
}
### in query variables
{
"includePrice": true
}
筛选 filtering
您还可以筛选 GraphQL 查询以返回特定数据。
筛选使用基于逻辑运算符和表达式的语法。
最原子的部分是可以应用于特定字段内容的单个表达式。它将字段的内容与给定的常量值进行比较。
例如,以下表达式会将字段的内容与值some text
进行比较,如果内容等于该值,则成功。 否则,表达式将失败。:
{
value: "some text"
_op: EQUALS
}
以下运算符可用于将字段与特定值进行比较:
EQUALS
String
、ID
、Boolean
EQUALS_NOT
String
、ID
CONTAINS
String
{ value: "mas", _op: CONTAINS }
与Christmas
、Xmas
、master
匹配……)CONTAINS_NOT
String
STARTS_WITH
ID
{ value: "/content/dam/", _op: STARTS_WITH
匹配/content/dam/path/to/fragment
,但不匹配/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
某些类型还允许您指定其他选项来修改表达式的计算方式:
_ignoreCase
String
time
的值与TIME
、time
、tImE
匹配……_sensitiveness
Float
float
值视为相同(以解决由于 float
值的内部表示引起的技术限制;应该避免,因为此选项可能有负面影响对性能的影响表达式可以在逻辑运算符 (_logOp
) 的帮助下组合成一个集合:
OR
— 如果至少有一个表达式成功,则表达式集将成功AND
— 如果所有表达式都成功,则表达式集将成功(默认)
每个字段都可以通过其自己的一组表达式进行过滤。过滤器参数中提到的所有字段的表达式集最终将由其自己的逻辑运算符组合。
过滤器定义(作为 filter
参数传递给查询)包含:
- 每个字段的子定义(可以通过其名称访问该字段,例如,数据(字段)类型中的
lastName
字段的过滤器中有一个lastName
字段) - 每个子定义包含
_expressions
数组,提供表达式集,以及_logOp
字段,该字段定义表达式应与之组合的逻辑运算符 - 每个表达式由值(
value
字段)和运算符(_operator
字段)定义,字段的内容应该与之进行比较
如果要将项目与AND
和_operator
组合,则可以省略_logOp
;如果要检查是否相等,则可以省略,因为这些值是默认值。
以下示例演示了一个完整的查询,该查询过滤所有 lastName
为 Provo
或包含 sjö
的人员,与大小写无关:
{
authorList(filter: {
lastname: {
_logOp: OR
_expressions: [
{
value: "sjö",
_operator: CONTAINS,
_ignoreCase: true
},
{
value: "Provo"
}
]
}
}) {
items {
lastName
firstName
}
}
}
使用可选变量执行GraphQL查询时,如果为可选变量提供的特定值为 而非,则在筛选器求值中将忽略该变量。 这意味着,查询结果将包含与筛选器变量相关的属性的所有值,包括null
而非null
。
null
值是为此类变量显式指定的**,则筛选器将仅匹配相应属性的null
值。例如,在下面的查询中,没有为属性lastName
指定值:
query getAuthorsFilteredByLastName($authorLastName: String) {
authorList(filter:
{
lastName: {_expressions: {value: $authorLastName}
}}) {
items {
lastName
}
}
}
将返回所有作者:
{
"data": {
"authorList": {
"items": [
{
"lastName": "Hammer"
},
{
"lastName": "Provo"
},
{
"lastName": "Wester"
},
{
"lastName": null
},
...
]
}
}
}
虽然您也可以对嵌套字段进行筛选,但不建议这样做,因为这可能会导致性能问题。
有关更多示例,请参阅:
-
GraphQL for AEM 扩展的详细信息
-
- 以及准备用于示例查询的示例内容和结构
排序 sorting
此功能让您根据指定字段对查询结果进行排序。
排序标准:
-
是以逗号分隔的值列表,表示字段路径
-
列表中的第一个字段定义主要排序顺序
- 如果主要排序标准的两个值相等,则使用第二个字段
- 如果前两个标准相等,则使用第三个字段,依此类推。
-
点分符号,即
field1.subfield.subfield
,以此类推。
-
-
带有可选的订单方向
- ASC(升序)或 DESC(降序);作为默认 ASC 应用
- 可以按字段指定方向;这种能力意味着您可以对一个字段按升序排序,对另一个字段按降序排序(名称、名字DESC)
例如:
query {
authorList(sort: "lastName, firstName") {
items {
firstName
lastName
}
}
}
也可以:
{
authorList(sort: "lastName DESC, firstName DESC") {
items {
lastName
firstName
}
}
}
您还可以使用 nestedFragmentname.fieldname
的格式对嵌套片段中的字段进行排序。
例如:
query {
articleList(sort: "authorFragment.lastName") {
items {
title
authorFragment {
firstName
lastName
birthDay
}
slug
}
}
}
分页 paging
此功能让您对返回列表的查询类型执行分页。提供了两种方法:
- 在
List
查询中的offset
和limit
- 在
Paginated
查询中的first
和after
列表查询 – 偏移和限制 list-offset-limit
在 ...List
查询中,您可以使用 offset
和 limit
返回特定的结果子集:
offset
:指定要返回的第一个数据集limit
:指定返回的最大数据集数
例如,要输出最多包含五篇文章的结果页面,从 完整 结果列表中的第五篇文章开始:
query {
articleList(offset: 5, limit: 5) {
items {
authorFragment {
lastName
firstName
}
}
}
}
-
分页需要稳定的排序顺序才能在请求同一结果集的不同页面的多个查询中正常工作。默认情况下,它使用结果集中每个项目的存储库路径来确保顺序始终相同。 如果使用不同的排序顺序,并且无法在JCR查询级别进行排序,则会对性能产生负面影响。 原因在于,在确定页面之前,必须将整个结果集加载到内存中。
-
偏移量越高,从完整的JCR查询结果集中跳过项目所需的时间就越多。 大型结果集的替代解决方案是使用带有
first
和after
方法的分页查询。
分页查询 – 先和后 paginated-first-after
...Paginated
查询类型重用了大部分 ...List
查询类型功能(过滤、排序),但没有使用 offset
/limit
参数,它使用 first
/after
参数,正如 GraphQL 光标连接规范所定义。您可以在 GraphQL 介绍 中找到不太正式的介绍。
first
:n
要返回的第一个项目。
默认为50
。最大值为100
。after
:确定请求页面开头的游标。 光标所表示的项目不包含在结果集中。 项目的游标由edges
结构的cursor
字段决定。
例如,输出包含最多五次冒险的结果页面,从 完整 结果列表中的给定光标项开始:
query {
adventurePaginated(first: 5, after: "ODg1MmMyMmEtZTAzMy00MTNjLThiMzMtZGQyMzY5ZTNjN2M1") {
edges {
cursor
node {
title
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
-
默认情况下,分页使用表示排序片段的存储库节点的UUID,以确保结果的顺序始终相同。 当使用
sort
时,隐式使用 UUID 以确保唯一排序;即使对于具有相同排序键的两个项目,也可以使用。 -
由于内部技术限制,如果对嵌套字段应用排序和筛选,则性能会降低。 因此,请使用存储在根级别的筛选器/排序字段。 如果要查询大型分页结果集,也建议使用此方法。
GraphQL 持久化查询 - 在 Dispatcher 中启用缓存 graphql-persisted-queries-enabling-caching-dispatcher
默认情况下,Dispatcher 中未启用持久化查询的缓存。无法实施默认启用,因为对多个源使用 CORS(跨源资源共享)的客户需要检查并(可能需要)更新其 Dispatcher 配置。
Vary
标头。启用持久化查询的缓存 enable-caching-persisted-queries
要启用持久查询的缓存,需要对Dispatcher配置文件进行以下更新:
-
<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 Dispatcher将后缀 .json
添加到所有保留的查询URL,以便可以缓存结果。这是为了确保查询符合Dispatcher对可缓存文档的要求。 有关详细信息,请参阅Dispatcher如何返回文档? -
<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*" }
Dispatcher 中的 CORS 配置 cors-configuration-in-dispatcher
使用 CORS 请求的客户可能需要在 Dispatcher 中查看和更新其 CORS 配置。
-
Origin
标头不得通过 Dispatcher 传递到 AEM 发布:- 检查
clientheaders.any
文件。
- 检查
-
相反,必须在 Dispatcher 级别为允许的源评估 CORS 请求。此方法还可确保在所有情况下,在一个位置正确设置 CORS 相关标头。
- 应将此类配置添加到
vhost
文件。下面提供了一个示例配置;为简单起见,仅提供了 CORS 相关部分。您可以根据特定用例进行调整。
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>
- 应将此类配置添加到
GraphQL for AEM – 执行摘要 graphql-extensions
使用 GraphQL for AEM 的查询基本处理遵循标准 GraphQL 规范。对于使用AEM的GraphQL查询,有几个扩展:
-
如果您需要单个结果:
- 使用模型名称;例如,city
-
如果您需要结果列表:
- 将
List
添加到模型名称;例如,cityList
- 请参阅示例查询 – 关于所有城市的所有信息
稍后您可以:
-
ASC
: 升序DESC
: 降序
-
使用以下任一方法返回一页结果:
- 将
-
筛选器
includeVariations
包含在List
查询类型中。 若要检索查询结果中的内容片段变体,includeVariations
筛选器必须设置为true
。note caution CAUTION 筛选器 includeVariations
不能与系统生成的字段_variation
一起使用。 -
如果您希望使用逻辑 OR:
- 使用
_logOp: OR
- 请参阅示例查询 – 所有名为“Jobs”或“Smith”的人
- 使用
-
逻辑 AND 也可使用,不过(通常)是隐式的
-
您可以查询与内容片段模型中字段对应的字段名称
-
除了来自您模型的字段以外,还有一些系统生成的字段(以下划线为前缀):
-
对于内容:
-
_locale
:用于显示语言;基于语言管理器 -
_metadata
:用于显示片段的元数据 -
_model
:允许查询内容片段模型(路径和标题) -
_path
:存储库中内容片段的路径 -
_reference
:用于显示引用,包括富文本编辑器中的内联引用 -
_variation
:用于显示内容片段中的特定变体note note NOTE 如果内容片段不存在给定的变量,则主控变量会作为(回退)默认值返回。 note caution CAUTION 系统生成的字段 _variation
不能与过滤器includeVariations
一起使用。 -
_tags
:用于显示包含标记的内容片段或变体的ID;此列表是cq:tags
标识符的数组。note note NOTE 还可以通过列出内容片段的元数据来查询标签。
-
-
以及操作:
-
_operator
:应用特定运算符;EQUALS
、EQUALS_NOT
、GREATER_EQUAL
、LOWER
、CONTAINS
、STARTS_WITH
-
_apply
:用于应用特定条件,例如AT_LEAST_ONCE
-
_ignoreCase
:在查询时忽略大小写
-
-
-
支持 GraphQL 合并类型:
- 使用
... on
- 使用
-
在查询嵌套片段时回退:
- 如果所请求的变体在嵌套片段中不存在,则返回 主 变体。
CORS 筛选条件 cors-filter
要访问GraphQL端点,请在客户Git存储库中配置CORS策略。 此配置可通过为一个或多个所需端点添加相应的OSGi CORS配置文件来完成。
此配置必须指定可信网站源alloworigin
或alloworiginregexp
,必须向其授予访问权限。
例如,要授予对https://my.domain
的GraphQL端点和持久查询端点的访问权限,您可以使用:
{
"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/.*"
]
}
如果您已为端点配置虚名路径,还可以在 allowedpaths
中使用它。
反向链接筛选条件 referrer-filter
除了CORS配置外,还必须配置反向链接筛选条件以允许从第三方主机进行访问。
此过滤器可通过添加适当的OSGi反向链接过滤器配置文件来完成,该配置文件可以:
- 指定了可信的网站主机名;可以为
allow.hosts
或allow.hosts.regexp
。 - 授予了对此主机名的访问权限。
例如,要授予反向链接 my.domain
的请求的访问权限,您可以:
{
"allow.empty":false,
"allow.hosts":[
"my.domain"
],
"allow.hosts.regexp":[
""
],
"filter.methods":[
"POST",
"PUT",
"DELETE",
"COPY",
"MOVE"
],
"exclude.agents.regexp":[
""
]
}
- 仅向可信域授予访问权限
- 确保未公开敏感信息
- 不使用通配符[*]语法;此功能禁用对GraphQL端点的经过身份验证的访问,还会将其向全世界公开。
限制 limitations
为了防止潜在问题,您的查询存在默认限制:
- 查询不能包含超过1M (1024 * 1024)个字符
- 查询不能包含超过15000个令牌
- 查询不能包含超过200000个空白令牌
您还需要了解:
-
当GraphQL查询包含两个(或更多)模型中同名的字段,并且满足以下条件时,将返回字段冲突错误:
-
因此,在何处:
- 使用两个(或更多模型)作为可能的引用;当它们在内容片段引用中定义为允许的 模型类型 时。
和:
- 这两个模型具有具有相同名称的字段;这意味着两个模型中出现相同的名称。
和
- 这些字段的数据类型不同。
-
例如:
-
当使用两个具有不同模型的片段(例如
M1
、M2
)作为另一个片段的可能引用(内容引用或片段引用)时;例如Fragment1
MultiField/List
-
这两个具有不同模型(
M1
、M2
)的片段具有同名但类型不同的字段。
举例说明:M1.Title
作为Text
M2.Title
作为Text/MultiField
-
如果GraphQL查询包含
Title
字段,则会发生字段冲突错误。
-
-
身份验证 authentication
请参阅对内容片段的远程 AEM GraphQL 查询的身份验证。
常见问题解答 faqs
出现的问题:
-
问:适用于 AEM 的 GraphQL API 与查询生成器 API 有何不同?
- 答:
AEM GraphQL API 提供了对 JSON 输出的全面控制,是用于查询内容的行业标准。
将来,AEM计划投资于AEM GraphQL API。
- 答:
教程 – AEM Headless 和 GraphQL 快速入门 tutorial
正在寻找实践教程?请查看 AEM Headless 和 GraphQL 快速入门端到端教程,其中说明了在 Headless CMS 场景中,如何使用 AEM GraphQL API 构建和公开内容并由外部应用程序使用。