合併 中的 GraphQL 解析程式 AWS AppSync - AWS AppSync

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

合併 中的 GraphQL 解析程式 AWS AppSync

注意

我們現在主要支援 APPSYNC_JS 執行期及其文件。請考慮在此處使用 APPSYNC_JS 執行期及其指南

GraphQL 結構描述中的解析程式與欄位具有一對一的關係,以及高度的彈性。由於資料來源是在解析程式上與結構描述個別獨立設定,因此您可以透過不同的資料來源來解析或操縱 GraphQL 的類型,對結構描述進行混合和匹配,最大程度地滿足您的需求。

下列範例案例示範如何在 結構描述中混合和比對資料來源。在開始之前,建議您熟悉設定 AWS Lambda、Amazon DynamoDB 和 Amazon OpenSearch Service 的資料來源和解析程式,如先前教學所述。

範例結構描述

下列結構描述的類型為 Post,已定義 3 個Query操作和 3 個Mutation操作:

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 個解析程式。其中一種可能的方法是讓所有這些都來自名為 的 Amazon DynamoDB 資料表Posts,其中 AllPosts會執行掃描並searchPosts執行查詢,如 DynamoDB Resolver 映射範本參考 所述。不過,還有其他替代方案可滿足您的業務需求,例如讓 Lambda 或 OpenSearch Service 解決這些 GraphQL 查詢。

透過解析程式來修改資料

您可能需要將 DynamoDB (或 Amazon Aurora) 等資料庫的結果傳回給已變更某些屬性的用戶端。這可能是資料類型的格式所造成 (例如用戶端上時間戳記的差異),或是為了處理回溯相容性的問題。為了說明起見,在以下範例中, AWS Lambda 函數會在每次叫用 GraphQL 解析器時指派隨機數字,藉此操控部落格文章的上演和下演:

'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 Service。然後,您只需將 searchPosts Resolver 連接至 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 資料表id,而 DynamoDB 來源的任何變更都會串流至您的 OpenSearch 服務網域。如需進行這項設定的詳細資訊,請參閱 DynamoDB 串流文件