使用次要索引 - AWS SDK for Java 2.x

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

使用次要索引

次要索引透過定義您在查詢和掃描操作中使用的替代索引鍵來改善資料存取。全域次要索引 (GSI) 具有分割區索引鍵和排序索引鍵,其可能與基礎資料表上的索引鍵不同。相反地,本機次要索引 (LSI) 使用主要索引的分割區索引鍵。

使用次要索引註釋註釋資料類別

參與次要索引的屬性需要 @DynamoDbSecondaryPartitionKey@DynamoDbSecondarySortKey註釋。

下列類別會顯示兩個索引的註釋。GSI 名為 的 SubjectLastPostedDateIndex會使用分割區金鑰的 屬性,以及排序金鑰LastPostedDateTimeSubject 屬性。LSI 名為 的 ForumLastPostedDateIndex使用 ForumName作為其分割區金鑰,並將 LastPostedDateTime作為排序金鑰。

請注意, Subject 屬性提供雙重角色。這是 主金鑰的排序金鑰,以及GSI名為 的分割區金鑰SubjectLastPostedDateIndex

MessageThread 類別

MessageThread 該類別適合用作 Amazon DynamoDB 開發人員指南範例 Thread 資料表的資料類別。

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; import java.util.List;
@DynamoDbBean public class MessageThread { private String ForumName; private String Subject; private String Message; private String LastPostedBy; private String LastPostedDateTime; private Integer Views; private Integer Replies; private Integer Answered; private List<String> Tags; @DynamoDbPartitionKey public String getForumName() { return ForumName; } public void setForumName(String forumName) { ForumName = forumName; } // Sort key for primary index and partition key for GSI "SubjectLastPostedDateIndex". @DynamoDbSortKey @DynamoDbSecondaryPartitionKey(indexNames = "SubjectLastPostedDateIndex") public String getSubject() { return Subject; } public void setSubject(String subject) { Subject = subject; } // Sort key for GSI "SubjectLastPostedDateIndex" and sort key for LSI "ForumLastPostedDateIndex". @DynamoDbSecondarySortKey(indexNames = {"SubjectLastPostedDateIndex", "ForumLastPostedDateIndex"}) public String getLastPostedDateTime() { return LastPostedDateTime; } public void setLastPostedDateTime(String lastPostedDateTime) { LastPostedDateTime = lastPostedDateTime; } public String getMessage() { return Message; } public void setMessage(String message) { Message = message; } public String getLastPostedBy() { return LastPostedBy; } public void setLastPostedBy(String lastPostedBy) { LastPostedBy = lastPostedBy; } public Integer getViews() { return Views; } public void setViews(Integer views) { Views = views; } @DynamoDbSecondaryPartitionKey(indexNames = "ForumRepliesIndex") public Integer getReplies() { return Replies; } public void setReplies(Integer replies) { Replies = replies; } public Integer getAnswered() { return Answered; } public void setAnswered(Integer answered) { Answered = answered; } public List<String> getTags() { return Tags; } public void setTags(List<String> tags) { Tags = tags; } public MessageThread() { this.Answered = 0; this.LastPostedBy = ""; this.ForumName = ""; this.Message = ""; this.LastPostedDateTime = ""; this.Replies = 0; this.Views = 0; this.Subject = ""; } @Override public String toString() { return "MessageThread{" + "ForumName='" + ForumName + '\'' + ", Subject='" + Subject + '\'' + ", Message='" + Message + '\'' + ", LastPostedBy='" + LastPostedBy + '\'' + ", LastPostedDateTime='" + LastPostedDateTime + '\'' + ", Views=" + Views + ", Replies=" + Replies + ", Answered=" + Answered + ", Tags=" + Tags + '}'; } }

建立索引

從SDK適用於 Java 的 2.20.86 版開始,該createTable()方法會自動從資料類別註釋產生次要索引。根據預設,基礎資料表中的所有屬性都會複製到索引,且佈建的輸送量值為 20 個讀取容量單位和 20 個寫入容量單位。

不過,如果您使用 2.20.86 之前的 SDK版本,則需要建置索引與資料表,如下列範例所示。此範例會建置Thread資料表的兩個索引。建置器參數具有設定兩種索引類型的方法,如備註行 1 和 2 所示。您可以使用索引建置器indexName()的方法,將資料類別註釋中指定的索引名稱與預期的索引類型建立關聯。

此程式碼會設定所有資料表屬性,以在註解行 3 和 4 之後的兩個索引中最終結束。如需屬性投影的詳細資訊,請參閱 Amazon DynamoDB 開發人員指南

public static void createMessageThreadTable(DynamoDbTable<MessageThread> messageThreadDynamoDbTable, DynamoDbClient dynamoDbClient) { messageThreadDynamoDbTable.createTable(b -> b // 1. Generate the GSI. .globalSecondaryIndices(gsi -> gsi.indexName("SubjectLastPostedDateIndex") // 3. Populate the GSI with all attributes. .projection(p -> p .projectionType(ProjectionType.ALL)) ) // 2. Generate the LSI. .localSecondaryIndices(lsi -> lsi.indexName("ForumLastPostedDateIndex") // 4. Populate the LSI with all attributes. .projection(p -> p .projectionType(ProjectionType.ALL)) ) );

使用索引查詢

下列範例會查詢本機次要索引 ForumLastPostedDateIndex

在註解行 2 之後,您可以建立呼叫 DynamoDbIndex.query() 方法時所需的QueryConditional物件。

透過傳遞索引名稱,您可以在評論第 3 行之後取得要查詢的索引參考。在註解行 4 之後,您可以在傳遞至QueryConditional物件的索引上呼叫 query()方法。

您也可以將查詢設定為傳回三個屬性值,如備註行 5 所示。如果 attributesToProject() 未呼叫,查詢會傳回所有屬性值。請注意,指定的屬性名稱以小寫字母開頭。這些屬性名稱與資料表中使用的名稱相符,不一定是資料類別的屬性名稱。

在註解第 6 行之後,反覆查看結果,並記錄查詢傳回的每個項目,並將其存放在清單中以傳回給呼叫者。

public static List<MessageThread> queryUsingSecondaryIndices(DynamoDbEnhancedClient enhancedClient, String lastPostedDate, DynamoDbTable<MessageThread> threadTable) { // 1. Log the parameter value. logger.info("lastPostedDate value: {}", lastPostedDate); // 2. Create a QueryConditional whose sort key value must be greater than or equal to the parameter value. QueryConditional queryConditional = QueryConditional.sortGreaterThanOrEqualTo(qc -> qc.partitionValue("Forum02").sortValue(lastPostedDate)); // 3. Specify the index name to query the DynamoDbIndex instance. final DynamoDbIndex<MessageThread> forumLastPostedDateIndex = threadTable.index("ForumLastPostedDateIndex"); // 4. Perform the query by using the QueryConditional object. final SdkIterable<Page<MessageThread>> pagedResult = forumLastPostedDateIndex.query(q -> q .queryConditional(queryConditional) // 5. Request three attribute in the results. .attributesToProject("forumName", "subject", "lastPostedDateTime")); List<MessageThread> collectedItems = new ArrayList<>(); // 6. Iterate through the pages response and sort the items. pagedResult.stream().forEach(page -> page.items().stream() .sorted(Comparator.comparing(MessageThread::getLastPostedDateTime)) .forEach(mt -> { // 7. Log the returned items and add the collection to return to the caller. logger.info(mt.toString()); collectedItems.add(mt); })); return collectedItems; }

在執行查詢之前,資料庫中存在以下項目。

MessageThread{ForumName='Forum01', Subject='Subject01', Message='Message01', LastPostedBy='', LastPostedDateTime='2023.03.28', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject02', Message='Message02', LastPostedBy='', LastPostedDateTime='2023.03.29', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject04', Message='Message04', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject08', Message='Message08', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject10', Message='Message10', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum03', Subject='Subject03', Message='Message03', LastPostedBy='', LastPostedDateTime='2023.03.30', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum03', Subject='Subject06', Message='Message06', LastPostedBy='', LastPostedDateTime='2023.04.02', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum03', Subject='Subject09', Message='Message09', LastPostedBy='', LastPostedDateTime='2023.04.05', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum05', Subject='Subject05', Message='Message05', LastPostedBy='', LastPostedDateTime='2023.04.01', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum07', Subject='Subject07', Message='Message07', LastPostedBy='', LastPostedDateTime='2023.04.03', Views=0, Replies=0, Answered=0, Tags=null}

第 1 行和第 6 行的記錄陳述式會產生下列主控台輸出。

lastPostedDate value: 2023.03.31 MessageThread{ForumName='Forum02', Subject='Subject04', Message='', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject08', Message='', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject10', Message='', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}

查詢傳回forumName的值為 Forum02lastPostedDateTime值大於或等於 2023.03.31 的項目。結果會顯示具有空字串message的值,但message屬性在索引中具有值。這是因為訊息屬性並未在註解行 5 之後投影。