使用 DynamoDB 解析程式建立簡單的後期應用程式 - AWS AppSync

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

使用 DynamoDB 解析程式建立簡單的後期應用程式

注意

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

本教學課程示範如何將自己的 Amazon DynamoDB 資料表帶至 AWS AppSync ,並將其連接至 GraphQL API。

您可以允許代表您 AWS AppSync 佈建 DynamoDB 資源。或者,如果您願意,您可以透過建立資料來源和解析程式來將現有的資料表連接到 GraphQL 結構描述。在這兩種情況下,您將能夠透過 GraphQL 陳述式讀取和寫入 DynamoDB 資料庫,以及訂閱即時資料。

有您必須完成的特定的組態步驟,才能讓 GraphQL 陳述式轉譯到 DynamoDB 操作,以及讓回應轉譯回 GraphQL。本教學課程概述透過幾個真實世界案例和資料存取模式的組態程序。

設定 DynamoDB 資料表

若要開始本教學課程,您必須先遵循下列步驟佈建 AWS 資源。

  1. 在 中使用下列 AWS CloudFormation 範本佈建 AWS 資源CLI:

    aws cloudformation create-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB \ --template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/dynamodb/AmazonDynamoDBCFTemplate.yaml \ --capabilities CAPABILITY_NAMED_IAM

    或者,您可以在帳戶中 AWS 的美國西部 2 區 (奧勒岡) 啟動下列 AWS CloudFormation 堆疊。

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

    這將會建立下列項目:

    • 稱為 AppSyncTutorial-Post的 DynamoDB 資料表,可存放Post資料。

    • 允許 AWS AppSync 與Post資料表互動IAM的角色和相關聯的IAM受管政策。

  2. 若要查看有關堆疊和已建立資源的詳細資訊,請執行下列CLI命令:

    aws cloudformation describe-stacks --stack-name AWSAppSyncTutorialForAmazonDynamoDB
  3. 之後若要刪除資源,您可以執行以下項目:

    aws cloudformation delete-stack --stack-name AWSAppSyncTutorialForAmazonDynamoDB

建立 GraphQL API

若要在 API中建立 GraphQL AWS AppSync:

  1. 登入 AWS Management Console 並開啟AppSync 主控台

    1. APIs儀表板 中,選擇建立 API

  2. 自訂您的 API或從 Amazon DynamoDB 匯入 視窗下,選擇從頭建置

    1. 選擇相同視窗右側的開始

  3. API名稱欄位中,將 的名稱API設定為 AWSAppSyncTutorial

  4. 選擇 Create (建立)。

AWS AppSync 主控台會使用API金鑰身分驗證模式API為您建立新的 GraphQL。您可以使用主控台設定 GraphQL 的其餘部分,API並在本教學課程的其餘部分針對它執行查詢。

定義基本文章 API

現在您已建立 AWS AppSync GraphQL API,您可以設定基本結構描述,允許基本建立、擷取和刪除貼文資料。

  1. 登入 AWS Management Console 並開啟AppSync 主控台

    1. APIs儀表板 中,選擇API您剛建立的 。

  2. Sidebar 中,選擇結構描述

    1. 結構描述窗格中,使用下列程式碼取代內容:

      schema { query: Query mutation: Mutation } type Query { getPost(id: ID): Post } type Mutation { addPost( id: ID! author: String! title: String! content: String! url: String! ): Post! } type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! }
  3. 選擇 Save (儲存)。

這個結構描述會定義 Post 類型和操作以新增和取得 Post 物件。

設定 DynamoDB 資料表的資料來源

接下來,將結構描述中定義的查詢和突變連結至 AppSyncTutorial-PostDynamoDB 資料表。

首先, AWS AppSync 需要注意資料表。您可以在 中設定資料來源來執行此操作 AWS AppSync:

  1. 登入 AWS Management Console 並開啟AppSync 主控台

    1. APIs儀表板 中,選擇您的 GraphQL API。

    2. Sidebar 中,選擇資料來源

  2. 選擇 Create data source (建立資料來源)

    1. 對於資料來源名稱 ,在 中輸入 PostDynamoDBTable

    2. 對於資料來源類型 ,選擇 Amazon DynamoDB 資料表

    3. 針對區域 ,選擇 US-WEST-2

    4. 針對資料表名稱 ,選擇 AppSyncTutorial-Post DynamoDB 資料表。

    5. 建立新的IAM角色 (建議) 或選擇具有 lambda:invokeFunctionIAM許可的現有角色。現有角色需要信任政策,如連接資料來源一節所述。

      以下是具有對資源執行操作所需許可的範例IAM政策:

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:invokeFunction" ], "Resource": [ "arn:aws:lambda:us-west-2:123456789012:function:myFunction", "arn:aws:lambda:us-west-2:123456789012:function:myFunction:*" ] } ] }
  3. 選擇 Create (建立)。

設定 addPost 解析器 (DynamoDB PutItem)

AWS AppSync 知道 DynamoDB 資料表後,您可以透過定義解析程式 將其連結至個別查詢和突變。您建立的第一個解析器是addPost解析器,可讓您在 AppSyncTutorial-Post DynamoDB 資料表中建立文章。

解析程式具有下列元件:

  • 在 GraphQL 結構描述中要附加解析程式的位置。在這種情況下,您會對 addPost 類型上的 Mutation 欄位設定解析程式。發起人呼叫 mutation { addPost(...){...} } 時會叫用此解析程式。

  • 用於此解析程式的資料來源。在這種情況下,您想要使用先前定義的 PostDynamoDBTable 資料來源,如此您可以將項目新增到 AppSyncTutorial-Post DynamoDB 資料表。

  • 請求映射範本。請求映射範本的目的是從來電者接收傳入的請求,並將其轉換為 的指示 AWS AppSync ,以針對 DynamoDB 執行 。

  • 回應映射範本。回應映射範本的任務即是從 DynamoDB 取得回應,並將其轉譯為 GraphQL 期望的項目。如果 DynamoDB 中的資料形狀與 GraphQL 中的 Post 類型不同,此功能會很有用,但如果他們的形狀一樣,您只需傳遞資料。

