

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

# 在中定义增强型订阅过滤器 Amazon AppSync
<a name="aws-appsync-real-time-enhanced-filtering"></a>

**重要**  
从 2025 年 3 月 13 日起， WebSockets 您可以使用 Amazon AppSync 事件构建实时 PubSub API。有关更多信息，请参阅[事件开发者指南 WebSocket中的通过发布Amazon](https://docs.amazonaws.cn/appsync/latest/eventapi/publish-websocket.html)*AppSync 事件*。

在中 Amazon AppSync，您可以使用支持其他逻辑运算符的筛选器，直接在 GraphQL API 订阅解析器中定义和启用用于在后端进行数据筛选的业务逻辑。您可以配置这些筛选条件，这与在客户端的订阅查询上定义的订阅参数不同。有关使用订阅参数的更多信息，请参阅[使用订阅参数](aws-appsync-real-time-data.md#using-subscription-arguments)。有关运算符列表，请参阅[Amazon AppSync 解析器映射模板实用程序参考](resolver-util-reference.md)。

就本文而言，我们将实时数据筛选分为以下几个类别：
+ **基本筛选** - 根据订阅查询中的客户端定义的参数进行筛选。
+ **增强筛选**-基于 Amazon AppSync 服务后端集中定义的逻辑进行筛选。

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

## 在 GraphQL 架构中定义订阅
<a name="aws-appsync-real-time-enhanced-filtering-using-subscription-filters"></a>

要使用增强订阅筛选条件，您可以在 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 解析器处理程序中启用的。有关更多信息，请参阅[解析器参考](https://docs.amazonaws.cn/appsync/latest/devguide/resolver-reference-js-version.html)。

要实施增强筛选条件的行为，您必须使用 `extensions.setSubscriptionFilter()` 函数定义一个筛选条件表达式，该表达式针对通过 GraphQL 变更发布并且订阅客户端可能感兴趣的数据进行评估。有关筛选扩展的更多信息，请参阅[扩展](https://docs.amazonaws.cn//appsync/latest/devguide/extensions-js.html)。

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

## 使用筛选扩展创建增强订阅筛选条件
<a name="aws-appsync-real-time-enhanced-filtering-defining-filters"></a>

增强筛选条件是在订阅解析器的响应处理程序中以 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` 级别 `high` 或 `medium`

  AND 
+ 大于或等于 `7` (`ge`) 的 `severity` 级别

或 
+ 设置为 `Security` 的 `classification` 票证 

  AND 
+ 设置为 `admin` 或 `operators` 的 `group` 分配

![显示票证筛选查询的示例](http://docs.amazonaws.cn/appsync/latest/devguide/images/aws-priority-example.png)


订阅解析器中定义的筛选条件（增强筛选）优先于仅基于订阅参数的筛选（基本筛选）。有关使用订阅参数的更多信息，请参阅[使用订阅参数](https://docs.amazonaws.cn//appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments)。

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

您可以在订阅的筛选条件扩展逻辑中使用 [`context` 变量](https://docs.amazonaws.cn/appsync/latest/devguide/resolver-context-reference-js.html)，以访问有关请求的上下文信息。例如，在使用 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 服务中实现的，具有增强筛选功能，从而简化了客户端代码。只有在满足定义的筛选条件时，客户端才会收到数据。

## 为嵌套的架构字段定义增强筛选条件
<a name="aws-appsync-real-time-enhanced-filters-nested-schema-fields.title"></a>

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

```
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
  }
}
```

## 从客户端中定义增强筛选条件
<a name="aws-appsync-real-time-enhanced-filtering-defining-from-client"></a>

您可以在 GraphQL 中通过[订阅参数](https://docs.amazonaws.cn/appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments)使用基本筛选。在订阅查询中进行调用的客户端定义参数的值。当在带有筛选功能的 Amazon AppSync 订阅解析器中启用增强型`extensions`过滤器时，解析器中定义的后端过滤器具有优先级和优先级。

使用 `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解析器概述](https://docs.amazonaws.cn/appsync/latest/devguide/resolver-reference-overview-js.html)。

## 额外的增强筛选限制
<a name="aws-appsync-real-time-enhanced-filtering-additional-restrictions"></a>

以下是几个对增强筛选条件施加额外限制的使用案例：
+ 增强筛选条件不支持顶级对象列表筛选。在该使用案例中，对于增强订阅，将忽略来自变更的发布数据。
+ Amazon AppSync 支持多达五个嵌套级别。将忽略超过嵌套级别 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,
          }
      }
  }
  ```