執行批次操作 - AWS SDK for Java 2.x

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

執行批次操作

DynamoDB 增強型用戶端API提供兩種批次方法,batchGetItem()batchWriteItem()

batchGetItem() 範例

使用 DynamoDbEnhancedClient.batchGetItem()方法,您可以在一個整體請求中跨多個資料表擷取最多 100 個個別項目。下列範例使用先前顯示的 CustomerMovieActor 資料類別。

在第 1 行和第 2 行之後的範例中,您會建置物件,稍後在註解第 3 行之後將ReadBatch物件新增為batchGetItem()方法的參數。

註解行 1 之後的程式碼會建置要從Customer資料表讀取的批次。註解行 1a 後的程式碼顯示使用建置器,該GetItemEnhancedRequest建置器會取得主索引鍵值和排序索引鍵值,以指定要讀取的項目。如果資料類別具有複合索引鍵,您必須同時提供分割區索引鍵值和排序索引鍵值。

與指定要請求項目的索引鍵值相反,您可以使用資料類別來請求項目,如備註行 1b 所示。在提交請求之前, 會SDK擷取場景後方的索引鍵值。

當您使用金鑰型方法指定項目時,如 2a 之後的兩個陳述式所示,您也可以指定 DynamoDB 應執行非常一致的讀取。使用該consistentRead()方法時,必須將其用於相同資料表的所有請求項目。

若要擷取 DynamoDB 找到的項目,請使用備註行 4 之後顯示resultsForTable() 的方法。呼叫請求中讀取的每個資料表的方法。 會resultsForTable()傳回您可以使用任何java.util.List方法處理的已找到項目清單。此範例會記錄每個項目。

若要探索 DynamoDB 未處理的項目,請在註解第 5 行之後使用 方法。BatchGetResultPage 類別具有 unprocessedKeysForTable()方法,可讓您存取每個未處理的金鑰。BatchGetItem API 參考具有導致未處理項目之情況的詳細資訊。

public static void batchGetItemExample(DynamoDbEnhancedClient enhancedClient, DynamoDbTable<Customer> customerTable, DynamoDbTable<MovieActor> movieActorTable) { Customer customer2 = new Customer(); customer2.setId("2"); customer2.setEmail("cust2@example.org"); // 1. Build a batch to read from the Customer table. ReadBatch customerBatch = ReadBatch.builder(Customer.class) .mappedTableResource(customerTable) // 1a. Specify the primary key value and sort key value for the item. .addGetItem(b -> b.key(k -> k.partitionValue("1").sortValue("cust1@orgname.org"))) // 1b. Alternatively, supply a data class instances to provide the primary key values. .addGetItem(customer2) .build(); // 2. Build a batch to read from the MovieActor table. ReadBatch moveActorBatch = ReadBatch.builder(MovieActor.class) .mappedTableResource(movieActorTable) // 2a. Call consistentRead(Boolean.TRUE) for each item for the same table. .addGetItem(b -> b.key(k -> k.partitionValue("movie01").sortValue("actor1")).consistentRead(Boolean.TRUE)) .addGetItem(b -> b.key(k -> k.partitionValue("movie01").sortValue("actor4")).consistentRead(Boolean.TRUE)) .build(); // 3. Add ReadBatch objects to the request. BatchGetResultPageIterable resultPages = enhancedClient.batchGetItem(b -> b.readBatches(customerBatch, moveActorBatch)); // 4. Retrieve the successfully requested items from each table. resultPages.resultsForTable(customerTable).forEach(item -> logger.info(item.toString())); resultPages.resultsForTable(movieActorTable).forEach(item -> logger.info(item.toString())); // 5. Retrieve the keys of the items requested but not processed by the service. resultPages.forEach((BatchGetResultPage pageResult) -> { pageResult.unprocessedKeysForTable(customerTable).forEach(key -> logger.info("Unprocessed item key: " + key.toString())); pageResult.unprocessedKeysForTable(customerTable).forEach(key -> logger.info("Unprocessed item key: " + key.toString())); }); }

在執行範例程式碼之前,假設下列項目位於兩個資料表中。

Customer [id=1, name=CustName1, email=cust1@example.org, regDate=2023-03-31T15:46:27.688Z] Customer [id=2, name=CustName2, email=cust2@example.org, regDate=2023-03-31T15:46:28.688Z] Customer [id=3, name=CustName3, email=cust3@example.org, regDate=2023-03-31T15:46:29.688Z] Customer [id=4, name=CustName4, email=cust4@example.org, regDate=2023-03-31T15:46:30.688Z] Customer [id=5, name=CustName5, email=cust5@example.org, regDate=2023-03-31T15:46:31.689Z] MovieActor{movieName='movie01', actorName='actor0', actingAward='actingaward0', actingYear=2001, actingSchoolName='null'} MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'} MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'} MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'} MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}

下列輸出顯示註解行 4 之後傳回和記錄的項目。

Customer [id=1, name=CustName1, email=cust1@example.org, regDate=2023-03-31T15:46:27.688Z] Customer [id=2, name=CustName2, email=cust2@example.org, regDate=2023-03-31T15:46:28.688Z] MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'} MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}

batchWriteItem() 範例

batchWriteItem()方法會在一或多個資料表中放置或刪除多個項目。您可以在請求中指定最多 25 個個別放置或刪除操作。下列範例使用先前顯示的 ProductCatalogMovieActor 模型類別。

WriteBatch 物件是在註解行 1 和 2 之後建置。對於ProductCatalog資料表,程式碼會放置一個項目並刪除一個項目。對於註解行 2 之後的MovieActor資料表,程式碼會放置兩個項目並刪除一個項目。

batchWriteItem方法在註解行 3 之後呼叫。builder 參數提供每個資料表的批次請求。

傳回的BatchWriteResult物件為每個操作提供不同的方法來檢視未處理的請求。備註行 4a 後的程式碼提供未處理刪除請求的金鑰,備註行 4b 後的程式碼則提供未處理的放置項目。

public static void batchWriteItemExample(DynamoDbEnhancedClient enhancedClient, DynamoDbTable<ProductCatalog> catalogTable, DynamoDbTable<MovieActor> movieActorTable) { // 1. Build a batch to write to the ProductCatalog table. WriteBatch products = WriteBatch.builder(ProductCatalog.class) .mappedTableResource(catalogTable) .addPutItem(b -> b.item(getProductCatItem1())) .addDeleteItem(b -> b.key(k -> k .partitionValue(getProductCatItem2().id()) .sortValue(getProductCatItem2().title()))) .build(); // 2. Build a batch to write to the MovieActor table. WriteBatch movies = WriteBatch.builder(MovieActor.class) .mappedTableResource(movieActorTable) .addPutItem(getMovieActorYeoh()) .addPutItem(getMovieActorBlanchettPartial()) .addDeleteItem(b -> b.key(k -> k .partitionValue(getMovieActorStreep().getMovieName()) .sortValue(getMovieActorStreep().getActorName()))) .build(); // 3. Add WriteBatch objects to the request. BatchWriteResult batchWriteResult = enhancedClient.batchWriteItem(b -> b.writeBatches(products, movies)); // 4. Retrieve keys for items the service did not process. // 4a. 'unprocessedDeleteItemsForTable()' returns keys for delete requests that did not process. if (batchWriteResult.unprocessedDeleteItemsForTable(movieActorTable).size() > 0) { batchWriteResult.unprocessedDeleteItemsForTable(movieActorTable).forEach(key -> logger.info(key.toString())); } // 4b. 'unprocessedPutItemsForTable()' returns keys for put requests that did not process. if (batchWriteResult.unprocessedPutItemsForTable(catalogTable).size() > 0) { batchWriteResult.unprocessedPutItemsForTable(catalogTable).forEach(key -> logger.info(key.toString())); } }

下列協助程式方法提供放置和刪除操作的模型物件。

public static ProductCatalog getProductCatItem1() { return ProductCatalog.builder() .id(2) .isbn("1-565-85698") .authors(new HashSet<>(Arrays.asList("a", "b"))) .price(BigDecimal.valueOf(30.22)) .title("Title 55") .build(); } public static ProductCatalog getProductCatItem2() { return ProductCatalog.builder() .id(4) .price(BigDecimal.valueOf(40.00)) .title("Title 1") .build(); } public static MovieActor getMovieActorBlanchettPartial() { MovieActor movieActor = new MovieActor(); movieActor.setActorName("Cate Blanchett"); movieActor.setMovieName("Blue Jasmine"); movieActor.setActingYear(2023); movieActor.setActingAward("Best Actress"); return movieActor; } public static MovieActor getMovieActorStreep() { MovieActor movieActor = new MovieActor(); movieActor.setActorName("Meryl Streep"); movieActor.setMovieName("Sophie's Choice"); movieActor.setActingYear(1982); movieActor.setActingAward("Best Actress"); movieActor.setActingSchoolName("Yale School of Drama"); return movieActor; } public static MovieActor getMovieActorYeoh(){ MovieActor movieActor = new MovieActor(); movieActor.setActorName("Michelle Yeoh"); movieActor.setMovieName("Everything Everywhere All at Once"); movieActor.setActingYear(2023); movieActor.setActingAward("Best Actress"); movieActor.setActingSchoolName("Royal Academy of Dance"); return movieActor; }

在執行範例程式碼之前,假設資料表包含下列項目。

MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'} MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'} ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}

範例程式碼完成後,資料表包含下列項目。

MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='null'} MovieActor{movieName='Everything Everywhere All at Once', actorName='Michelle Yeoh', actingAward='Best Actress', actingYear=2023, actingSchoolName='Royal Academy of Dance'} ProductCatalog{id=2, title='Title 55', isbn='1-565-85698', authors=[a, b], price=30.22}

請注意,在MovieActor資料表中,Blue Jasmine影片項目已取代為透過getMovieActorBlanchettPartial()協助程式方法取得之放置請求中使用的項目。如果未提供資料 Bean 屬性值,則會移除資料庫中的值。這就是Blue Jasmine電影項目產生的 actingSchoolName 為 null 的原因。

注意

雖然API文件指出可以使用條件表達式,而且可以使用個別放置刪除請求來傳回耗用容量和收集指標,但在批次寫入案例中,情況並非如此。為了改善批次操作的效能,會忽略這些個別選項。