設定解析程式:

  1. 登入 AWS Management Console 並開啟AppSync 主控台

    1. APIs儀表板 中,選擇您的 GraphQL API。

    2. Sidebar 中,選擇資料來源

  2. 選擇 Create data source (建立資料來源)

    1. 對於資料來源名稱 ,在 中輸入 PostDynamoDBTable

    2. 對於資料來源類型 ,選擇 Amazon DynamoDB 資料表

    3. 針對區域 ,選擇 US-WEST-2

    4. 針對資料表名稱 ,選擇 AppSyncTutorial-Post DynamoDB 資料表。

    5. 建立新的IAM角色 (建議) 或選擇具有 lambda:invokeFunctionIAM許可的現有角色。現有角色需要信任政策,如連接資料來源一節所述。

      以下是具有對資源執行操作所需許可的範例IAM政策:

      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:invokeFunction" ], "Resource": [ "arn:aws:lambda:us-west-2:123456789012:function:myFunction", "arn:aws:lambda:us-west-2:123456789012:function:myFunction:*" ] } ] }
  3. 選擇 Create (建立)。

  4. 選擇 Schema (結構描述) 標籤。

  5. 在右側的資料類型窗格中,尋找突變類型的addPost欄位,然後選擇連接

  6. 動作選單 中,選擇更新執行時間 ,然後選擇單位解析程式 (VTL僅限 )

  7. Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  8. 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "attributeValues" : { "author" : $util.dynamodb.toDynamoDBJson($context.arguments.author), "title" : $util.dynamodb.toDynamoDBJson($context.arguments.title), "content" : $util.dynamodb.toDynamoDBJson($context.arguments.content), "url" : $util.dynamodb.toDynamoDBJson($context.arguments.url), "ups" : { "N" : 1 }, "downs" : { "N" : 0 }, "version" : { "N" : 1 } } }

    注意:所有金鑰和屬性值皆有指定的類型。例如,您將 author 欄位設為 { "S" : "${context.arguments.author}" }S 該部分表示 AWS AppSync 和 DynamoDB 的值將是字串值。會將實際值填入 author 引數。同樣地,version 欄位是號碼欄位,因為它會將 N 用於類型。最後,您也可以初始化 upsdownsversion 欄位。

    在本教學課程中,您已指定 GraphQL ID!類型,該類型會為插入 DynamoDB 的新項目編製索引,作為 client arguments. AWS AppSync comes 的一部分,並具有名為 的自動 ID 產生公用程式$utils.autoId(),您也可以以 的形式使用"id" : { "S" : "${$utils.autoId()}" }。然後,您可以直接將 id: ID! 移出 addPost() 的結構描述定義,該 ID 便會自動插入。您不會在本教學課程中使用此技巧,但在寫入 DynamoDB 資料表時,應該將其視為最佳實務。

    如需映射範本的詳細資訊,請參閱解析程式映射範本概觀參考文件。如需 GetItem 請求映射的詳細資訊,請參閱GetItem參考文件。如需有關類型的詳細資訊,請參閱類型系統 (要求映射) 參考文件。

  9. 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)

    注意:由於 AppSyncTutorial-Post 資料表中的資料形狀正好與 GraphQL 中的 Post 類型形狀相符,回應映射範本只需直接傳遞結果。另請注意,此教學課程中的所有範例會使用相同的回應映射範本,因此您只需建立一個檔案。

  10. 選擇 Save (儲存)。

呼叫 API以新增貼文

現在已設定解析程式, AWS AppSync 可將傳入addPost的突變轉譯為 DynamoDB PutItem 操作。您現在可以執行變動以將項目放置到資料表中。

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格:

    mutation addPost { addPost( id: 123 author: "AUTHORNAME" title: "Our first post!" content: "This is our first post." url: "https://aws.amazon.com/appsync/" ) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 新建立文章的結果應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "addPost": { "id": "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }

以下是發生的情況:

  • AWS AppSync 收到addPost突變請求。

  • AWS AppSync 接受了請求,請求映射範本,並產生了請求映射文件。此看起來如下:

    { "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "123" } }, "attributeValues" : { "author": { "S" : "AUTHORNAME" }, "title": { "S" : "Our first post!" }, "content": { "S" : "This is our first post." }, "url": { "S" : "https://aws.amazon.com/appsync/" }, "ups" : { "N" : 1 }, "downs" : { "N" : 0 }, "version" : { "N" : 1 } } }
  • AWS AppSync 使用請求映射文件來產生和執行 DynamoDBPutItem 請求。

  • AWS AppSync 取得PutItem請求的結果並將其轉換為 GraphQL 類型。

    { "id" : "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups" : 1, "downs" : 0, "version" : 1 }
  • 透過回應映射文件來進行傳遞,這可讓其以原狀進行傳遞。

  • 傳回在 GraphQL 回應中新建立的物件。

設定 getPost 解析程式 (DynamoDB GetItem

現在您可以將資料新增至 AppSyncTutorial-PostDynamoDB 資料表,您需要設定getPost查詢,以便從AppSyncTutorial-Post資料表擷取該資料。若要執行此作業,您可以設定另一個解析程式。

  • 選擇 Schema (結構描述) 標籤。

  • 在右側的資料類型窗格中,尋找查詢類型的getPost欄位,然後選擇連接

  • 動作選單 中,選擇更新執行時間 ,然後選擇單位解析程式 (VTL僅限 )

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id) } }
  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)
  • 選擇 Save (儲存)。

呼叫 API以取得文章

