教學課程:解析器 - AWS AppSync

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

教學課程:解析器

注意

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

本教學課程說明如何將自己的 Amazon DynamoDB 表格帶入AWS AppSync 並將其連接到 GraphQL API。

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

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

設定您的 DynamoDB 資料表

要開始本教程,首先您需要按照以下步驟佈建AWS資源。

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

    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堆疊。

    這將會建立下列項目:

    • 稱為將保Post存資料AppSyncTutorial-Post的 DynamoDB 資料表。

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

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

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

    aws cloudformation delete-stack --stack-name AWSAppSyncTutorialForAmazonDynamoDB

建立您的 GraphQL API

若要在 AWS AppSync 中建立 GraphQL API:

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

    1. API 儀表板中,選擇「建立 API」。

  2. 在「自訂您的 API 或從 Amazon DynamoDB 匯入」視窗下,選擇「從頭開始建立」。

    1. 選擇開始在同一窗口的右側。

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

  4. 選擇 建立

AWS AppSync 主控台會使用 API 金鑰身分驗證模式為您建立新 GraphQL API。您可以使用主控台來設定其他 GraphQL API 和對其執行查詢,以進行此教學的其他部分。

定義一個基本的後期 API

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

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

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

  2. 側邊欄中,選擇結構描述

    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. 選擇 儲存

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

設定 DynamoDB 表格的資料來源

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

首先,AWS AppSync 需要注意到您的資料表。您需要在 AWS AppSync 設定資料來源來這樣做:

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

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

    2. 側邊欄中,選擇「資料來源」。

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

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

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

    3. 在「區域」中,選擇「US-WEST-2」。

    4. 對於表格名稱,請選擇 AppSyncTutorial-發佈 DynamoDB 表。

    5. 建立新的 IAM 角色 (建議使用) 或選擇具有 lambda:invokeFunction IAM 權限的現有角色。現有角色需要信任原則,如附加資料來源一節所述。

      以下是具有對資源執行操作所需許可的 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. 選擇 建立

設定新 addPost 解析器 (DynamoDB 器) PutItem

瞭解 DynamoDB 表後 AWS AppSync ,您可以透過定義解析器將其連結至個別查詢和突變。您建立的第一個解析器是addPost解析器,它可讓您在 DynamoDB 表格中建立貼文。AppSyncTutorial-Post

解析程式具有下列元件:

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

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

  • 請求映射範本。要求映射範本的目的是從發起人取得傳入要求並將其轉譯至適合 AWS AppSync 的指示以針對 DynamoDB 執行。

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

設定解析程式:

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

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

    2. 側邊欄中,選擇「資料來源」。

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

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

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

    3. 在「區域」中,選擇「US-WEST-2」。

    4. 對於表格名稱,請選擇 AppSyncTutorial-發佈 DynamoDB 表。

    5. 建立新的 IAM 角色 (建議使用) 或選擇具有 lambda:invokeFunction IAM 權限的現有角色。現有角色需要信任原則,如附加資料來源一節所述。

      以下是具有對資源執行操作所需許可的 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. 選擇 建立

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

  5. 在右側的 [資料類型] 窗格中,尋找 [變異] 類型上的 [addPost] 欄位,然後選擇 [附加]。

  6. 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  7. 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  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 的新項目編製索引) 作為用戶端引數的一部分。 AWS AppSync帶有一個用於自動 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. 選擇 儲存

呼叫 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 使用請求對應文件來產生並執行 DynamoDB PutItem 請求。

  • 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-Post DynamoDB 資料表,您必須設定getPost查詢,才能從資料表擷取該資料。AppSyncTutorial-Post若要執行此作業,您可以設定另一個解析程式。

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

  • 在右側的 [資料類型] 窗格中,尋找 [查詢] 類型上的 getPost 欄位,然後選擇 [附加]。

  • 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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)
  • 選擇 儲存

呼叫 API 以取得文章

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

  • 選擇 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查詢只需要id、和 authortitle,您可以將請求對應範本變更為使用投影運算式,僅從 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! }
  • 選擇 儲存

  • 在右側的 [資料類型] 窗格中,在 [更] 類型上尋找新建立的 updatePost 欄位,然後選擇 [附加]。

  • 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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 更新運算式來完成的。表達式本身會在 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突變轉換為 DynamoDB 操作。Update您現在可以執行變動,以更新您之前撰寫的項目。

  • 選擇 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 對這些欄位執行任何動作。此外,由於您要求 DynamoDB 向version欄位新增 1 AWS AppSync ,因此欄位會增加 1。version

修改 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. 選擇 儲存

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

  5. 選擇「PostDynamo資料庫表格」以開啟現有的解析程式。

  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. 選擇 儲存

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

另外,還有新的 condition 區段。條件運算式可讓您根據 DynamoDB 中已有的物件狀態告訴AWS AppSync 和 DynamoDB 是否應該成功執行作業。在這種情況下,只有當 DynamoDB 中目前項目的version欄位與引數完全相符時,您才希望UpdateItem請求成功。expectedVersion

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

呼叫 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符。要求成功,這表示 DynamoDB 中的version欄位已遞增至。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! }
  • 選擇 儲存

  • 在右側的 [資料類型] 窗格中,尋找 [突變] 類型上新建立的 UpvotePost 欄位,然後選擇 [附加]。

  • 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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)
  • 選擇 儲存

  • 在右側的 [資料類型] 窗格中,在 [變異] 類型上尋找新建立的downvotePost欄位,然後選擇 [附加]。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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)
  • 選擇 儲存

呼叫 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 欄位設為選用,稍後在您新增要求映射範本時,將對此進行說明。

  • 選擇 儲存

  • 在右側的 [資料類型] 窗格中,在 [更] 類型上尋找新建立的刪除欄位,然後選擇 [附加]。

  • 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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 要求中指定條件表達式。無論 DynamoDB 中的值為何version,或項目是否存在,它都會成功。

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

    $utils.toJson($context.result)

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

  • 選擇 儲存

如需有關DeleteItem請求對應的詳細資訊,請參閱DeleteItem參考文件。

呼叫 API 以刪除文章

現在解析器已經設置好了,AWS AppSync 知道如何將傳入的delete突變轉換為 DynamoDB 操作。DeleteItem您現在可以執行變動以在資料表中刪除項目。

  • 選擇 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 Scan)

到目前為止,如果您知道要尋找之每個文章的 id,API 才有用。讓我們新增新的解析程式,傳回資料表中的所有文章。

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

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

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

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

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

  • 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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 解析程式傳回的物件不同:文章清單在 AWS AppSync DynamoDB 解析程式結果中稱為 items,但在 PaginatedPosts 中稱為 posts

  • 選擇 儲存

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

呼叫 API 以掃描所有文章

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

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

  • 選擇 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 } } }

設定 allPostsBy作者解析程式 (DynamoDB 查詢)

除了針對所有貼文掃描 DynamoDB 之外,您還可以查詢 DynamoDB 以擷取特定作者建立的貼文。您先前建立的 DynamoDB 表格已經具有author-index可與 DynamoDB 作業搭配使用的GlobalSecondaryIndex呼叫,以擷取特定Query作者建立的所有貼文。

  • 選擇 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 類型。

  • 選擇 儲存

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

  • 在「動作」功能表中,選擇「更新執行階段」,然後選擇「單位解析器(僅限 VTL)」。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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 解析程式中所使用的相同回應映射範本。

  • 選擇 儲存

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

呼叫 API 來查詢某個作者的所有文章

現在解析器已經設置好了,AWS AppSync 知道如何將傳入的allPostsByAuthor突變轉換為針對索引的 DynamoDB Query 操作。author-index您現在可以查詢資料表以擷取特定作者的所有文章。

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

  • 選擇 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! }
  • 選擇 儲存

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

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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 }
  • 選擇 儲存

  • 在右側的 [資料類型] 窗格中,在 [更] 類型上尋找新建立的 addTag 欄位,然後選擇 [附加]。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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)
  • 選擇 儲存

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

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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)
  • 選擇 儲存

呼叫 API 來使用標籤

現在,您已經設定解析器,AWS AppSync 知道如何將傳入addTagallPostsByTag請求轉換為 DynamoDB UpdateItem 和作業。removeTag Scan

為了嘗試看看,讓我們選擇您先前建立的其中一篇文章。例如,讓我們使用 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! }
  • 選擇 儲存

  • 在右側的 [資料類型] 窗格中,在 [更] 類型上尋找新建立的 addComment 欄位,然後選擇 [附加]。

  • 在 [資料來源名稱] 中,選擇 [資料PostDynamo表]。

  • 將以下內容貼到 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)
  • 選擇 儲存

呼叫 API 以新增評論

現在您已設定解析器,AWS AppSync 知道如何將傳入的addComment請求轉譯為 DynamoDB UpdateItem 作業。

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

  • 選擇 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." } ] } } }

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

結論

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

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

若要刪除針對本教學課程建立的 DynamoDB 表和 IAM 角色,您可以執行以下指令刪除AWSAppSyncTutorialForAmazonDynamoDB堆疊,或造訪AWS CloudFormation主控台並刪除堆疊:

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