での拡張サブスクリプションフィルターの定義 AWS AppSync - AWS AppSync GraphQL

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

での拡張サブスクリプションフィルターの定義 AWS AppSync

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

このドキュメントでは、リアルタイムデータフィルタリングを次のカテゴリに分類します。

  • 基本フィルタリング - サブスクリプションクエリのクライアント定義引数に基づくフィルタリング。

  • 拡張フィルタリング - AWS AppSync サービスバックエンドで一元的に定義されたロジックに基づくフィルタリング。

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

GraphQL スキーマでのサブスクリプションの定義

拡張サブスクリプションフィルターを使用するには、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 リゾルバーのハンドラーで有効になります。詳細については、「リゾルバーのリファレンス」を参照してください。

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

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

フィルター拡張機能を使用して拡張サブスクリプションフィルターを作成する

拡張フィルターは、サブスクリプションのリゾルバーのレスポンスハンドラーに 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}

または

  • classification チケットをSecurityに設定

    AND

  • groupアサインをadminまたはoperatorsに設定

例: チケットフィルタリングクエリの表示例

サブスクリプションリゾルバーで定義されたフィルター (拡張フィルター) は、サブスクリプション引数のみに基づくフィルター (基本フィルター) よりも優先されます。サブスクリプション引数の使用について詳しくは、「サブスクリプション引数の使用」を参照してください。

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

サブスクリプションのフィルター拡張ロジック内のcontext 変数を使用して、リクエストに関するコンテキスト情報にアクセスできます。例えば、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 サービスに実装されるため、クライアントは引数なしでサブスクライブできます。これにより、クライアントコードが簡素化されます。クライアントは、定義されたフィルター条件が満たされた場合にのみデータを受け取ります。

ネストされたスキーマフィールド用の拡張フィルターの定義

強化されたサブスクリプションフィルターを使用して、ネストされたスキーマフィールドをフィルターできます。前のセクションのスキーマをロケーションと住所のタイプを含むように変更したとします。

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 では、サブスクリプション引数を使用して基本的なフィルタリングを使用できます。サブスクリプションクエリで呼び出しを行うクライアントは、引数の値を定義します。フィルターを使用して AWS 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 リゾルバーの概要」を参照してください。

その他の強化されたフィルタリング制限

拡張フィルターに追加の制限が課されるユースケースを以下に示します。

  • 拡張フィルタは、最上位のオブジェクトリストのフィルタリングをサポートしていません。このユースケースでは、ミューテーションから公開されたデータは拡張サブスクリプションでは無視されます。

  • AWS AppSync は、最大 5 レベルのネストをサポートしています。ネストレベル 5 を超えるスキーマフィールドのフィルターは無視されます。以下の GraphQL レスポンスを見てください。venue.address.country.metadata.continentcontinent フィールドはレベル 5 のネストなので許可されています。ただし、venue.address.country.metadata.capital.financialfinancial はレベル 6 のネストなので、フィルターは機能しません。

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