現在已設定解析器, AWS AppSync 知道如何將傳入的getPost查詢轉換為 DynamoDBGetItem 操作。您現在可以執行查詢,擷取您稍早建立的貼文。

  • 選擇 Queries (查詢) 標籤。

  • Queries (查詢) 窗格中,貼入下面內容:

    query getPost { getPost(id:123) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 從 DynamoDB 擷取的文章應出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "getPost": { "id": "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }

以下是發生的情況:

  • AWS AppSync 收到getPost查詢請求。

  • AWS AppSync 接受了請求,請求映射範本,並產生了請求映射文件。此看起來如下:

    { "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : { "S" : "123" } } }
  • AWS AppSync 使用請求映射文件來產生和執行 DynamoDB GetItem 請求。

  • AWS AppSync 取得GetItem請求的結果,並將其轉換為 GraphQL 類型。

    { "id" : "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups" : 1, "downs" : 0, "version" : 1 }
  • 透過回應映射文件來進行傳遞,這可讓其以原狀進行傳遞。

  • 在回應中傳回擷取的物件。

或者,採取下列範例:

query getPost { getPost(id:123) { id author title } }

如果您的getPost查詢只需要 idauthortitle,您可以變更請求映射範本,以使用投影表達式,以僅指定您想要從 DynamoDB 資料表傳輸到 的屬性,以避免不必要的資料從 DynamoDB 傳輸到 AWS AppSync。例如,請求映射範本可能看起來像下面的程式碼片段:

{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id) }, "projection" : { "expression" : "#author, id, title", "expressionNames" : { "#author" : "author"} } }

建立 updatePost 突變 DynamoDB UpdateItem)

到目前為止,您可以在 DynamoDB 中建立和擷取Post物件。接下來,您會設定新的變動,讓我們能夠更新物件。您將使用 UpdateItem DynamoDB 操作來執行此操作。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中的 Mutation 類型來新增 updatePost 變動,如下所示:

    type Mutation { updatePost( id: ID!, author: String!, title: String!, content: String!, url: String! ): Post addPost( author: String! title: String! content: String! url: String! ): Post! }
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立updatePost的欄位,然後選擇連接

  • 動作選單 中,選擇更新執行時間 ,然後選擇單位解析程式 (VTL僅限 )

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "SET author = :author, title = :title, content = :content, #url = :url ADD version :one", "expressionNames": { "#url" : "url" }, "expressionValues": { ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author), ":title" : $util.dynamodb.toDynamoDBJson($context.arguments.title), ":content" : $util.dynamodb.toDynamoDBJson($context.arguments.content), ":url" : $util.dynamodb.toDynamoDBJson($context.arguments.url), ":one" : { "N": 1 } } } }

    注意:此解析器正在使用 DynamoDB UpdateItem,這與 PutItem 操作明顯不同。您只是要求 DynamoDB 更新某些屬性,而不是撰寫整個項目。這是使用 DynamoDB Update Expressions 完成的。表達式本身會在 expression 區段中的 update 欄位中指定。其要求設定 authortitlecontent 以及 url 屬性,然後遞增 version 欄位。要使用的值不會出現在表達式本身;表達式的預留位置名稱開頭為冒號,其會在 expressionValues 欄位中加以定義。最後,DynamoDB 已預留了無法在 中顯示的單字expression。例如,由於 url 是保留字,因此若要更新 url 欄位,您可以使用名稱預留位置,並在 expressionNames 欄位中定義他們。

    如需UpdateItem請求映射的詳細資訊,請參閱UpdateItem參考文件。如需如何寫入更新表達式的詳細資訊,請參閱 DynamoDB UpdateExpressions 文件

  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)

呼叫 API以更新貼文

現在已設定解析程式, AWS AppSync 知道如何將傳入update的突變轉換為 DynamoDBUpdate 操作。您現在可以執行變動,以更新您之前撰寫的項目。

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation updatePost { updatePost( id:"123" author: "A new author" title: "An updated author!" content: "Now with updated content!" url: "https://aws.amazon.com/appsync/" ) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • DynamoDB 中的更新文章應出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "updatePost": { "id": "123", "author": "A new author", "title": "An updated author!", "content": "Now with updated content!", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 2 } } }

在此範例中, upsdowns 欄位並未修改,因為請求映射範本並未要求 AWS AppSync 和 DynamoDB 對這些欄位執行任何動作。此外,version由於您要求 AWS AppSync 和 DynamoDB 將 1 新增至 version 欄位,因此 欄位增量為 1。

