本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
在 中執行 DynamoDB 交易 AWS AppSync
注意
我們現在主要支援 APPSYNC_JS 執行期及其文件。請考慮在此處使用 APPSYNC_JS 執行期及其指南。
AWS AppSync 支援在單一區域中的一或多個資料表使用 Amazon DynamoDB 交易操作。支援的操作包括 TransactGetItems
和 TransactWriteItems
。透過在 中使用這些功能 AWS AppSync,您可以執行下列任務:
-
在單次查詢中傳遞索引鍵清單,並從資料表傳回結果
-
在單次查詢中讀取一個或多個資料表的記錄
-
以一種 all-or-nothing方式將交易中的記錄寫入一或多個資料表
-
符合某些條件時執行交易
許可
與其他解析程式一樣,您需要在 中建立資料來源, AWS AppSync 並建立角色或使用現有的資料來源。由於交易操作在 DynamoDB 資料表上需要不同的許可,因此您需要授予已設定的角色許可,以進行讀取或寫入動作:
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:accountId:table/TABLENAME", "arn:aws:dynamodb:region:accountId:table/TABLENAME/*" ] } ] }
注意:角色與 中的資料來源相關聯 AWS AppSync,欄位上的解析器會針對資料來源叫用。設定為針對 DynamoDB 擷取的資料來源只會指定一個資料表,以保持組態簡單。因此,在單一解析程式中針對多個資料表執行交易操作時 (這是一項更為進階的工作),您必須授予權限給該資料來源上的角色,以存取解析程式將會與其互動的所有資料表。這將在上述IAM政策的資源欄位中完成。針對資料表設定交易呼叫是在解析程式範本中完成,我們將會在下列內容中說明此範本。
資料來源
為簡單起見,我們將針對本教學課程中使用的所有解析程式,使用相同的資料來源。在資料來源索引標籤上,建立新的 DynamoDB 資料來源並命名為 TransactTutorial。資料表可以使用任何名稱,因為資料表名稱在交易操作中是指定為請求映射範本的一部分。我們會將資料表命名為 empty
。
我們將有兩個名為 savingAccounts和 的資料表checkingAccounts,兩個資料表都以 accountNumber
作為分割區金鑰,而一個transactionHistory資料表則以 transactionId
作為分割區金鑰。
在本教學課程中,具備下列內嵌政策的任何角色皆可使用。將 region
和 accountId
更換為您的區域和帳戶 ID:
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:accountId:table/savingAccounts", "arn:aws:dynamodb:region:accountId:table/savingAccounts/*", "arn:aws:dynamodb:region:accountId:table/checkingAccounts", "arn:aws:dynamodb:region:accountId:table/checkingAccounts/*", "arn:aws:dynamodb:region:accountId:table/transactionHistory", "arn:aws:dynamodb:region:accountId:table/transactionHistory/*" ] } ] }
交易
在此範例中,內容是傳統的銀行交易,我們將使用 TransactWriteItems
以進行下列操作:
-
從存款帳戶轉帳至支票帳戶
-
為每筆交易產生新的交易記錄
然後,我們會使用 TransactGetItems
擷取存款帳戶和支票帳戶中的詳細資料。
警告
TransactWriteItems
與衝突偵測和解決搭配使用時,不支援 。必須停用這些設定,以防止可能的錯誤。
定義 GraphQl 結構描述,如下所示:
type SavingAccount { accountNumber: String! username: String balance: Float } type CheckingAccount { accountNumber: String! username: String balance: Float } type TransactionHistory { transactionId: ID! from: String to: String amount: Float } type TransactionResult { savingAccounts: [SavingAccount] checkingAccounts: [CheckingAccount] transactionHistory: [TransactionHistory] } input SavingAccountInput { accountNumber: String! username: String balance: Float } input CheckingAccountInput { accountNumber: String! username: String balance: Float } input TransactionInput { savingAccountNumber: String! checkingAccountNumber: String! amount: Float! } type Query { getAccounts(savingAccountNumbers: [String], checkingAccountNumbers: [String]): TransactionResult } type Mutation { populateAccounts(savingAccounts: [SavingAccountInput], checkingAccounts: [CheckingAccountInput]): TransactionResult transferMoney(transactions: [TransactionInput]): TransactionResult } schema { query: Query mutation: Mutation }
TransactWriteItems - 填入帳戶
為了在帳戶之間轉帳,我們需要在表格中填入詳細資料。我們將使用 GraphQL 操作 Mutation.populateAccounts
來執行此作業。
在結構描述區段中,按一下Mutation.populateAccounts
操作旁的附加。前往VTL單位解析程式,然後選擇相同的TransactTutorial
資料來源。
現在使用下列請求映射範本:
請求映射範本
#set($savingAccountTransactPutItems = []) #set($index = 0) #foreach($savingAccount in ${ctx.args.savingAccounts}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($savingAccount.accountNumber))) #set($attributeValues = {}) $util.qr($attributeValues.put("username", $util.dynamodb.toString($savingAccount.username))) $util.qr($attributeValues.put("balance", $util.dynamodb.toNumber($savingAccount.balance))) #set($index = $index + 1) #set($savingAccountTransactPutItem = {"table": "savingAccounts", "operation": "PutItem", "key": $keyMap, "attributeValues": $attributeValues}) $util.qr($savingAccountTransactPutItems.add($savingAccountTransactPutItem)) #end #set($checkingAccountTransactPutItems = []) #set($index = 0) #foreach($checkingAccount in ${ctx.args.checkingAccounts}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($checkingAccount.accountNumber))) #set($attributeValues = {}) $util.qr($attributeValues.put("username", $util.dynamodb.toString($checkingAccount.username))) $util.qr($attributeValues.put("balance", $util.dynamodb.toNumber($checkingAccount.balance))) #set($index = $index + 1) #set($checkingAccountTransactPutItem = {"table": "checkingAccounts", "operation": "PutItem", "key": $keyMap, "attributeValues": $attributeValues}) $util.qr($checkingAccountTransactPutItems.add($checkingAccountTransactPutItem)) #end #set($transactItems = []) $util.qr($transactItems.addAll($savingAccountTransactPutItems)) $util.qr($transactItems.addAll($checkingAccountTransactPutItems)) { "version" : "2018-05-29", "operation" : "TransactWriteItems", "transactItems" : $util.toJson($transactItems) }
以及下列回應映射範本:
回應映射範本
#if ($ctx.error) $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons) #end #set($savingAccounts = []) #foreach($index in [0..2]) $util.qr($savingAccounts.add(${ctx.result.keys[$index]})) #end #set($checkingAccounts = []) #foreach($index in [3..5]) $util.qr($checkingAccounts.add(${ctx.result.keys[$index]})) #end #set($transactionResult = {}) $util.qr($transactionResult.put('savingAccounts', $savingAccounts)) $util.qr($transactionResult.put('checkingAccounts', $checkingAccounts)) $util.toJson($transactionResult)
儲存解析程式並導覽至 AWS AppSync 主控台的查詢區段以填入帳戶。
執行下列的變動:
mutation populateAccounts { populateAccounts ( savingAccounts: [ {accountNumber: "1", username: "Tom", balance: 100}, {accountNumber: "2", username: "Amy", balance: 90}, {accountNumber: "3", username: "Lily", balance: 80}, ] checkingAccounts: [ {accountNumber: "1", username: "Tom", balance: 70}, {accountNumber: "2", username: "Amy", balance: 60}, {accountNumber: "3", username: "Lily", balance: 50}, ]) { savingAccounts { accountNumber } checkingAccounts { accountNumber } } }
我們在一個變動中填入 3 個存款帳戶和 3 個支票帳戶。
使用 DynamoDB 主控台來驗證 savingAccounts和 checkingAccounts資料表中顯示的資料。
TransactWriteItems - 轉帳
使用下列請求映射範本 將解析器連接至 transferMoney
突變。請注意,amounts
、savingAccountNumbers
以及 checkingAccountNumbers
的值是相同的。
#set($amounts = []) #foreach($transaction in ${ctx.args.transactions}) #set($attributeValueMap = {}) $util.qr($attributeValueMap.put(":amount", $util.dynamodb.toNumber($transaction.amount))) $util.qr($amounts.add($attributeValueMap)) #end #set($savingAccountTransactUpdateItems = []) #set($index = 0) #foreach($transaction in ${ctx.args.transactions}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($transaction.savingAccountNumber))) #set($update = {}) $util.qr($update.put("expression", "SET balance = balance - :amount")) $util.qr($update.put("expressionValues", $amounts[$index])) #set($index = $index + 1) #set($savingAccountTransactUpdateItem = {"table": "savingAccounts", "operation": "UpdateItem", "key": $keyMap, "update": $update}) $util.qr($savingAccountTransactUpdateItems.add($savingAccountTransactUpdateItem)) #end #set($checkingAccountTransactUpdateItems = []) #set($index = 0) #foreach($transaction in ${ctx.args.transactions}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($transaction.checkingAccountNumber))) #set($update = {}) $util.qr($update.put("expression", "SET balance = balance + :amount")) $util.qr($update.put("expressionValues", $amounts[$index])) #set($index = $index + 1) #set($checkingAccountTransactUpdateItem = {"table": "checkingAccounts", "operation": "UpdateItem", "key": $keyMap, "update": $update}) $util.qr($checkingAccountTransactUpdateItems.add($checkingAccountTransactUpdateItem)) #end #set($transactionHistoryTransactPutItems = []) #foreach($transaction in ${ctx.args.transactions}) #set($keyMap = {}) $util.qr($keyMap.put("transactionId", $util.dynamodb.toString(${utils.autoId()}))) #set($attributeValues = {}) $util.qr($attributeValues.put("from", $util.dynamodb.toString($transaction.savingAccountNumber))) $util.qr($attributeValues.put("to", $util.dynamodb.toString($transaction.checkingAccountNumber))) $util.qr($attributeValues.put("amount", $util.dynamodb.toNumber($transaction.amount))) #set($transactionHistoryTransactPutItem = {"table": "transactionHistory", "operation": "PutItem", "key": $keyMap, "attributeValues": $attributeValues}) $util.qr($transactionHistoryTransactPutItems.add($transactionHistoryTransactPutItem)) #end #set($transactItems = []) $util.qr($transactItems.addAll($savingAccountTransactUpdateItems)) $util.qr($transactItems.addAll($checkingAccountTransactUpdateItems)) $util.qr($transactItems.addAll($transactionHistoryTransactPutItems)) { "version" : "2018-05-29", "operation" : "TransactWriteItems", "transactItems" : $util.toJson($transactItems) }
我們將會在單一 TransactWriteItems
操作中有 3 筆銀行交易。使用下列回應映射範本:
#if ($ctx.error) $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons) #end #set($savingAccounts = []) #foreach($index in [0..2]) $util.qr($savingAccounts.add(${ctx.result.keys[$index]})) #end #set($checkingAccounts = []) #foreach($index in [3..5]) $util.qr($checkingAccounts.add(${ctx.result.keys[$index]})) #end #set($transactionHistory = []) #foreach($index in [6..8]) $util.qr($transactionHistory.add(${ctx.result.keys[$index]})) #end #set($transactionResult = {}) $util.qr($transactionResult.put('savingAccounts', $savingAccounts)) $util.qr($transactionResult.put('checkingAccounts', $checkingAccounts)) $util.qr($transactionResult.put('transactionHistory', $transactionHistory)) $util.toJson($transactionResult)
現在,請導覽至 AWS AppSync 主控台的查詢區段,並執行如下transferMoney的突變:
mutation write { transferMoney( transactions: [ {savingAccountNumber: "1", checkingAccountNumber: "1", amount: 7.5}, {savingAccountNumber: "2", checkingAccountNumber: "2", amount: 6.0}, {savingAccountNumber: "3", checkingAccountNumber: "3", amount: 3.3} ]) { savingAccounts { accountNumber } checkingAccounts { accountNumber } transactionHistory { transactionId } } }
我們已傳送單一變動中的 2 筆銀行交易。使用 DynamoDB 主控台來驗證資料是否顯示在 savingAccounts、 checkingAccounts和 transactionHistory資料表中。
TransactGetItems - 擷取帳戶
為了擷取單一交易請求中存款帳戶和支票帳戶的詳細資料,我們會將解析程式附加至結構模式中的 Query.getAccounts
GraphQL 操作。選取連接 ,前往VTL單位解析程式,然後在下一個畫面上選取教學課程開始時建立的相同TransactTutorial
資料來源。設定範本,如下所示:
請求映射範本
#set($savingAccountsTransactGets = []) #foreach($savingAccountNumber in ${ctx.args.savingAccountNumbers}) #set($savingAccountKey = {}) $util.qr($savingAccountKey.put("accountNumber", $util.dynamodb.toString($savingAccountNumber))) #set($savingAccountTransactGet = {"table": "savingAccounts", "key": $savingAccountKey}) $util.qr($savingAccountsTransactGets.add($savingAccountTransactGet)) #end #set($checkingAccountsTransactGets = []) #foreach($checkingAccountNumber in ${ctx.args.checkingAccountNumbers}) #set($checkingAccountKey = {}) $util.qr($checkingAccountKey.put("accountNumber", $util.dynamodb.toString($checkingAccountNumber))) #set($checkingAccountTransactGet = {"table": "checkingAccounts", "key": $checkingAccountKey}) $util.qr($checkingAccountsTransactGets.add($checkingAccountTransactGet)) #end #set($transactItems = []) $util.qr($transactItems.addAll($savingAccountsTransactGets)) $util.qr($transactItems.addAll($checkingAccountsTransactGets)) { "version" : "2018-05-29", "operation" : "TransactGetItems", "transactItems" : $util.toJson($transactItems) }
回應映射範本
#if ($ctx.error) $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons) #end #set($savingAccounts = []) #foreach($index in [0..2]) $util.qr($savingAccounts.add(${ctx.result.items[$index]})) #end #set($checkingAccounts = []) #foreach($index in [3..4]) $util.qr($checkingAccounts.add($ctx.result.items[$index])) #end #set($transactionResult = {}) $util.qr($transactionResult.put('savingAccounts', $savingAccounts)) $util.qr($transactionResult.put('checkingAccounts', $checkingAccounts)) $util.toJson($transactionResult)
儲存解析程式並導覽至 AWS AppSync 主控台的查詢區段。若要擷取存款帳戶和支票帳戶,請執行下列查詢:
query getAccounts { getAccounts( savingAccountNumbers: ["1", "2", "3"], checkingAccountNumbers: ["1", "2"] ) { savingAccounts { accountNumber username balance } checkingAccounts { accountNumber username balance } } }
我們已成功使用 示範 DynamoDB 交易的使用 AWS AppSync。