での GraphQL リゾルバーの組み合わせ AWS AppSync - AWS AppSync

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

での GraphQL リゾルバーの組み合わせ AWS AppSync

注記

現在、主に APPSYNC_JS ランタイムとそのドキュメントをサポートしています。APPSYNC_JS ランタイムとそのガイドをここで使用することを検討してください。

GraphQL スキーマのリゾルバーとフィールドには、非常に柔軟性の高い 1 対 1 の関係があります。データソースはスキーマとは独立にリゾルバーに設定されるため、ニーズに応じてスキーマ上で組み合わせやマッチングを行い、さまざまなデータソースを使用して GraphQL 型の解決や操作が行えます。

次のシナリオ例では、スキーマ内のデータソースを混在させて一致させる方法を示します。開始する前に、前のチュートリアルで説明したように AWS Lambda、、Amazon DynamoDB、および Amazon OpenSearch Service のデータソースとリゾルバーの設定に精通しておくことをお勧めします。

スキーマの例

次のスキーマには、3 つの Query 処理と 3 つの Mutation 処理を含む Post という型が定義されています。

type Post { id: ID! author: String! title: String content: String url: String ups: Int downs: Int version: Int! } type Query { allPost: [Post] getPost(id: ID!): Post searchPosts: [Post] } type Mutation { addPost( id: ID!, author: String!, title: String, content: String, url: String ): Post updatePost( id: ID!, author: String!, title: String, content: String, url: String, ups: Int!, downs: Int!, expectedVersion: Int! ): Post deletePost(id: ID!): Post }

この例では、合計 6 つのリゾルバーをアタッチします。考えられる方法の 1 つは、これらをすべて Posts という Amazon DynamoDB テーブルから取得することです。この場合、「DynamoDB のリゾルバーのマッピングテンプレートリファレンス」で説明されているように、AllPosts はスキャンを実行し、searchPosts はクエリを実行します。ただし、これらの GraphQL クエリを Lambda または OpenSearch サービスから解決するなど、ビジネスニーズを満たす代替方法があります。

リゾルバーを使用してデータを変更する

DynamoDB (または Amazon Aurora) などのデータベースからクライアントに、一部の属性を変更した結果を返したい場合があります。クライアントでのタイムスタンプの相違などによるデータ型の成形が必要な場合や、後方互換性を確保するための処理が必要な場合などです。以下では、分かりやすい例として、GraphQL リゾルバーが呼び出されるたびに投稿にランダムな番号を割り当て、ブログの投稿に対する賛成または反対を操作する AWS Lambda 関数を示しています。

'use strict'; const doc = require('dynamodb-doc'); const dynamo = new doc.DynamoDB(); exports.handler = (event, context, callback) => { const payload = { TableName: 'Posts', Limit: 50, Select: 'ALL_ATTRIBUTES', }; dynamo.scan(payload, (err, data) => { const result = { data: data.Items.map(item =>{ item.ups = parseInt(Math.random() * (50 - 10) + 10, 10); item.downs = parseInt(Math.random() * (20 - 0) + 0, 10); return item; }) }; callback(err, result.data); }); };

これは完全に有効な Lambda 関数であり、GraphQL スキーマの AllPosts フィールドにアタッチできるため、すべての結果を返すクエリが、賛成/反対に対するランダムな番号を受け取ります。

DynamoDB と OpenSearch サービス

一部のアプリケーションでは、DynamoDB に対してミューテーションクエリまたは簡易検索クエリを実行し、バックグラウンドプロセスでドキュメントを OpenSearch サービスに転送する場合があります。その後、searchPostsResolver を OpenSearch サービスデータソースにアタッチし、GraphQL クエリを使用して (DynamoDB で生成されたデータから) 検索結果を返すだけです。これは、キーワードやあいまいワードによる検索、地理空間検索などの高度な検索処理をアプリケーションに追加する場合に非常に役立ちます。DynamoDB からのデータ転送は、 ETLプロセスを通じて行うか、Lambda を使用して DynamoDB からストリーミングできます。 AWS アカウントの米国西部 2 (オレゴン) リージョンで、次の AWS CloudFormation スタックを使用して、この完全な例を起動できます。

Blue button labeled "Launch Stack" with an arrow icon indicating an action to start.

この例では、スキーマは以下のような DynamoDB リゾルバーを使用して投稿を追加します。

mutation add { putPost(author:"Nadia" title:"My first post" content:"This is some test content" url:"https://aws.amazon.com/appsync/" ){ id title } }

これにより、データが DynamoDB に書き込まれ、Lambda 経由で Amazon OpenSearch Service にデータがストリーミングされます。これにより、異なるフィールドですべての投稿を検索できます。例えば、データは Amazon OpenSearch Service にあるため、次のように、スペースを含む自由形式のテキストで作成者フィールドまたはコンテンツフィールドを検索できます。

query searchName{ searchAuthor(name:" Nadia "){ id title content } } query searchContent{ searchContent(text:"test"){ id title content } }

データは DynamoDB に直接書き込まれるため、allPosts{...} クエリと singlePost{...} クエリを使用して、テーブルに対するリストまたは項目の検索処理が効率的に実行できます。このスタックでは、DynamoDB ストリームに対して次のコード例を使用します。

注意 : ここで示しているのは一例にすぎません。

var AWS = require('aws-sdk'); var path = require('path'); var stream = require('stream'); var esDomain = { endpoint: 'https://opensearch-domain-name.REGION.es.amazonaws.com', region: 'REGION', index: 'id', doctype: 'post' }; var endpoint = new AWS.Endpoint(esDomain.endpoint) var creds = new AWS.EnvironmentCredentials('AWS'); function postDocumentToES(doc, context) { var req = new AWS.HttpRequest(endpoint); req.method = 'POST'; req.path = '/_bulk'; req.region = esDomain.region; req.body = doc; req.headers['presigned-expires'] = false; req.headers['Host'] = endpoint.host; // Sign the request (Sigv4) var signer = new AWS.Signers.V4(req, 'es'); signer.addAuthorization(creds, new Date()); // Post document to ES var send = new AWS.NodeHttpClient(); send.handleRequest(req, null, function (httpResp) { var body = ''; httpResp.on('data', function (chunk) { body += chunk; }); httpResp.on('end', function (chunk) { console.log('Successful', body); context.succeed(); }); }, function (err) { console.log('Error: ' + err); context.fail(); }); } exports.handler = (event, context, callback) => { console.log("event => " + JSON.stringify(event)); var posts = ''; for (var i = 0; i < event.Records.length; i++) { var eventName = event.Records[i].eventName; var actionType = ''; var image; var noDoc = false; switch (eventName) { case 'INSERT': actionType = 'create'; image = event.Records[i].dynamodb.NewImage; break; case 'MODIFY': actionType = 'update'; image = event.Records[i].dynamodb.NewImage; break; case 'REMOVE': actionType = 'delete'; image = event.Records[i].dynamodb.OldImage; noDoc = true; break; } if (typeof image !== "undefined") { var postData = {}; for (var key in image) { if (image.hasOwnProperty(key)) { if (key === 'postId') { postData['id'] = image[key].S; } else { var val = image[key]; if (val.hasOwnProperty('S')) { postData[key] = val.S; } else if (val.hasOwnProperty('N')) { postData[key] = val.N; } } } } var action = {}; action[actionType] = {}; action[actionType]._index = 'id'; action[actionType]._type = 'post'; action[actionType]._id = postData['id']; posts += [ JSON.stringify(action), ].concat(noDoc?[]:[JSON.stringify(postData)]).join('\n') + '\n'; } } console.log('posts:',posts); postDocumentToES(posts, context); };

その後、DynamoDB ストリームを使用してこれを のプライマリキーを持つ DynamoDB テーブルにアタッチできます。DynamoDB のソースへの変更はid、 OpenSearch サービスドメインにストリーミングされます。この設定の詳細については、DynamoDB Streams のドキュメントを参照してください。