アプリケーションデータの読み取り
Amplify GraphQLクライアントを使用してアプリケーションデータを読み取ることができます。このガイドでは、データの読み取りと取得の違い、必要なデータだけを取得するためのクエリ結果のフィルタリング方法、結果をより管理しやすくするためのページネーション方法について説明します。必要に応じてこれらのリクエストをキャンセルする方法も紹介します。
始める前に、以下が必要です:
- APIに接続されたアプリケーション
- 表示するために既に作成されたデータ
データのリストと取得
クエリはAPIを通じてデータを読み取るために使用され、listとgetの操作が含まれます。
Amplify CLIは、GraphQL APIの@modelタイプに対して、listとgetクエリを自動的に作成します。listクエリは、特定のレコードの識別子を指定する必要なく、Todoアイテムなどの複数のアイテムを取得します。これはアイテムの概要またはサマリーを取得するか、list操作を拡張して特定の条件でアイテムをフィルタリングするのに最適です。識別子で単一のエントリをクエリしたい場合は、getを使用して特定のTodoアイテムを取得します。
Amplify CLIは、すべての可能なGraphQL操作(ミューテーション、クエリ、サブスクリプション)のGraphQLクライアントコードを自動的に生成します。JavaScriptアプリケーションの場合、生成されたコードはデフォルトでsrc/graphqlフォルダに保存されます。
GraphQLクエリを実行するには、生成されたクエリをインポートして、client.graphqlで実行します:
import { generateClient } from 'aws-amplify/api';import * as queries from './graphql/queries';
const client = generateClient();
// Simple queryconst allTodos = await client.graphql({ query: queries.listTodos });console.log(allTodos); // result: { "data": { "listTodos": { "items": [/* ..... */] } } }
// Fetch a single record by its identifierconst oneTodo = await client.graphql({ query: queries.getTodo, variables: { id: 'some id' }});トラブルシューティング未認可エラーのトラブルシューティング
少なくとも1つの認可ルールが定義されていない場合、未認可エラーが発生する可能性があります。
@authディレクティブを使用して、パブリック、サインイン済みユーザー、ユーザーごと、およびユーザーグループごとのデータアクセスの認可ルールを構成します。認可ルールはデフォルトでの拒否の原則に基づいて動作します。つまり、認可ルールが明確に構成されていない場合、それは拒否されます。
type Todo @model @auth(rules: [{ allow: owner }]) { content: String}前の例では、各サインイン済みユーザーまたは「オーナー」がTodoの作成、読み取り、更新、および削除を行うことができます。
Amplifyは、許可されている操作を制限し、複数の認可ルールを組み合わせ、きめ細かいフィールドレベルの認可を適用することも可能にします。
type Todo @model @auth(rules: [{ allow: public, operations: [read] }, { allow: owner }]) { content: String}前の例では、すべてのユーザー(public)がすべてのTodoを読み取ることができますが、owner(認証されたユーザー)は自分のTodoの作成、読み取り、更新、および削除ができます。
詳細については、GraphQL APIの認可ルールを参照してください。
詳細データをクエリするカスタム認可モード
各AWS AppSync APIは、アプリを設定する際にデフォルトの認可モードを使用します。このデフォルトをオーバーライドするには、authModeプロパティを渡します。例えば、API Keyオーサリゼーションによるパブリック読み取りとIAMオーサリゼーションによる認証読み取りがある場合に便利です。次の例は、カスタム認可モードでデータをクエリする方法を示しています:
import { generateClient } from 'aws-amplify/api';import * as queries from './graphql/queries';
const client = generateClient();
const todos = await client.graphql({ query: queries.listTodos, authMode: GRAPHQL_AUTH_MODE.AWS_IAM});リストクエリのフィルタリング
データが増加するにつれて、リストクエリをページネーションする必要があります。幸いなことに、これはAmplifyが生成したGraphQL APIに既に組み込まれています。
import { generateClient } from 'aws-amplify/api';import { listTodos } from './graphql/queries';
const client = generateClient();
const variables = { filter: { priority: { eq: 1 } }};
await client.graphql({ query: listTodos, variables: variables});詳細フィルタはどのように機能しますか?
GraphQLエクスプローラーのドキュメントペインまたは自動生成された/graphqlフォルダ内でスキーマを入力するのは次のようなものです:
listTodos( filter: ModelTodoFilterInput limit: Int nextToken: String): ModelTodoConnection
input ModelTodoFilterInput { id: ModelIDInput priority: ModelIntInput # ... all your other Todo fields here and: [ModelTodoFilterInput] or: [ModelTodoFilterInput] not: ModelTodoFilterInput}スキーマの入力タイプは、それらに対して実行できるフィルタリングの種類を示します。例えば、ModelIntInputなどの整数フィールドには次のスキーマがあります:
input ModelIntInput { ne: Int # "not equal to" eq: Int # "equal to" le: Int # "less than or equal to" lt: Int # "less than" ge: Int # "greater than or equal to" gt: Int # "greater than" between: [Int] attributeExists: Boolean attributeType: ModelAttributeTypes}これらのフィルタはフィールドのタイプに基づいて異なりますが、対応するAmazon DynamoDBクエリにリンクされています。
複合フィルタ
and、or、notブール論理でフィルタを組み合わせることができます。前の自動生成されたスキーマで観察すると、ModelTodoFilterInputはそれらのフィールドに関して再帰的です。したがって、例えば、priority値が1_または_2をフィルタリングしたい場合、次のようにします:
import { generateClient } from 'aws-amplify/api';import { listTodos } from './graphql/queries';
const client = generateClient();
const variables = { filter: { or: [{ priority: { eq: 1 } }, { priority: { eq: 2 } }] }};
await client.graphql({ query: listTodos, variables: variables});自然言語ではなくブール論理であるため、priorityが1と2の両方をクエリするとは何の結果も返されないことに注意してください。
リストクエリのページネーション
リストクエリ結果をページネーションするには、nextTokenとlimit入力変数を設定して、後続のリストクエリリクエストを作成します。limit変数は、返される結果の数を制限します。応答には、次のページのデータをリクエストするために使用できるnextTokenが含まれます。nextTokenは、これらのフィルタで作成された次のクエリの開始アイテムのカーソルを表す非常に長い文字列です。
import { generateClient } from 'aws-amplify/api';import { listTodos } from './graphql/queries';
const client = generateClient();
const res = await client.graphql({ query: listTodos, variables: { // Fetch first 20 records limit: 20 }});
const { items: itemsPage1, nextToken } = res.data.listTodos;
// Fetch the next 20 recordsvariables.nextToken = nextToken;
const res = await client.graphql({ query: listTodos, variables: { limit: 20 }});
const { items: itemsPage2 } = res.data.listTodos;ウォークスルーGraphQL APIでページネーションを実装する
このウォークスルーは、ページネーションの実装に関する追加のステップバイステップのガイダンスを提供します。
大規模なレコードセットを使用する場合、最初のN個のアイテムのみを取得したい場合があります。例えば、Todoアプリの基本的なGraphQLスキーマから始めましょう:
type Todo @model { id: ID! title: String! description: String}APIが@modelディレクティブで作成されると、以下のクエリが自動的に作成されます:
type Query { getTodo(id: ID!): Todo listTodos( filter: ModelTodoFilterInput limit: Int nextToken: String ): ModelTodoConnection}次に、ModelTodoConnectionタイプを見て、listTodosクエリが実行されるときに返されるデータのアイデアを取得します:
type ModelTodoConnection { items: [Todo] nextToken: String}listTodosクエリを使用してAPIをクエリする場合、戻り値の型はModelTodoConnectionになります。これは、Todosの配列とnextTokenの両方を返すことができることを意味します。
nextTokenはページネーションを処理します。nextTokenがnullの場合、APIから返されるデータはこれ以上ありません。nextTokenが存在する場合、値を次のlistTodosクエリの引数として使用して、APIから次の選択セットを返すことができます。
これをテストするために、次のようなミューテーションを使用して5つのTodosを作成してください:
mutation createTodo { createTodo(input: { title: "Todo 1" description: "My first todo" }) { id title description }}次に、limit引数を指定してクエリ内のTodosの数の上限を設定できます。このクエリでは、上限を2つのアイテムに設定し、戻り値としてnextTokenをリクエストします:
query listTodos { listTodos(limit: 2) { items { id title description } nextToken }}次に、APIから次の2つのアイテムをクエリするには、このnextTokenを引数として指定します:
query listTodos { listTodos(limit: 2, nextToken: <your_token>) { items { id title description } nextToken }}返すべき他のアイテムがなくなると、応答のnextTokenはnullに設定されます。
JavaScriptアプリケーションからのクエリ
listTodosクエリはCLIによって自動生成されます。参照として、次のようなものになります:
const listTodos = ` query listTodos($limit: Int) { listTodos(limit: $limit) { items { id title description } nextToken } }`;JavaScriptアプリケーションからのクエリにlimitを指定するには、以下のコードを使用して変数として上限を設定することができます:
import { generateClient } from 'aws-amplify/api';
const client = generateClient();
async function fetchTodos() { const todoData = await client.graphql({ query: listTodos, variables: { limit: 2 } }); console.log({ todoData });}APIリクエストから返されるデータは次のようなもので、items配列には作成されたアイテムがいくつか含まれます:
{ "data" { "listTodos" { "items": [{ id: "001", title: "Todo 1", description: "My first todo" }], "nextToken": "<token-id>" } }}JavaScriptアプリケーションからのクエリにnextTokenを設定するには、以下のコードを使用できます:
import { generateClient } from 'aws-amplify/api';
const client = generateClient();
async function fetchTodos() { const todoData = await client.graphql({ query: listTodos, variables: { limit: 2, nextToken: '<token-id>' } }); console.log({ todoData });}読み取りリクエストをキャンセル
APIカテゴリを通じて作成されたクエリまたはミューテーションリクエストをキャンセルするには、返されたプロミスへの参照を保持することで可能です。
import { generateClient } from 'aws-amplify/api'
const client = generateClient()
const promise = client.graphql({ query: "..." });
try { await promise;} catch (error) { console.log(error); // If the error is because the request was cancelled you can confirm here. if (client.isCancelError(error)) { console.log(error.message); // "my message for cancellation" // handle user cancellation logic }}
...
// To cancel the above requestclient.cancel(promise, "my message for cancellation");client.graphql()から返されたプロミスが変更されていないことを確認する必要があります。通常、async関数は返されるプロミスを別のプロミスでラップします。例えば、以下は機能しません:
import { generateClient } from 'aws-amplify/api';
const client = generateClient();
async function makeAPICall() { return client.graphql({ query: '...' });}const promise = makeAPICall();
// The following will NOT cancel the request.client.cancel(promise, 'my error message');まとめ
おめでとうございます!アプリケーションデータの読み取りガイドを完了しました。このガイドでは、getおよびlistクエリを通じてデータを読み取る方法を学びました。
次のステップ
推奨される次のステップには、データのミューテーションを監視するためのリアルタイムイベントへのサブスクリプション、およびデータの情報アーキテクチャの構築と カスタマイズの続行が含まれます。このワークに役立つリソースには以下が含まれます: