

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# での拡張サブスクリプションフィルターの定義 AWS AppSync
<a name="aws-appsync-real-time-enhanced-filtering"></a>

**重要**  
2025 年 3 月 13 日以降、 AWS AppSync Events を使用して WebSockets を搭載したリアルタイム PubSub API を構築できます。詳細については、「*AWS AppSync Events デベロッパーガイド*」の「[WebSocket 経由でイベントを公開する](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html)」を参照してください。

では AWS AppSync、追加の論理演算子をサポートするフィルターを使用して、GraphQL API サブスクリプションリゾルバーでバックエンドのデータフィルタリングのビジネスロジックを直接定義して有効にできます。クライアントのサブスクリプションクエリで定義されるサブスクリプション引数とは異なり、これらのフィルターは設定できます。サブスクリプション引数の使用の詳細については、「[サブスクリプション引数の使用](aws-appsync-real-time-data.md#using-subscription-arguments)」を参照してください。演算子のリストについては、「[AWS AppSync リゾルバーマッピングテンプレートユーティリティリファレンス](resolver-util-reference.md)」を参照してください。

このドキュメントでは、リアルタイムデータフィルタリングを次のカテゴリに分類します。
+ **基本フィルタリング** - サブスクリプションクエリのクライアント定義引数に基づくフィルタリング。
+ **拡張フィルタリング** - AWS AppSync サービスバックエンドで一元的に定義されたロジックに基づくフィルタリング。

以下のセクションでは、拡張サブスクリプションフィルターの設定方法と、その実際の使用方法について説明します。

## GraphQL スキーマでのサブスクリプションの定義
<a name="aws-appsync-real-time-enhanced-filtering-using-subscription-filters"></a>

拡張サブスクリプションフィルターを使用するには、GraphQL スキーマでサブスクリプションを定義し、次にフィルター拡張機能を使用して拡張フィルターを定義します。拡張サブスクリプションフィルタリングの仕組みを説明するには AWS AppSync、チケット管理システム API を定義する次の GraphQL スキーマを例として使用します。

```
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.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)」を参照してください。

拡張フィルターの動作を実装するには、`extensions.setSubscriptionFilter()` 関数を使用して、サブスクライブされたクライアントが関心を持つ可能性のある GraphQL ミューテーションからの公開データに対して評価されるフィルター式を定義する必要があります。フィルター拡張機能の詳細については、「[拡張機能](https://docs.aws.amazon.com//appsync/latest/devguide/extensions-js.html)」を参照してください。

次のセクションでは、フィルターを使用して、拡張フィルターを使用する方法について説明します。

## フィルター拡張機能を使用して拡張サブスクリプションフィルターを作成する
<a name="aws-appsync-real-time-enhanced-filtering-defining-filters"></a>

拡張フィルターは、サブスクリプションのリゾルバーのレスポンスハンドラーに JSON で記述されます。フィルターは `filterGroup` というリストにまとめることができます。フィルターは、それぞれフィールド、演算子、値を含む少なくとも 1 つのルールを使用して定義されます。拡張フィルターを設定するための `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 
+ `severity` レベル `7`より大きいか等しい (`ge`\$1

OR 
+ `classification` チケットを`Security`に設定 

  AND 
+ `group`アサインを`admin`または`operators`に設定

![\[例: チケットフィルタリングクエリの表示例\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/aws-priority-example.png)


サブスクリプションリゾルバーで定義されたフィルター (拡張フィルター) は、サブスクリプション引数のみに基づくフィルター (基本フィルター) よりも優先されます。サブスクリプション引数の使用について詳しくは、「[サブスクリプション引数の使用](https://docs.aws.amazon.com//appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments)」を参照してください。

サブスクリプションの GraphQL スキーマで引数が定義されていて必要な場合、その引数がリゾルバーの `extensions.setSubscriptionFilter()` メソッドでルールとして定義されている場合にのみ、指定された引数に基づくフィルタリングが行われます。ただし、サブスクリプションリゾルバーに `extensions` フィルタリングメソッドがない場合、クライアントで定義された引数は基本的なフィルタリングにのみ使用されます。基本フィルターと拡張フィルターは同時に使用できません。

サブスクリプションのフィルター拡張ロジック内の[`context` 変数を使用して](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)、リクエストに関するコンテキスト情報にアクセスできます。例えば、Amazon Cognito ユーザープール、OIDC、または Lambda カスタムオーソライザーを認可に使用する場合、サブスクリプションが確立されたときに `context.identity` でユーザーに関する情報を取得できます。この情報を使用して、ユーザーの ID に基づいてフィルタを設定できます。

次に、拡張されたフィルタ動作を `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
  }
}
```

クライアントは引数なしでサブスクライブできます。これは、フィルタリングロジックが拡張フィルタリングを使用して AWS 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.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments)を使用して基本的なフィルタリングを使用できます。サブスクリプションクエリで呼び出しを行うクライアントは、引数の値を定義します。`extensions` フィルタリングを使用して AWS 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 リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)」を参照してください。

## その他の強化されたフィルタリング制限
<a name="aws-appsync-real-time-enhanced-filtering-additional-restrictions"></a>

拡張フィルターに追加の制限が課されるユースケースを以下に示します。
+ 拡張フィルタは、最上位のオブジェクトリストのフィルタリングをサポートしていません。このユースケースでは、ミューテーションから公開されたデータは拡張サブスクリプションでは無視されます。
+ AWS 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,
          }
      }
  }
  ```