持久 GraphQL 查询 persisted-graphql-queries

持久查询是创建并存储在 Adobe Experience Manager (AEM) as a Cloud Service 服务器上的 GraphQL 查询。它们可以经客户端应用程序以 GET 请求方式请求。GET 请求的响应可以在 Dispatcher 和 CDN 层缓存,最终改进请求客户端应用程序的性能。这与标准的 GraphQL 查询不同,后者使用 POST 请求执行,而在 POST 请求中,无法轻松缓存响应。

NOTE
建议使用持久查询。请参阅 GraphQL 查询最佳实践 (Dispatcher) 以了解详细信息和相关的 Dispatcher 配置。

GraphiQL IDE 在 AEM 中可供您开发、测试和持久您的 GraphQL 查询,然后再转移到您的生产环境。对于需要自定义的情况(例如,当自定义缓存时)可使用该 API;请参阅在如何使 GraphQL 查询持久中提供的 cURL 示例。

持久查询及端点 persisted-queries-and-endpoints

持久查询必须始终使用与相应 Sites 配置相关的端点,因此它们可以使用以下项之一或全部:

  • 全球配置和端点
    查询具有对所有内容片段模型的访问权限。
  • 特定 Sites 配置和端点
    为特定 Sites 配置创建持久查询需要对应的 Sites 配置特定的端点(用于提供对相关内容片段模型的访问权限)。
    例如,要创建特定于 WKND Sites 配置的持久查询,必须预先创建对应的 WKND 特定的端点。
NOTE
有关更多详细信息,请参阅在配置浏览器中启用内容片段功能
对于适当的 Sites 配置,需要启用 GraphQL 持久查询

例如,如果存在名为 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
NOTE
这里有两种不同的查询,保存在不同的路径中。
它们只是正好使用了相同的模型,但通过不同的端点。

如何使 GraphQL 查询持久 how-to-persist-query

建议先在 AEM 作者环境中保留查询,然后将查询转移到 AEM 发布环境中,供应用程序使用。

有多种持久查询的方法,包括:

GraphiQL IDE 是 首选 ​保留查询的方法。使用 cURL 命令行工具使给定的查询持久:

  1. 使用 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
            }
        }
      }
    }'
    
  2. 此时,检查响应。

    例如,检查是否成功:

    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"
    }
    
  3. 然后,您可以通过对 URL /graphql/execute.json/<shortPath> 执行 GET 操作来请求持久查询。

    例如,使用持久查询:

    code language-shell
    $ curl -X GET \
        http://localhost:4502/graphql/execute.json/wknd/plain-article-query
    
  4. 通过将持久查询 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
          }
        }
      }
    }'
    
  5. 创建打包的简单查询。

    例如:

    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 } } } }"}'
    
  6. 使用缓存控制创建打包的简单查询。

    例如:

    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 }}'
    
  7. 使用参数创建持久查询:

    例如:

    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 是保存持久查询的缩略路径。

  1. 例如,wknd 是配置名称,plain-article-query 为持久查询的名称。要执行查询:

    code language-shell
    $ curl -X GET \
        https://publish-p123-e456.adobeaemcloud.com/graphql/execute.json/wknd/plain-article-query
    
  2. 使用参数执行查询。

    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级别编码两次。
    要避免出现这种情况,请执行以下操作:

    • 启用 DispatcherNoCanonURL 在Dispatcher上。
      这将指示Dispatcher将原始URL转发到AEM,以防止编码重复。
      但是,此设置当前仅在 vhost 级别,因此,如果您已有Dispatcher配置来重写URL(例如,在使用缩短的URL时),您可能需要单独的 vhost 用于持久查询URL。

    • 发送 /\ 字符未编码。
      在调用持久查询URL时,请确保所有 /\ 在持久查询变量的值中,字符保持未编码状态。

      note note
      NOTE
      仅当满足以下条件,才建议使用此选项 DispatcherNoCanonURL 无法实施解决方案,因为没有任何原因。
  • CACHE_GRAPHQL_PERSISTED_QUERIES

    时间 CACHE_GRAPHQL_PERSISTED_QUERIES 为Dispatcher启用,然后 ; 不能在变量的值中使用字符。

正在缓存您的持久查询 caching-persisted-queries