修改 updatePost 解析程式 (DynamoDB UpdateItem

這對於 updatePost 變動而言是一個好的開始,但有兩個主要的問題:

  • 如果您只想更新單一欄位,您必須更新所有欄位。

  • 如果兩個人同時修改物件,您便可能會失去資訊。

為了解決這些問題,您將會修改 updatePost 變動,使其僅修改請求中指定的引數,然後將條件新增到 UpdateItem 操作。

  1. 選擇 Schema (結構描述) 標籤。

  2. Schema (結構描述) 窗格中,修改 Mutation 類型中的 updatePost 欄位,以便從 authortitlecontenturl 引數中移除驚嘆號,並請確保 id 欄位維持原狀。這會使它們變成可選引數。此外,新增必要 expectedVersion 引數。

    type Mutation { updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String! title: String! content: String! url: String! ): Post! }
  3. 選擇 Save (儲存)。

  4. 在右側的資料類型窗格中,尋找突變類型的updatePost欄位。

  5. 選擇 PostDynamoDBTable 以開啟現有的解析程式。

  6. Configure the request mapping template (設定要求映射範本) 中修改要求映射範本,如下所示:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, ## Set up some space to keep track of things you're updating ** #set( $expNames = {} ) #set( $expValues = {} ) #set( $expSet = {} ) #set( $expAdd = {} ) #set( $expRemove = [] ) ## Increment "version" by 1 ** $!{expAdd.put("version", ":one")} $!{expValues.put(":one", { "N" : 1 })} ## Iterate through each argument, skipping "id" and "expectedVersion" ** #foreach( $entry in $context.arguments.entrySet() ) #if( $entry.key != "id" && $entry.key != "expectedVersion" ) #if( (!$entry.value) && ("$!{entry.value}" == "") ) ## If the argument is set to "null", then remove that attribute from the item in DynamoDB ** #set( $discard = ${expRemove.add("#${entry.key}")} ) $!{expNames.put("#${entry.key}", "$entry.key")} #else ## Otherwise set (or update) the attribute on the item in DynamoDB ** $!{expSet.put("#${entry.key}", ":${entry.key}")} $!{expNames.put("#${entry.key}", "$entry.key")} $!{expValues.put(":${entry.key}", { "S" : "${entry.value}" })} #end #end #end ## Start building the update expression, starting with attributes you're going to SET ** #set( $expression = "" ) #if( !${expSet.isEmpty()} ) #set( $expression = "SET" ) #foreach( $entry in $expSet.entrySet() ) #set( $expression = "${expression} ${entry.key} = ${entry.value}" ) #if ( $foreach.hasNext ) #set( $expression = "${expression}," ) #end #end #end ## Continue building the update expression, adding attributes you're going to ADD ** #if( !${expAdd.isEmpty()} ) #set( $expression = "${expression} ADD" ) #foreach( $entry in $expAdd.entrySet() ) #set( $expression = "${expression} ${entry.key} ${entry.value}" ) #if ( $foreach.hasNext ) #set( $expression = "${expression}," ) #end #end #end ## Continue building the update expression, adding attributes you're going to REMOVE ** #if( !${expRemove.isEmpty()} ) #set( $expression = "${expression} REMOVE" ) #foreach( $entry in $expRemove ) #set( $expression = "${expression} ${entry}" ) #if ( $foreach.hasNext ) #set( $expression = "${expression}," ) #end #end #end ## Finally, write the update expression into the document, along with any expressionNames and expressionValues ** "update" : { "expression" : "${expression}" #if( !${expNames.isEmpty()} ) ,"expressionNames" : $utils.toJson($expNames) #end #if( !${expValues.isEmpty()} ) ,"expressionValues" : $utils.toJson($expValues) #end }, "condition" : { "expression" : "version = :expectedVersion", "expressionValues" : { ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion) } } }
  7. 選擇 Save (儲存)。

此範本是更為複雜的範例。它示範映射範本的強大功能和靈活性。它會循環使用所有引數,但會略過 idexpectedVersion。如果引數設定為某個項目,則會要求 AWS AppSync 和 DynamoDB 在 DynamoDB 中的物件上更新該屬性。如果屬性設定為 null,則會要求 AWS AppSync 和 DynamoDB 從後置物件中移除該屬性。若未指定引數,它將會保留該屬性。它會增量 version 欄位。

另外,還有新的 condition 區段。條件表達式可讓您根據 DynamoDB 中已存在的物件狀態,在執行操作之前,告知 AWS AppSync 和 DynamoDB 請求是否應成功。在此情況下,只有當 DynamoDB 中目前項目version的欄位完全符合expectedVersion引數時,您才希望UpdateItem請求成功。

如需條件表達式的詳細資訊,請參閱條件表達式參考文件。

呼叫 API以更新貼文

讓我們嘗試使用新解析程式來更新 Post 物件:

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation updatePost { updatePost( id:123 title: "An empty story" content: null expectedVersion: 2 ) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • DynamoDB 中的更新文章應出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "updatePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 3 } } }

在此請求中,您要求 AWS AppSync 和 DynamoDB 僅更新 titlecontent 欄位。它會將所有其他欄位單獨保留 (除了遞增 version 欄位)。您將 title 屬性設定為新的值,並從文章中移除 content 屬性。authorurlupsdowns 欄位維持原狀。

嘗試再次執行變動要求,讓要求維持原狀。您應該會看到類似以下的回應:

{ "data": { "updatePost": null }, "errors": [ { "path": [ "updatePost" ], "data": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 3 }, "errorType": "DynamoDB:ConditionalCheckFailedException", "locations": [ { "line": 2, "column": 3 } ], "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)" } ] }

條件表達式評估為「false」,因此要求失敗:

  • 第一次執行請求時,DynamoDB 中文章version的欄位值為 2,符合引expectedVersion數。請求成功,這表示version欄位已在 DynamoDB 中遞增至 3

  • 第二次執行請求時,DynamoDB 中文章version的欄位值為 3,與expectedVersion引數不相符。

此模式通常稱為樂觀鎖定

AWS AppSync DynamoDB 解析程式的特徵是它傳回 DynamoDB 中後物件的目前值。您可以在 GraphQL 回應的 data 區段 errors 欄位中找到此值。您的應用程式可以使用這些資訊來決定繼續執行的方式。在此情況下,您可以看到 DynamoDB 中物件version的欄位設定為 3,因此您只需要將expectedVersion引數更新為 3,請求就會再次成功。

如需有關處理條件檢查錯誤的詳細資訊,請參閱條件表達式映射範本參考文件。

建立 upvotePost 和 downvotePost 變更 DynamoDB UpdateItem)

Post 類型具有 upsdowns 欄位來啟用記錄上移和下移,但到目前為止, API不會讓我們對它們執行任何動作。讓我們新增一些變動來對文章表示贊同與不贊同。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中的 Mutation 類型以新增 upvotePostdownvotePost 變動,如下所示:

    type Mutation { upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立upvotePost的欄位,然後選擇連接

  • 動作選單 中,選擇更新執行時間 ,然後選擇單位解析程式 (VTL僅限 )

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD ups :plusOne, version :plusOne", "expressionValues" : { ":plusOne" : { "N" : 1 } } } }
  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立downvotePost的欄位,然後選擇連接

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD downs :plusOne, version :plusOne", "expressionValues" : { ":plusOne" : { "N" : 1 } } } }
  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)
  • 選擇 Save (儲存)。

呼叫 API以向上和向下修改貼文

現在已設定新的解析程式, AWS AppSync 知道如何將傳入upvotePostdownvote突變轉換為 DynamoDB UpdateItem 操作。您現在可以執行變動,對您之前建立的文章表達贊同或不贊同。

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation votePost { upvotePost(id:123) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 文章會在 DynamoDB 中更新,並會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "upvotePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 0, "version": 4 } } }
  • 再選擇幾次 Execute query (執行查詢)。您應查看在每次執行查詢時以 1 為單位而遞增的 upsversion 欄位。

  • 變更查詢以呼叫 downvotePost 變動,如下所示:

    mutation votePost { downvotePost(id:123) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。此時,您應查看在每次執行查詢時以 1 為單位而遞增的 downsversion 欄位。

    { "data": { "downvotePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 4, "version": 12 } } }

設定deletePost解析程式 (DynamoDB DeleteItem)

您要設定的下一個變動是刪除貼文。您將使用 DeleteItem DynamoDB 操作來執行此操作。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中的 Mutation 類型來新增 deletePost 變動,如下所示:

    type Mutation { deletePost(id: ID!, expectedVersion: Int): Post upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }

    這次您將 expectedVersion 欄位設為選用,稍後在您新增要求映射範本時,將對此進行說明。

  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立的刪除欄位,然後選擇連接

  • 動作選單 中,選擇更新執行時間 ,然後選擇 Unit Resolver (VTL 僅限 )

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "DeleteItem", "key": { "id": $util.dynamodb.toDynamoDBJson($context.arguments.id) } #if( $context.arguments.containsKey("expectedVersion") ) ,"condition" : { "expression" : "attribute_not_exists(id) OR version = :expectedVersion", "expressionValues" : { ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion) } } #end }

    注意:expectedVersion 引數為可選引數。如果呼叫者在請求中設定expectedVersion引數,則範本會新增條件,只有在項目已刪除,或 DynamoDB 中文章的version屬性完全符合 時,才會允許DeleteItem請求成功expectedVersion。如果省略,將不會在 DeleteItem 要求中指定條件表達式。無論 的值為何version,或 DynamoDB 中是否存在該項目,它都會成功。

  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)

    注意:即使您正在刪除某個項目,如果該項目尚未刪除,您仍然可以傳回已刪除的項目。

  • 選擇 Save (儲存)。

如需DeleteItem請求映射的詳細資訊,請參閱DeleteItem參考文件。

呼叫 API以刪除貼文

現在已設定解析程式, AWS AppSync 知道如何將傳入delete的突變轉譯為 DynamoDBDeleteItem 操作。您現在可以執行變動以在資料表中刪除項目。

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation deletePost { deletePost(id:123) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 文章會從 DynamoDB 中刪除。請注意, 會 AWS AppSync 傳回從 DynamoDB 刪除之項目的值,該值應出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "deletePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 4, "version": 12 } } }

如果對 deletePost 的呼叫實際上是從 DynamoDB 遭到刪除的呼叫,則只會傳回值。

  • 再次選擇 Execute query (執行查詢)

  • 此呼叫仍會成功,但不會傳回任何值。

    { "data": { "deletePost": null } }

現在讓我們嘗試刪除文章,但這次是指定 expectedValue。首先,您需要建立新文章,因為您刪除的正好是您到目前為止所用的文章。

  • 將以下變動貼到 Queries (查詢) 窗格:

    mutation addPost { addPost( id:123 author: "AUTHORNAME" title: "Our second post!" content: "A new post." url: "https://aws.amazon.com/appsync/" ) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 新建立文章的結果應該會出現在查詢窗格右側的結果窗格中。請記下新建立的物件的 id,因為您很快就會用到它。其看起來與下列類似:

    { "data": { "addPost": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }

現在讓我們嘗試刪除該文章,但我們將錯誤的值放入 expectedVersion

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation deletePost { deletePost( id:123 expectedVersion: 9999 ) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

    { "data": { "deletePost": null }, "errors": [ { "path": [ "deletePost" ], "data": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 }, "errorType": "DynamoDB:ConditionalCheckFailedException", "locations": [ { "line": 2, "column": 3 } ], "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)" } ] }

    請求失敗,因為條件表達式評估為 false:DynamoDB 中version帖子的值與引數中expectedValue指定的值不相符。會在 GraphQL 回應 data 區段中 errors 欄位傳回物件的目前值。

  • 重試要求,但更正 expectedVersion

    mutation deletePost { deletePost( id:123 expectedVersion: 1 ) { id author title content url ups downs version } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 這次請求成功,並傳回從 DynamoDB 刪除的值:

    { "data": { "deletePost": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }
  • 再次選擇 Execute query (執行查詢)

  • 呼叫仍然成功,但這次不會傳回任何值,因為文章已在 DynamoDB 中刪除。

{ "data": { "deletePost": null } }

設定allPost解析程式 (DynamoDB 掃描)

目前API為止,只有在您知道要查看的每個文章id的 時才有用。讓我們新增新的解析程式,傳回資料表中的所有文章。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中的 Query 類型以新增 allPost 查詢,如下所示:

    type Query { allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
  • 新增 PaginationPosts 類型:

    type PaginatedPosts { posts: [Post!]! nextToken: String }
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找查詢類型上新建立allPost的欄位,然後選擇連接

  • 動作選單 中,選擇更新執行時間 ,然後選擇單位解析程式 (VTL僅限 )

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "Scan" #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": $util.toJson($context.arguments.nextToken) #end }

    此解析程式有兩個選用引數:count 會指定單一呼叫中傳回的項目上限數,nextToken 可用來擷取下一組結果 (稍後您將顯示 nextToken 值來自何處)。

  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    { "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }

    注意:到目前為止,此回應映射範本與所有其他範本皆不同。allPost 查詢結果是 PaginatedPosts,其中包含文章清單和分頁字符。此物件的形狀與從 AWS AppSync DynamoDB Resolver 傳回的物件不同:文章清單在 AWS AppSync DynamoDB Resolver 結果items中呼叫,但在 posts中呼叫PaginatedPosts

  • 選擇 Save (儲存)。

如需有關 Scan 要求映射的詳細資訊,請參閱掃描參考文件。

呼叫 API以掃描所有貼文

現在已設定解析器, AWS AppSync 知道如何將傳入的allPost查詢轉換為 DynamoDBScan 操作。您現在可以掃描資料表來擷取所有文章。

在您可以嘗試之前,您必須將一些資料填入資料表,因為您已刪除目前為止所使用的項目。

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格:

    mutation addPost { post1: addPost(id:1 author: "AUTHORNAME" title: "A series of posts, Volume 1" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post2: addPost(id:2 author: "AUTHORNAME" title: "A series of posts, Volume 2" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post3: addPost(id:3 author: "AUTHORNAME" title: "A series of posts, Volume 3" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post4: addPost(id:4 author: "AUTHORNAME" title: "A series of posts, Volume 4" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post5: addPost(id:5 author: "AUTHORNAME" title: "A series of posts, Volume 5" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post6: addPost(id:6 author: "AUTHORNAME" title: "A series of posts, Volume 6" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post7: addPost(id:7 author: "AUTHORNAME" title: "A series of posts, Volume 7" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post8: addPost(id:8 author: "AUTHORNAME" title: "A series of posts, Volume 8" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post9: addPost(id:9 author: "AUTHORNAME" title: "A series of posts, Volume 9" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

現在,讓我們來掃描資料表,一次會傳回五個結果。

  • 將以下查詢貼到 Queries (查詢) 窗格中:

    query allPost { allPost(count: 5) { posts { id title } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 前五篇文章應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "allPost": { "posts": [ { "id": "5", "title": "A series of posts, Volume 5" }, { "id": "1", "title": "A series of posts, Volume 1" }, { "id": "6", "title": "A series of posts, Volume 6" }, { "id": "9", "title": "A series of posts, Volume 9" }, { "id": "7", "title": "A series of posts, Volume 7" } ], "nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRkJEdXdUK09hcnovRGhNTGxLTGdMUEFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF6ajFodkhKU1paT1pncTRaUUNBUkNBZ2dHWnJiR1dQWGxkMDB1N0xEdGY4Z2JsbktzRjRua1VCcks3TFJLcjZBTFRMeGFwVGJZMDRqOTdKVFQyYVRwSzdzbVdtNlhWWFVCTnFIOThZTzBWZHVkdDI2RlkxMHRqMDJ2QTlyNWJTUWpTbWh6NE5UclhUMG9KZWJSQ2JJbXBlaDRSVlg0Tis0WTVCN1IwNmJQWWQzOVhsbTlUTjBkZkFYMVErVCthaXZoNE5jMk50RitxVmU3SlJ5WmpzMEFkSGduM3FWd2VrOW5oeFVVd3JlK1loUks5QkRzemdiMDlmZmFPVXpzaFZ4cVJRbC93RURlOTcrRmVJdXZNby9NZ1F6dUdNbFRyalpNR3FuYzZBRnhwa0VlZTFtR0FwVDFISElUZlluakptYklmMGUzUmcxbVlnVHVSbDh4S0trNmR0QVoraEhLVDhuNUI3VnF4bHRtSnlNUXBrZGl6KzkyL3VzNDl4OWhrMnVxSW01ZFFwMjRLNnF0dm9ZK1BpdERuQTc5djhzb0grVytYT3VuQ2NVVDY4TVZ1Wk5KYkRuSEFSSEVlaTlVNVBTelU5RGZ6d2pPdmhqWDNJMWhwdWUrWi83MDVHVjlPQUxSTGlwZWZPeTFOZFhwZTdHRDZnQW00bUJUK2c1eC9Ec3ZDbWVnSDFDVXRTdHVuU1ZFa2JpZytQRC9oMUwyRTNqSHhVQldaa28yU256WUc0cG0vV1RSWkFVZHZuQT09In0=" } } }

您取得五個結果以及 nextToken,您可以用它來取得下一組結果。

  • 更新 allPost 查詢以包括來自之前結果組的 nextToken

    query allPost { allPost( count: 5 nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRlluNktJRWl6V0ZlR3hJOVJkaStrZUFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5cW8yUGFSZThnalFpemRCTUNBUkNBZ2dHWk1JODhUNzhIOFVUZGtpdFM2ZFluSWRyVDg4c2lkN1RjZzB2d1k3VGJTTWpSQ2U3WjY3TkUvU2I1dWNETUdDMmdmMHErSGJSL0pteGRzYzVEYnE1K3BmWEtBdU5jSENJdWNIUkJ0UHBPWVdWdCtsS2U5L1pNcWdocXhrem1RaXI1YnIvQkt6dU5hZmJCdE93NmtoM2Jna1BKM0RjWWhpMFBGbmhMVGg4TUVGSjBCcXg3RTlHR1V5N0tUS0JLZlV3RjFQZ0JRREdrNzFYQnFMK2R1S2IrVGtZZzVYMjFrc3NyQmFVTmNXZmhTeXE0ZUJHSWhqZWQ5c3VKWjBSSTc2ZnVQdlZkR3FLNENjQmxHYXhpekZnK2pKK1FneEU1SXduRTNYYU5TR0I4QUpmamR2bU1wbUk1SEdvWjlMUUswclczbG14RDRtMlBsaTNLaEVlcm9pem5zcmdINFpvcXIrN2ltRDN3QkJNd3BLbGQzNjV5Nnc4ZnMrK2FnbTFVOUlKOFFrOGd2bEgySHFROHZrZXBrMWlLdWRIQ25LaS9USnBlMk9JeEVPazVnRFlzRTRUU09HUlVJTkxYY2MvdW1WVEpBMUthV2hWTlAvdjNlSnlZQUszbWV6N2h5WHVXZ1BkTVBNWERQdTdjVnVRa3EwK3NhbGZOd2wvSUx4bHNyNDVwTEhuVFpyRWZvVlV1bXZ5S2VKY1RUU1lET05hM1NwWEd2UT09In0=" ) { posts { id author } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 剩餘的四篇文章應該會出現在查詢窗格右側的結果窗格中。在這組結果中沒有 nextToken,因為您已翻遍了所有九篇文章,已經沒有剩餘的文章。其看起來與下列類似:

    { "data": { "allPost": { "posts": [ { "id": "2", "title": "A series of posts, Volume 2" }, { "id": "3", "title": "A series of posts, Volume 3" }, { "id": "4", "title": "A series of posts, Volume 4" }, { "id": "8", "title": "A series of posts, Volume 8" } ], "nextToken": null } } }

設定 allPostsByAuthor Resolver (DynamoDB 查詢)

除了掃描所有文章的 DynamoDB 之外,您也可以查詢 DynamoDB 來擷取特定作者建立的文章。您先前建立的 DynamoDB 資料表已有 GlobalSecondaryIndex 呼叫author-index,您可以搭配 DynamoDBQuery 操作使用,以擷取特定作者建立的所有文章。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中的 Query 類型以新增 allPostsByAuthor 查詢,如下所示:

    type Query { allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts! allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }

    注意:這會使用與您在 allPost 查詢中使用的相同 PaginatedPosts 類型。

  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找查詢類型上新建立的allPostsBy作者欄位,然後選擇連接

  • 動作選單 中,選擇更新執行時間 ,然後選擇單位解析程式 (VTL僅限 )

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "Query", "index" : "author-index", "query" : { "expression": "author = :author", "expressionValues" : { ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author) } } #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": "${context.arguments.nextToken}" #end }

    如同 allPost 解析程式,此解析程式有兩個可選引數:count,其會指定項目的上限數,以在單一呼叫中傳回,以及 nextToken,其可用來擷取接下來的結果組 (您可從先前的呼叫中取得 nextToken 值)。

  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    { "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }

    注意:這是與您在 allPost 解析程式中所使用的相同回應映射範本。

  • 選擇 Save (儲存)。

如需有關 Query 要求映射的詳細資訊,請參閱查詢參考文件。

呼叫 API 以查詢作者的所有文章

現在已設定解析器, AWS AppSync 知道如何根據author-index索引將傳入的allPostsByAuthor突變轉譯至 DynamoDBQuery 操作。您現在可以查詢資料表以擷取特定作者的所有文章。

在這麼做之前,讓我們再將一些文章填入資料表,因為目前為止每篇文章的作者都一樣。

  • 選擇 Queries (查詢) 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格:

    mutation addPost { post1: addPost(id:10 author: "Nadia" title: "The cutest dog in the world" content: "So cute. So very, very cute." url: "https://aws.amazon.com/appsync/" ) { author, title } post2: addPost(id:11 author: "Nadia" title: "Did you know...?" content: "AppSync works offline?" url: "https://aws.amazon.com/appsync/" ) { author, title } post3: addPost(id:12 author: "Steve" title: "I like GraphQL" content: "It's great" url: "https://aws.amazon.com/appsync/" ) { author, title } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

現在,讓我們查詢資料表,傳回 Nadia 撰寫的所有文章。

  • 將以下查詢貼到 Queries (查詢) 窗格中:

    query allPostsByAuthor { allPostsByAuthor(author: "Nadia") { posts { id title } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • Nadia 撰寫的所有文章應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you know...?" } ], "nextToken": null } } }

分頁適用於 Query,如同它適用於 Scan。例如,讓我們查詢 AUTHORNAME 的所有文章,一次取得五篇。

  • 將以下查詢貼到 Queries (查詢) 窗格中:

    query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" count: 5 ) { posts { id title } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • AUTHORNAME 撰寫的所有文章應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "6", "title": "A series of posts, Volume 6" }, { "id": "4", "title": "A series of posts, Volume 4" }, { "id": "2", "title": "A series of posts, Volume 2" }, { "id": "7", "title": "A series of posts, Volume 7" }, { "id": "1", "title": "A series of posts, Volume 1" } ], "nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ==" } } }
  • 使用之前查詢傳回的值更新 nextToken 引數,如下所示:

    query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" count: 5 nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ==" ) { posts { id title } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • AUTHORNAME 撰寫的其餘文章應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "8", "title": "A series of posts, Volume 8" }, { "id": "5", "title": "A series of posts, Volume 5" }, { "id": "3", "title": "A series of posts, Volume 3" }, { "id": "9", "title": "A series of posts, Volume 9" } ], "nextToken": null } } }

使用集

到目前為止,Post 類型為統一金鑰/值物件。您也可以使用 AWS AppSyncDynamo資料庫解析程式建立複雜的物件模型,例如集、清單和地圖。

讓我們將 Post 類型更新為包含標籤。貼文可以有 0 個或更多的標籤,這些標籤以字串集的形式存放在 DynamoDB 中。您也會設定一些變動來新增和移除標籤,以及新查詢以掃描含特定標籤的文章。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中的 Post 類型以新增 tags 欄位,如下所示:

    type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] }
  • 修改 Schema (結構描述) 窗格中的 Query 類型以新增 allPostsByTag 查詢,如下所示:

    type Query { allPostsByTag(tag: String!, count: Int, nextToken: String): PaginatedPosts! allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts! allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
  • 修改 Schema (結構描述) 窗格中的 Mutation 類型以新增 addTagremoveTag 變動,如下所示:

    type Mutation { addTag(id: ID!, tag: String!): Post removeTag(id: ID!, tag: String!): Post deletePost(id: ID!, expectedVersion: Int): Post upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找查詢類型上新建立的allPostsBy標籤欄位,然後選擇連接

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "Scan", "filter": { "expression": "contains (tags, :tag)", "expressionValues": { ":tag": $util.dynamodb.toDynamoDBJson($context.arguments.tag) } } #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": $util.toJson($context.arguments.nextToken) #end }
  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    { "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立addTag的欄位,然後選擇連接

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD tags :tags, version :plusOne", "expressionValues" : { ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] }, ":plusOne" : { "N" : 1 } } } }
  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立removeTag的欄位,然後選擇連接

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "DELETE tags :tags ADD version :plusOne", "expressionValues" : { ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] }, ":plusOne" : { "N" : 1 } } } }
  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)
  • 選擇 Save (儲存)。

呼叫 API 以使用標籤

現在您已設定解析程式, AWS AppSync 知道如何將傳入的 removeTagaddTagallPostsByTag請求轉換為 DynamoDBUpdateItemScan操作。

為了嘗試看看,讓我們選擇您先前建立的其中一篇文章。例如,讓我們使用 Nadia 撰寫的一篇文章。

  • 選擇 Queries (查詢) 標籤。

  • 將以下查詢貼到 Queries (查詢) 窗格中:

    query allPostsByAuthor { allPostsByAuthor( author: "Nadia" ) { posts { id title } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • Nadia 的所有文章應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you known...?" } ], "nextToken": null } } }
  • 我們使用標題為 "The cutest dog in the world" 的文章。請記下其 id,因為您稍後將會用到它。

現在,讓我們嘗試新增 dog 標籤。

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation addTag { addTag(id:10 tag: "dog") { id title tags } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 使用新標籤更新的文章。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }

您可以新增更多的標籤,如下所示:

  • 更新變動以將 tag 引數變更為 puppy

    mutation addTag { addTag(id:10 tag: "puppy") { id title tags } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 使用新標籤更新的文章。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } } }

您也可以刪除標籤:

  • 將以下變動貼到 Queries (查詢) 窗格。您也必須將 id 引數更新為您先前記下的值。

    mutation removeTag { removeTag(id:10 tag: "puppy") { id title tags } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 貼文將會更新,且 puppy 標籤將會刪除。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }

您也可以搜尋所有包含標籤的貼文:

  • 將以下查詢貼到 Queries (查詢) 窗格中:

    query allPostsByTag { allPostsByTag(tag: "dog") { posts { id title tags } nextToken } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • 具有 dog 標籤的所有文章將會傳回,如下所示:

    { "data": { "allPostsByTag": { "posts": [ { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } ], "nextToken": null } } }

使用清單和映射

除了使用 DynamoDB 集之外,您還可以使用 DynamoDB 清單和地圖來建模單一物件中的複雜資料。

讓我們新增功能以將評論新增到文章。這將建模為 DynamoDB 中Post物件上的映射物件清單。

注意:在實際應用程式中,您會在它們自己的資料表中塑造評論。在本教學課程中,您將只是將它們新增至 Post 資料表。

  • 選擇 Schema (結構描述) 標籤。

  • 修改 Schema (結構描述) 窗格中新增 Comment 類型,如下所示:

    type Comment { author: String! comment: String! }
  • 修改 Schema (結構描述) 窗格中的 Post 類型以新增 comments 欄位,如下所示:

    type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] comments: [Comment!] }
  • 修改 Schema (結構描述) 窗格中的 Mutation 類型來新增 addComment 變動,如下所示:

    type Mutation { addComment(id: ID!, author: String!, comment: String!): Post addTag(id: ID!, tag: String!): Post removeTag(id: ID!, tag: String!): Post deletePost(id: ID!, expectedVersion: Int): Post upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
  • 選擇 Save (儲存)。

  • 在右側的資料類型窗格中,尋找突變類型上新建立addComment的欄位,然後選擇連接

  • Data source name (資料來源名稱) 中選擇 PostDynamoDBTable

  • 將以下內容貼到 Configure the request mapping template (設定請求映射範本) 區段:

    { "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "SET comments = list_append(if_not_exists(comments, :emptyList), :newComment) ADD version :plusOne", "expressionValues" : { ":emptyList": { "L" : [] }, ":newComment" : { "L" : [ { "M": { "author": $util.dynamodb.toDynamoDBJson($context.arguments.author), "comment": $util.dynamodb.toDynamoDBJson($context.arguments.comment) } } ] }, ":plusOne" : $util.dynamodb.toDynamoDBJson(1) } } }

    這個更新表達式將會將包含新評論的清單附加到現有的 comments 清單。如果清單不存在,則會建立一個。

  • 將以下內容貼到 Configure the response mapping template (設定回應映射範本) 區段:

    $utils.toJson($context.result)
  • 選擇 Save (儲存)。

呼叫 API以新增註解

現在您已設定解析器, AWS AppSync 知道如何將傳入addComment的請求轉換為 DynamoDBUpdateItem 操作。

讓我們透過將評論新增至您已新增標籤的相同文章,以嘗試此操作。

  • 選擇 Queries (查詢) 標籤。

  • 將以下查詢貼到 Queries (查詢) 窗格中:

    mutation addComment { addComment( id:10 author: "Steve" comment: "Such a cute dog." ) { id comments { author comment } } }
  • 選擇 Execute query (執行查詢) (橘色播放按鈕)。

  • Nadia 的所有文章應該會出現在查詢窗格右側的結果窗格中。其看起來與下列類似:

    { "data": { "addComment": { "id": "10", "comments": [ { "author": "Steve", "comment": "Such a cute dog." } ] } } }

如果您多次執行要求,系統會將多個評論附加到清單。

結論

在本教學課程中,您已建置 API,讓我們使用 AWS AppSync 和 GraphQL 在 DynamoDB 中操作 Post 物件。如需詳細資訊,請參閱解析程式映射範本參考

若要清除,您可以從API主控台刪除 AppSync GraphQL。

若要刪除 DynamoDB 資料表和您為本教學課程建立IAM的角色,您可以執行下列動作來刪除AWSAppSyncTutorialForAmazonDynamoDB堆疊,或造訪 AWS CloudFormation 主控台並刪除堆疊:

aws cloudformation delete-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB