持久 GraphQL 查询 persisted-graphql-queries
持久查询是创建并存储在 Adobe Experience Manager (AEM) as a Cloud Service 服务器上的 GraphQL 查询。它们可以经客户端应用程序以 GET 请求方式请求。GET 请求的响应可以在 Dispatcher 和 CDN 层缓存,最终改进请求客户端应用程序的性能。这与标准的 GraphQL 查询不同,后者使用 POST 请求执行,而在 POST 请求中,无法轻松缓存响应。
GraphiQL IDE 在 AEM 中可供您开发、测试和持久您的 GraphQL 查询,然后再转移到您的生产环境。对于需要自定义的情况(例如,当自定义缓存时)可使用该 API;请参阅在如何使 GraphQL 查询持久中提供的 cURL 示例。
持久查询及端点 persisted-queries-and-endpoints
持久查询必须始终使用与相应 Sites 配置相关的端点,因此它们可以使用以下项之一或全部:
- 全球配置和端点
查询具有对所有内容片段模型的访问权限。 - 特定 Sites 配置和端点
为特定 Sites 配置创建持久查询需要对应的 Sites 配置特定的端点(用于提供对相关内容片段模型的访问权限)。
例如,要创建特定于 WKND Sites 配置的持久查询,必须预先创建对应的 WKND 特定的端点。
例如,如果存在名为 my-query
的特定查询,使用来自 Sites 配置 my-conf
的模型 my-model
:
- 您可以使用
my-conf
特定的端点创建查询,然后查询会保存如下:/conf/my-conf/settings/graphql/persistentQueries/my-query
- 您可以使用
global
端点创建相同的查询,但此后查询会保存如下:/conf/global/settings/graphql/persistentQueries/my-query
如何使 GraphQL 查询持久 how-to-persist-query
建议先在 AEM 作者环境中保留查询,然后将查询转移到 AEM 发布环境中,供应用程序使用。
有多种持久查询的方法,包括:
GraphiQL IDE 是 首选 保留查询的方法。使用 cURL 命令行工具使给定的查询持久:
-
使用 PUT 操作将查询放入新端点 URL
/graphql/persist.json/<config>/<persisted-label>
来准备查询。例如,创建持久查询:
code language-shell $ curl -X PUT \ -H 'authorization: Basic YWRtaW46YWRtaW4=' \ -H "Content-Type: application/json" \ "http://localhost:4502/graphql/persist.json/wknd/plain-article-query" \ -d \ '{ articleList { items{ _path author main { json } } } }'
-
此时,检查响应。
例如,检查是否成功:
code language-json { "action": "create", "configurationName": "wknd", "name": "plain-article-query", "shortPath": "/wknd/plain-article-query", "path": "/conf/wknd/settings/graphql/persistentQueries/plain-article-query" }
-
然后,您可以通过对 URL
/graphql/execute.json/<shortPath>
执行 GET 操作来请求持久查询。例如,使用持久查询:
code language-shell $ curl -X GET \ http://localhost:4502/graphql/execute.json/wknd/plain-article-query
-
通过将持久查询 POST 到已经存在的查询路径来更新持久查询。
例如,使用持久查询:
code language-shell $ curl -X POST \ -H 'authorization: Basic YWRtaW46YWRtaW4=' \ -H "Content-Type: application/json" \ "http://localhost:4502/graphql/persist.json/wknd/plain-article-query" \ -d \ '{ articleList { items{ _path author main { json } referencearticle { _path } } } }'
-
创建打包的简单查询。
例如:
code language-shell $ curl -X PUT \ -H 'authorization: Basic YWRtaW46YWRtaW4=' \ -H "Content-Type: application/json" \ "http://localhost:4502/graphql/persist.json/wknd/plain-article-query-wrapped" \ -d \ '{ "query": "{articleList { items { _path author main { json } referencearticle { _path } } } }"}'
-
使用缓存控制创建打包的简单查询。
例如:
code language-shell $ curl -X PUT \ -H 'authorization: Basic YWRtaW46YWRtaW4=' \ -H "Content-Type: application/json" \ "http://localhost:4502/graphql/persist.json/wknd/plain-article-query-max-age" \ -d \ '{ "query": "{articleList { items { _path author main { json } referencearticle { _path } } } }", "cache-control": { "max-age": 300 }}'
-
使用参数创建持久查询:
例如:
code language-shell $ curl -X PUT \ -H 'authorization: Basic YWRtaW46YWRtaW4=' \ -H "Content-Type: application/json" \ "http://localhost:4502/graphql/persist.json/wknd/plain-article-query-parameters" \ -d \ 'query GetAsGraphqlModelTestByPath($apath: String!, $withReference: Boolean = true) { articleByPath(_path: $apath) { item { _path author main { plaintext } referencearticle @include(if: $withReference) { _path } } } }'
如何执行持久查询 execute-persisted-query
要执行持久查询,客户端应用程序使用以下语法发出 GET 请求:
GET <AEM_HOST>/graphql/execute.json/<PERSISTENT_PATH>
其中 PERSISTENT_PATH
是保存持久查询的缩略路径。
-
例如,
wknd
是配置名称,plain-article-query
为持久查询的名称。要执行查询:code language-shell $ curl -X GET \ https://publish-p123-e456.adobeaemcloud.com/graphql/execute.json/wknd/plain-article-query
-
使用参数执行查询。
note note NOTE 执行持久查询时,必须对查询变量和值进行正确地编码。 例如:
code language-xml $ curl -X GET \ "https://publish-p123-e456.adobeaemcloud.com/graphql/execute.json/wknd/plain-article-query-parameters%3Bapath%3D%2Fcontent%2Fdam%2Fwknd%2Fen%2Fmagazine%2Falaska-adventure%2Falaskan-adventures%3BwithReference%3Dfalse
请参阅使用查询变量以了解更多详细信息。
使用查询变量 query-variables
查询变量可与持久查询一起使用。使用变量名称和值将查询变量附加到以分号 (;
) 为前缀的请求中。多个变量以分号分隔。
该模式如下所示:
<AEM_HOST>/graphql/execute.json/<PERSISTENT_QUERY_PATH>;variable1=value1;variable2=value2
例如,以下查询包含一个变量 activity
要根据活动值过滤列表,请执行以下操作:
query getAdventuresByActivity($activity: String!) {
adventureList (filter: {
adventureActivity: {
_expressions: [
{
value: $activity
}
]
}
}){
items {
_path
adventureTitle
adventurePrice
adventureTripLength
}
}
}
此查询可以保留在路径 wknd/adventures-by-activity
下。要调用 Persisted 查询 activity=Camping
,请求如下所示:
<AEM_HOST>/graphql/execute.json/wknd/adventures-by-activity%3Bactivity%3DCamping
UTF-8 编码 %3B
是 ;
的,%3D
是 =
的编码。查询变量和任何特殊字符必须正确编码才能执行持久查询。
使用查询变量 - 最佳实践 query-variables-best-practices
在查询中使用变量时,应遵循一些最佳做法:
-
编码
作为一般方法,始终建议对所有特殊字符进行编码;例如,;
、=
、?
、&
等等。 -
分号
使用多个变量(以分号分隔)的持久查询需要具有以下任一功能:- 编码的分号(
%3B
);对 URL 进行编码也能达到此目的 - 或者在查询末尾添加一个分号
- 编码的分号(
-
CACHE_GRAPHQL_PERSISTED_QUERIES
什么时候CACHE_GRAPHQL_PERSISTED_QUERIES
为 Dispatcher 启用,则包含/
或者\
其值中的字符在 Dispatcher 级别被编码两次。为了避免这种情况:-
在 Dispatcher 上启用
DispatcherNoCanonURL
。
这将指示 Dispatcher 将原始 URL 转发到 AEM,从而防止重复编码。
但是此设置目前仅适用于vhost
级别,因此如果你已经有 Dispatcher 配置来重写 URL(例如使用缩短的 URL 时),则可能需要单独的vhost
用于持久查询 URL。 -
发送
/
或者\
未编码的字符。
调用持久查询 URL 时,确保所有/
或者\
字符在持久查询变量的值中仍未编码。note note NOTE 此选项仅建议用于 DispatcherNoCanonURL
解决方案因某种原因无法实施。
-
-
CACHE_GRAPHQL_PERSISTED_QUERIES
当为 Dispatcher 启用“
CACHE_GRAPHQL_PERSISTED_QUERIES
”时,则变量值中不能使用字符“;
”。
正在缓存您的持久查询 caching-persisted-queries
建议使用持久查询,因为可在 Dispatcher 和内容交付网络 (CDN) 层缓存此类查询,最终提高发出请求的客户端应用程序的性能。
默认情况下,AEM 将根据生存时间 (TTL) 定义使缓存失效。可通过以下参数定义这些 TTL。可通过多种方式访问这些参数,其名称因所使用的机制而异:
max-age
cache-control : max-age
cacheControlMaxAge
graphqlCacheControl
s-maxage
surrogate-control : max-age
surrogateControlMaxAge
graphqlSurrogateControl
stale-while-revalidate
surrogate-control : stale-while-revalidate
surrogateControlStaleWhileRevalidate
graphqlStaleWhileRevalidate
stale-if-error
surrogate-control : stale-if-error
surrogateControlStaleIfError
graphqlStaleIfError
创作实例 author-instances
创作实例的默认值为:
max-age
: 60s-maxage
: 60stale-while-revalidate
: 86400stale-if-error
: 86400
这些值:
-
无法被覆盖:
- 用 OSGi 配置覆盖
-
可被覆盖:
- 被使用 cURL 定义 HTTP 标头设置的请求覆盖;它应该包括适合
cache-control
和/或surrogate-control
的设置;有关示例,请参阅在持久查询级别管理缓存 - 如果在 GraphiQL IDE 的 标头 对话框中指定值,则可覆盖
- 被使用 cURL 定义 HTTP 标头设置的请求覆盖;它应该包括适合
发布实例 publish-instances
发布实例的默认值为:
max-age
: 60s-maxage
: 7200stale-while-revalidate
: 86400stale-if-error
: 86400
这些值可被覆盖:
-
在持久查询级别覆盖;其中涉及在命令行界面中使用 cURL 将查询发布到 AEM 以及发布持久查询。
在 GraphiQL IDE 中管理 HTTP 缓存标头 http-cache-headers-graphiql-ide
GraphiQL IDE - 请参阅保存持久查询
在持久查询级别管理缓存 cache-persisted-query-level
其中涉及在命令行界面中使用 cURL 将查询发布到 AEM。
PUT(创建)方法的示例:
curl -u admin:admin -X PUT \
--url "http://localhost:4502/graphql/persist.json/wknd/plain-article-query-max-age" \
--header "Content-Type: application/json" \
--data '{ "query": "{articleList { items { _path author } } }", "cache-control": { "max-age": 300 }, "surrogate-control": {"max-age":600, "stale-while-revalidate":1000, "stale-if-error":1000} }'
POST(更新)方法的示例:
curl -u admin:admin -X POST \
--url "http://localhost:4502/graphql/persist.json/wknd/plain-article-query-max-age" \
--header "Content-Type: application/json" \
--data '{ "query": "{articleList { items { _path author } } }", "cache-control": { "max-age": 300 }, "surrogate-control": {"max-age":600, "stale-while-revalidate":1000, "stale-if-error":1000} }'
可以在创建时(PUT)或以后(例如,通过 POST 请求)设置 cache-control
。在创建持久查询时,缓存控制是可选的,因为 AEM 可以提供默认值。有关使用 cURL 使查询持久的示例,请参阅如何使 GraphQL 查询持久。
使用 Cloud Manager 变量管理缓存 cache-cloud-manager-variables
可用 Cloud Manager 定义 Cloud Manager 环境变量以定义所需的值:
graphqlStaleIfError
graphqlSurrogateControl
使用 OSGi 配置管理缓存 cache-osgi-configration
要全局管理缓存,您可以为 持久查询服务配置配置 OSGi 设置。
发布实例的默认 OSGi 配置:
-
读取 Cloud Manager 变量(如果可用):
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto OSGi 配置属性 读取此项 Cloud Manager 变量 cacheControlMaxAge
读 graphqlCacheControl
surrogateControlMaxAge
读 graphqlSurrogateControl
surrogateControlStaleWhileRevalidate
读 graphqlStaleWhileRevalidate
surrogateControlStaleIfError
读 graphqlStaleIfError
-
如果不可用,OSGi 配置将使用发布实例的默认值。
配置查询响应代码 configuring-query-response-code
默认情况下,无论实际结果如何,PersistedQueryServlet
在执行查询时都会发送200
响应。
当持久查询中出现错误时,您可以为 持久查询服务配置配置 OSGi 设置,以控制 /execute.json/persisted-query
端点是否返回更详细的状态代码。
字段 Respond with application/graphql-response+json
(responseContentTypeGraphQLResponseJson
) 可以根据需要定义:
-
false
(默认值):
持久化查询成功与否无关紧要。Content-Type
标头返回的是application/json
,而/execute.json/persisted-query
总是 返回状态代码200
。 -
true
:
返回的Content-Type
是application/graphql-response+json
,并且当运行持久查询时出现任何形式的错误,端点将返回适当的响应代码:table 0-row-2 1-row-2 2-row-2 3-row-2 4-row-2 代码 描述 200 成功响应 400 表示缺少标题,或者持久查询路径存在问题。例如:未指定配置名称、未指定后缀等。
参阅 故障排除 - 未配置 GraphQL 端点。404 未能找到所请求的资源。例如:Graphql 端点在服务器上不可用。
参阅 故障排除 - GraphQL 持久查询 URL 中缺少路径。500 内部服务器错误。例如:验证错误、持久性错误等。 note note NOTE 另请参阅 https://graphql.github.io/graphql-over-http/draft/#sec-Status-Codes
为应用程序使用的查询 URL 编码 encoding-query-url
对于应用程序,在构建查询变量时使用的任何特殊字符(即分号 (;
)、等号 (=
)、斜杠 /
)才能使用相应的 UTF-8 编码。
例如:
curl -X GET \ "https://publish-p123-e456.adobeaemcloud.com/graphql/execute.json/wknd/adventure-by-path%3BadventurePath%3D%2Fcontent%2Fdam%2Fwknd%2Fen%2Fadventures%2Fbali-surf-camp%2Fbali-surf-camp"
URL 可以划分为以下部分:
/graphql/execute.json
/wknd/adventure-by-path
%3B
;
的编码adventurePath
%3D
=
的编码%2F
/
的编码%2Fcontent%2Fdam...
在纯文本中,请求 URI 如下所示:
/graphql/execute.json/wknd/adventure-by-path;adventurePath=/content/dam/wknd/en/adventures/bali-surf-camp/bali-surf-camp
要在客户端应用程序中使用持久查询,应使用 AEM headless 客户端 SDK JavaScript、Java 或 NodeJS。Headless 客户端 SDK 将自动在请求中正确编码任何查询变量。
正在将持久查询转移到生产环境 transfer-persisted-query-production
应始终在 AEM 创作服务上创建持久查询,然后将其发布(复制)到 AEM 发布服务。通常,持久查询会在本地或开发环境等较低环境中创建和测试。然后,有必要将持久查询提升到更高级别的环境,最终在生产 AEM 发布环境中提供,以供客户端应用程序使用。
持久查询包
可以将持久查询构建在 AEM 程序包中。然后,可以在不同的环境中下载和安装 AEM 包。AEM 包也可以从 AEM 创作环境复制到 AEM 发布环境。
要创建包:
- 导航到 工具 > 部署 > 包。
- 点击 创建包 创建一个新包。这打开一个用于定义资源包的对话框。
- 在包定义对话框中,在 常规 下输入 名称,如“wknd-persistent-queries”。
- 输入版本号,如“1.0”。
- 在 过滤器 下添加新的 过滤器。使用路径查找器选择
persistentQueries
文件夹。例如,对于wknd
配置,完整路径为/conf/wknd/settings/graphql/persistentQueries
。 - 选择 保存 以保存新的包定义并关闭对话框。
- 在新创建的包定义中选择 生成 按钮。
生成包后,您可以:
- 下载 包,并在其他环境上重新上传。
- 通过点击 更多 > 复制 来 复制 包。这会将包复制到连接的 AEM 发布环境。