增强订阅筛选 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

增强订阅筛选

在 Amazon AppSync 中,您可以使用支持其他逻辑运算符的筛选条件,直接在 GraphQL API 订阅解析器中为后端数据筛选定义和启用业务逻辑。您可以配置这些筛选条件,这与在客户端的订阅查询上定义的订阅参数不同。有关使用订阅参数的更多信息,请参阅使用订阅参数。有关运算符列表,请参阅解析器映射模板实用程序参考

就本文而言,我们将实时数据筛选分为以下几个类别:

  • 基本筛选 - 根据订阅查询中的客户端定义的参数进行筛选。

  • 增强筛选 - 根据 Amazon AppSync 服务后端集中定义的逻辑进行筛选。

以下几节介绍了如何配置增强订阅筛选条件,并说明了它们的实际用途。

在 GraphQL 架构中定义订阅

要使用增强订阅筛选条件,您可以在 GraphQL 架构中定义订阅,然后使用筛选扩展定义增强筛选条件。要说明增强订阅筛选在 Amazon AppSync 中的工作方式,请将以下 GraphQL 架构(定义票证管理系统 API)作为示例:

type Ticket { id: ID createdAt: AWSDateTime content: String severity: Int priority: Priority category: String group: String status: String } type Mutation { createTicket(input: TicketInput): Ticket } type Query { getTicket(id: ID!): Ticket } type Subscription { onSpecialTicketCreated: Ticket @aws_subscribe(mutations: ["createTicket"]) onGroupTicketCreated(group: String!): Ticket @aws_subscribe(mutations: ["createTicket"]) } enum Priority { none lowest low medium high highest } input TicketInput { content: String severity: Int priority: Priority category: String group: String

假设您为 API 创建一个 NONE 数据源,然后使用该数据源将一个解析器附加到 createTicket 变更。您的处理程序可能如下所示:

import { util } from '@aws-appsync/utils'; export function request(ctx) { return { payload: { id: util.autoId(), createdAt: util.time.nowISO8601(), status: 'pending', ...ctx.args.input, }, }; } export function response(ctx) { return ctx.result; }
注意

增强筛选条件是在给定订阅的 GraphQL 解析器处理程序中启用的。有关更多信息,请参阅解析器参考

要实施增强筛选条件的行为,您必须使用 extensions.setSubscriptionFilter() 函数定义一个筛选条件表达式,该表达式针对通过 GraphQL 变更发布并且订阅客户端可能感兴趣的数据进行评估。有关筛选扩展的更多信息,请参阅扩展

以下几节介绍了如何使用筛选扩展实施增强筛选条件。

使用筛选扩展创建增强订阅筛选条件

增强筛选条件是在订阅解析器的响应处理程序中以 JSON 格式编写的。可以将筛选条件组合到一个名为 filterGroup 的列表中。筛选条件是使用至少一个规则定义的,每个规则包含字段、运算符和值。让我们为 onSpecialTicketCreated 定义一个新的解析器以设置增强筛选条件。您可以在一个筛选条件中配置多个使用 AND 逻辑进行评估的规则,而一个筛选条件组中的多个筛选条件使用 OR 逻辑进行评估:

import { util, extensions } from '@aws-appsync/utils'; export function request(ctx) { // simplfy return null for the payload return { payload: null }; } export function response(ctx) { const filter = { or: [ { severity: { ge: 7 }, priority: { in: ['high', 'medium'] } }, { category: { eq: 'security' }, group: { in: ['admin', 'operators'] } }, ], }; extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter)); // important: return null in the response return null; }

根据前面示例中定义的筛选条件,如果使用以下条件创建了票证,则将重要票证自动推送到订阅的 API 客户端:

  • priority 级别 highmedium

    AND

  • 大于或等于 7 (ge) 的 severity 级别

  • 设置为 Securityclassification 票证

    AND

  • 设置为 adminoperatorsgroup 分配


                    显示票证筛选查询的示例

订阅解析器中定义的筛选条件(增强筛选)优先于仅基于订阅参数的筛选(基本筛选)。有关使用订阅参数的更多信息,请参阅使用订阅参数

如果在订阅的 GraphQL 架构中定义某个参数,并且该参数是必需的,只有在解析器的 extensions.setSubscriptionFilter() 方法中将给定参数定义为规则时,才会根据该参数进行筛选。不过,如果在订阅解析器中没有 extensions 筛选方法,则客户端中定义的参数仅用于基本筛选。您不能同时使用基本筛选和增强筛选。

您可以在订阅的筛选条件扩展逻辑中使用 context 变量,以访问有关请求的上下文信息。例如,在使用 Amazon Cognito 用户池、OIDC 或 Lambda 自定义授权者进行授权时,您可以在设置订阅后在 context.identity 中检索有关您的用户的信息。您可以使用该信息根据用户身份设置筛选条件。

现在假设您希望实施 onGroupTicketCreated 的增强筛选条件行为。onGroupTicketCreated 订阅要求将必需的 group 名称作为参数。在创建后,将自动为票证分配 pending 状态。您可以设置订阅筛选条件,以仅接收属于提供的组的新创建的票证:

import { util, extensions } from '@aws-appsync/utils'; export function request(ctx) { // simplfy return null for the payload return { payload: null }; } export function response(ctx) { const filter = { group: { eq: ctx.args.group }, status: { eq: 'pending' } }; extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter)); return null; }

在使用变更发布数据时,如以下示例中所示:

mutation CreateTicket { createTicket(input: {priority: medium, severity: 2, group: "aws"}) { id priority severity status group createdAt } }

在使用 createTicket 变更创建票证时,订阅的客户端立即侦听通过 WebSockets 自动推送的数据:

subscription OnGroup { onGroupTicketCreated(group: "aws") { category status severity priority id group createdAt content } }

客户端可以在没有参数的情况下进行订阅,因为筛选逻辑是在 Amazon AppSync 服务中使用增强筛选实施的,这简化了客户端代码。只有在满足定义的筛选条件时,客户端才会收到数据。

为嵌套的架构字段定义增强筛选条件

您可以使用增强订阅筛选以筛选嵌套的架构字段。假设我们修改了上一节中的架构以包含位置和地址类型:

type Ticket { id: ID createdAt: AWSDateTime content: String severity: Int priority: Priority category: String group: String status: String location: ProblemLocation } type Mutation { createTicket(input: TicketInput): Ticket } type Query { getTicket(id: ID!): Ticket } type Subscription { onSpecialTicketCreated: Ticket @aws_subscribe(mutations: ["createTicket"]) onGroupTicketCreated(group: String!): Ticket @aws_subscribe(mutations: ["createTicket"]) } type ProblemLocation { address: Address } type Address { country: String } enum Priority { none lowest low medium high highest } input TicketInput { content: String severity: Int priority: Priority category: String group: String location: AWSJSON

对于该架构,您可以使用 . 分隔符表示嵌套。以下示例为 location.address.country 下面的嵌套架构字段添加筛选规则。如果票证的地址设置为 USA,则会触发订阅:

import { util, extensions } from '@aws-appsync/utils'; export const request = (ctx) => ({ payload: null }); export function response(ctx) { const filter = { or: [ { severity: { ge: 7 }, priority: { in: ['high', 'medium'] } }, { category: { eq: 'security' }, group: { in: ['admin', 'operators'] } }, { 'location.address.country': { eq: 'USA' } }, ], }; extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter)); return null; }

在上面的示例中,location 表示嵌套级别 1,address 表示嵌套级别 2,country 表示嵌套级别 3,所有这些字段以 . 分隔符分隔。

您可以使用 createTicket 变更测试该订阅:

mutation CreateTicketInUSA { createTicket(input: {location: "{\"address\":{\"country\":\"USA\"}}"}) { category content createdAt group id location { address { country } } priority severity status } }

从客户端中定义增强筛选条件

您可以在 GraphQL 中通过订阅参数使用基本筛选。在订阅查询中进行调用的客户端定义参数的值。在具有 extensions 筛选的 Amazon AppSync 订阅解析器中启用增强筛选条件时,解析器中定义的后端筛选条件优先。

使用 filter 参数在订阅中配置客户端定义的动态增强筛选条件。在配置这些筛选条件时,您必须更新 GraphQL 架构以反映新参数:

... type Subscription { onSpecialTicketCreated(filter: String): Ticket @aws_subscribe(mutations: ["createTicket"]) } ...

然后,客户端可以发送订阅查询,如以下示例中所示:

subscription onSpecialTicketCreated($filter: String) { onSpecialTicketCreated(filter: $filter) { id group description priority severity } }

您可以像以下示例一样配置查询变量:

{"filter" : "{\"severity\":{\"le\":2}}"}

可以在订阅响应映射模板中实施 util.transform.toSubscriptionFilter() 解析器实用程序,以应用每个客户端的订阅参数中定义的筛选条件:

import { util, extensions } from '@aws-appsync/utils'; export function request(ctx) { // simplfy return null for the payload return { payload: null }; } export function response(ctx) { const filter = ctx.args.filter; extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter)); return null; }

通过使用该策略,客户端可以定义自己的筛选条件,以使用增强筛选逻辑和额外的运算符。当给定客户端在安全 WebSocket 连接中调用订阅查询时,将会分配筛选条件。有关用于增强筛选的转换实用程序的更多信息(包括 filter 查询变量负载格式),请参阅 JavaScript 解析器概述

额外的增强筛选限制

以下是几个对增强筛选条件施加额外限制的使用案例:

  • 增强筛选条件不支持顶级对象列表筛选。在该使用案例中,对于增强订阅,将忽略来自变更的发布数据。

  • Amazon AppSync 最多支持 5 个嵌套级别。将忽略超过嵌套级别 5 的架构字段的筛选条件。请考虑下面的 GraphQL 响应。允许使用 venue.address.country.metadata.continent 中的 continent 字段,因为它是 5 级嵌套。不过,venue.address.country.metadata.capital.financial 中的 financial 是 6 级嵌套,因此,筛选条件不起作用:

    { "data": { "onCreateFilterEvent": { "venue": { "address": { "country": { "metadata": { "capital": { "financial": "New York" }, "continent" : "North America" } }, "state": "WA" }, "builtYear": 2023 }, "private": false, } } }