建议使用持久查询,因为可在 Dispatcher 和内容交付网络 (CDN) 层缓存此类查询,最终提高发出请求的客户端应用程序的性能。

默认情况下,AEM 将根据生存时间 (TTL) 定义使缓存失效。可通过以下参数定义这些 TTL。可通过多种方式访问这些参数,其名称因所使用的机制而异:

缓存类型
HTTP 标头
cURL
OSGi 配置
Cloud Manager
浏览器
max-age
cache-control : max-age
cacheControlMaxAge
graphqlCacheControl
CDN
s-maxage
surrogate-control : max-age
surrogateControlMaxAge
graphqlSurrogateControl
CDN
stale-while-revalidate
surrogate-control : stale-while-revalidate
surrogateControlStaleWhileRevalidate
graphqlStaleWhileRevalidate
CDN
stale-if-error
surrogate-control : stale-if-error
surrogateControlStaleIfError
graphqlStaleIfError

创作实例 author-instances

创作实例的默认值为:

  • max-age : 60
  • s-maxage : 60
  • stale-while-revalidate : 86400
  • stale-if-error : 86400

这些值:

  • 无法被覆盖:

    • 用 OSGi 配置覆盖
  • 可被覆盖:

    • 被使用 cURL 定义 HTTP 标头设置的请求覆盖;它应该包括适合 cache-control 和/或 surrogate-control 的设置;有关示例,请参阅在持久查询级别管理缓存
    • 如果在 GraphiQL IDE 的​ 标头 ​对话框中指定值,则可覆盖

发布实例 publish-instances

发布实例的默认值为:

  • max-age : 60
  • s-maxage : 7200
  • stale-while-revalidate : 86400
  • stale-if-error : 86400

这些值可被覆盖:

在 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
86400
酌情
酌情
graphqlSurrogateControl
600
酌情
酌情

使用 OSGi 配置管理缓存 cache-osgi-configration

要全局管理缓存,您可以为​ 持久查询服务配置配置 OSGi 设置

NOTE
对于缓存控制,OSGi 配置仅适用于发布实例。创作实例上存在该配置,但忽略了它。
NOTE
持久查询服务配置 ​也用于配置查询响应代码

发布实例的默认 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 端点,当持久查询中存在错误时。

NOTE
持久查询服务配置 ​也用于管理缓存。

字段 Respond with application/graphql-response+json (responseContentTypeGraphQLResponseJson) 可以根据需要定义:

  • false(默认值):
    持久化查询成功与否无关紧要。此 Content-Type 返回的标头是 application/json,和 /execute.json/persisted-query 始终 返回状态代码 200.

  • true:返回的 Content-Typeapplication/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 可以划分为以下部分:

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 JavaScriptJavaNodeJS。Headless 客户端 SDK 将自动在请求中正确编码任何查询变量。

正在将持久查询转移到生产环境 transfer-persisted-query-production

应始终在 AEM 创作服务上创建持久查询,然后将其发布(复制)到 AEM 发布服务。通常,持久查询会在本地或开发环境等较低环境中创建和测试。然后,有必要将持久查询提升到更高级别的环境,最终在生产 AEM 发布环境中提供,以供客户端应用程序使用。

持久查询包

可以将持久查询构建在 AEM 程序包中。然后,可以在不同的环境中下载和安装 AEM 包。AEM 包也可以从 AEM 创作环境复制到 AEM 发布环境。

要创建包:

  1. 导航到​ 工具 > 部署 >
  2. 点击​ 创建包 ​创建一个新包。这将打开一个用于定义资源包的对话框。
  3. 在包定义对话框中,在​ 常规 ​下输入​ 名称,如“wknd-persistent-queries”。
  4. 输入版本号,如“1.0”。
  5. 在​ 过滤器 ​下添加新的​ 过滤器。使用路径查找器选择 persistentQueries 文件夹。例如,对于 wknd 配置,完整路径为 /conf/wknd/settings/graphql/persistentQueries
  6. 选择 保存 以保存新的包定义并关闭对话框。
  7. 选择 生成 按钮创建包定义。

生成包后,您可以:

  • 下载 包,并在其他环境上重新上传。
  • 通过点击​ 更多 > 复制 ​来​ 复制 ​包。这会将包复制到连接的 AEM 发布环境。
recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab