Query Functions
Query Functions字段响应移除

字段响应移除

Included in the “Power Extensions” bundle

向 GraphQL schema 添加 @remove 指令,从响应中移除字段的输出。

说明

GraphQL 规范规定,GraphQL 响应必须与 query 的结构完全一致。然而,在某些情况下,我们更倾向于不返回字段的响应,原因如下:

  • 我们已经知道其值,不再发送可以提升性能
  • 其中包含敏感信息(例如登录凭据)
  • 空字段可以与 null 值区分开来

在字段上添加 @remove 后,该字段将不会出现在响应中。

以下 query(使用 PHP Functions via SchemaHTTP Client 扩展)通过拼接站点域名和 REST API 端点来生成发送 HTTP 请求的 URL。由于这些「组件」的值对我们来说并不重要,无需在响应中输出,因此可以用 @remove 将其移除:

query {
  siteURL: optionValue(name: "siteurl")
    @remove
 
  requestURL: _sprintf(
    string: "%s/wp-json/wp/v2/comments/11/?_fields=id,content,date",
    values: [$__siteURL]
  )
    @remove
 
  _sendJSONObjectItemHTTPRequest(
    input: {
      url: $__requestURL
    }
  )
}

...结果(注意 siteURLrequestURL 字段未出现在响应中):

{
  "data": {
    "_sendJSONObjectItemHTTPRequest": {
      "id": 11,
      "date": "2020-12-12T04:07:36",
      "content": {
        "rendered": "<p>Btw, I really like this stuff<\/p>\n"
      }
    }
  }
}

我们也可以让 @remove 指令在满足特定条件时才移除值。condition 参数可接受 3 个可能的值:

  • ALWAYS(默认值):始终移除
  • IS_NULL:当值为 null 时移除
  • IS_EMPTY:当值为空时移除

例如,在以下 query 中,当文章没有特色图片时,featuredImage 字段的值将为 null。通过添加 @remove(condition: IS_NULL),该值将不会被加入响应:

query {
  posts {
    title
    featuredImage @remove(condition: IS_NULL) {
      src
    }
  }
}

...结果:

{
  "data": {
    "posts": [
      {
        "title": "Hello world!"
      },
      {
        "title": "Nested mutations are a must have",
        "featuredImage": {
          "src": "https:\/\/gato-graphql.lndo.site\/wp-content\/uploads\/2022\/05\/graphql-voyager-public.jpg"
        }
      },
      {
        "title": "Customize the schema for each client"
      }
    ]
  }
}

示例

从外部 API 移除不需要的数据

假设我们想从外部 REST API 端点获取某些特定数据,而不需要其余数据。可以使用 @remove 缩减响应的有效载荷,从而提升性能:

  • 使用 _sendJSONObjectItemHTTPRequest 字段(来自 HTTP Client 扩展)连接到 REST API
  • 通过 Field to InputPHP Function via Schema_objectProperty 字段处理数据,提取所需信息
  • @remove 移除来自 REST 端点的原始数据

以下 query 将所有内容整合在一起:

{
  postData: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://newapi.getpop.org/wp-json/wp/v2/posts/1"
  }) @remove
  renderedTitle: _objectProperty(
    object: $__postData,
    by: {
      path: "title.rendered"
    }
  )
}

在该 query 的响应中,postData 字段已被移除:

{
  "data": {
    "renderedTitle": "Hello world!"
  }
}

避免输出用户凭据

此示例连接到 GitHub API 以获取私有仓库中可用的 artifacts,并避免在响应中输出用户凭据:

query RetrieveGitHubActionArtifacts(
  $repoOwner: String!
  $repoProject: String!
) {
  githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
    @remove
 
  # Create the authorization header to send to GitHub
  authorizationHeader: _sprintf(
    string: "Bearer %s"
    # "Field to Input" feature to access value from the field above
    values: [$__githubAccessToken]
  )
    @remove
 
  # Create the authorization header to send to GitHub
  githubRequestHeaders: _echo(
    value: [
      { name: "Accept", value: "application/vnd.github+json" }
      { name: "Authorization", value: $__authorizationHeader }
    ]
  )
    @remove
 
  githubAPIEndpoint: _sprintf(
    string: "https://api.github.com/repos/%s/%s/actions/artifacts"
    values: [$repoOwner, $repoProject]
  )
 
  # Use the field from "Send HTTP Request Fields" to connect to GitHub
  gitHubArtifactData: _sendJSONObjectItemHTTPRequest(
    input: {
      url: $__githubAPIEndpoint
      options: { headers: $__githubRequestHeaders }
    }
  )
}

GraphQL 规范

此功能目前不属于 GraphQL 规范的一部分,但已有相关提案: