View a markdown version of this page

Verwenden Sie sekundäre Indizes - AWS SDK for Java 2.x

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Verwenden Sie sekundäre Indizes

Der Primärschlüssel einer Tabelle definiert den Primärindex, der bestimmt, wie DynamoDB standardmäßig Elemente speichert und abruft.

Sekundäre Indizes bieten alternative Schlüssel, die Sie bei Abfrage- und Scanvorgängen verwenden. Globale Sekundärindizes (GSI) haben einen Partitionsschlüssel und einen optionalen Sortierschlüssel, die sich von denen in der Basistabelle unterscheiden können. Im Gegensatz dazu teilen sich lokale Sekundärindizes (LSI) den Partitionsschlüssel des Primärindexes, definieren aber einen anderen Sortierschlüssel.

Definieren Sie Schlüssel für globale und lokale Sekundärindizes

Für Attribute, die an Sekundärindizes beteiligt sind, ist entweder die @DynamoDbSecondarySortKey Anmerkung @DynamoDbSecondaryPartitionKey oder erforderlich.

Die folgende Klasse zeigt Anmerkungen für zwei Indizes. Die angegebene GSI SubjectLastPostedDateIndexverwendet das Subject Attribut für den Partitionsschlüssel und das LastPostedDateTime für den Sortierschlüssel. Die benannte LSI ForumLastPostedDateIndexverwendet den ForumName als Partitionsschlüssel und LastPostedDateTime als Sortierschlüssel.

Beachten Sie, dass das Subject Attribut eine doppelte Rolle spielt. Es ist der Sortierschlüssel des Primärschlüssels und der Partitionsschlüssel der genannten SubjectLastPostedDateIndexGSI.

MessageThread-Klasse

Die MessageThread Klasse eignet sich als Datenklasse für die Thread-Beispieltabelle im Amazon DynamoDB Developer Guide.

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 + '}'; } }

Erstellen Sie den Index

Ab Version 2.20.86 des SDK for Java generiert die createTable() Methode automatisch Sekundärindizes aus Datenklassenanmerkungen. Standardmäßig werden alle Attribute aus der Basistabelle in einen Index kopiert, und die bereitgestellten Durchsatzwerte betragen 20 Lesekapazitätseinheiten und 20 Schreibkapazitätseinheiten.

Wenn Sie jedoch eine SDK-Version vor 2.20.86 verwenden, müssen Sie den Index zusammen mit der Tabelle erstellen, wie im folgenden Beispiel gezeigt. In diesem Beispiel werden die beiden Indizes für die Tabelle erstellt. Thread Der Builder-Parameter verfügt über Methoden zur Konfiguration beider Indextypen, wie nach den Kommentarzeilen 1 und 2 gezeigt. Sie verwenden die indexName() Methode des Indexgenerators, um die in den Datenklassenanmerkungen angegebenen Indexnamen dem gewünschten Indextyp zuzuordnen.

Dieser Code konfiguriert alle Tabellenattribute so, dass sie nach den Kommentarzeilen 3 und 4 in beiden Indizes landen. Weitere Informationen zu Attributprojektionen finden Sie im Amazon DynamoDB Developer Guide.

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)) ) );

Abfragen mithilfe eines Indexes

Im folgenden Beispiel wird der lokale sekundäre Index ForumLastPostedDateIndex abgefragt.

Nach Kommentarzeile 2 erstellen Sie ein QueryConditionalObjekt, das für den Aufruf der Methode DynamoDbIndex.query() erforderlich ist.

Sie erhalten nach Kommentarzeile 3 einen Verweis auf den Index, den Sie abfragen möchten, indem Sie den Namen des Indexes übergeben. Nach Kommentarzeile 4 rufen Sie die query() Methode für den Index auf und übergeben das QueryConditional Objekt.

Sie konfigurieren die Abfrage auch so, dass sie drei Attributwerte zurückgibt, wie nach Kommentarzeile 5 gezeigt. Wenn nicht aufgerufen attributesToProject() wird, gibt die Abfrage alle Attributwerte zurück. Beachten Sie, dass die angegebenen Attributnamen mit Kleinbuchstaben beginnen. Diese Attributnamen stimmen mit denen überein, die in der Tabelle verwendet werden, nicht unbedingt mit den Attributnamen der Datenklasse.

Folgen Sie der Kommentarzeile 6 und wiederholen Sie die Ergebnisse, protokollieren Sie jedes von der Abfrage zurückgegebene Element und speichern Sie es auch in der Liste, um zum Aufrufer zurückzukehren.

public class IndexScanExamples { private static Logger logger = LoggerFactory.getLogger(IndexScanExamples.class); public static List<MessageThread> queryUsingSecondaryIndices(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. final DynamoDbIndex<MessageThread> forumLastPostedDateIndex = threadTable.index("ForumLastPostedDateIndex"); // 4. Perform the query 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 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; }

Die folgenden Elemente sind in der Datenbank vorhanden, bevor die Abfrage ausgeführt wird.

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}

Die Protokollierungsanweisungen in den Zeilen 1 und 6 führen zu der folgenden Konsolenausgabe.

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}

Die Abfrage hat Elemente mit dem forumName Wert Forum02 und einem lastPostedDateTime Wert größer oder gleich 2023.03.31 zurückgegeben. Die Ergebnisse zeigen message Werte mit einer leeren Zeichenfolge, obwohl die message Attribute Werte im Index haben. Das liegt daran, dass das Nachrichtenattribut im Code nach Kommentarzeile 5 nicht projiziert wurde.

Verwenden Sie zusammengesetzte Schlüssel für globale Sekundärindizes (GSI)

Das SDK for Java 2.x DynamoDB Enhanced Client unterstützt zusammengesetzte Schlüssel für globale Sekundärindizes. Sie können bis zu vier Partitionsschlüsselattribute und vier Sortierschlüsselattribute für eine einzelne GSI definieren. Dadurch entfällt die Notwendigkeit, mehrere Attribute auf der Clientseite zu einem einzigen Zeichenkettenschlüssel zu verketten.

Verwenden Sie den order Parameter in den @DynamoDbSecondarySortKey Anmerkungen @DynamoDbSecondaryPartitionKey und, um die Position der einzelnen Attribute im zusammengesetzten Schlüssel anzugeben. Der order Parameter akzeptiert Werte aus der OrderEnumeration (Teil des erweiterten DynamoDB-Clients):FIRST,SECOND, THIRD und. FOURTH

Kommentieren Sie die Datenklasse mit Anmerkungen zu zusammengesetzten Schlüsseln

Das folgende Beispiel modelliert eine Bestelltabelle. Die Basistabelle verwendet orderId als Partitionsschlüssel. Eine GSI mit dem Namen OrdersByStatusDateAmountverwendet einen zusammengesetzten Partitionsschlüssel von customerId und status und einen zusammengesetzten Sortierschlüssel von orderDate undamount. Mit diesem Design können Sie die Bestellungen eines Kunden, gefiltert nach Status, Datum und Schwellenwert, abfragen.

import software.amazon.awssdk.enhanced.dynamodb.mapper.Order; 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;
@DynamoDbBean public class OrderItem { private String orderId; private String customerId; private String status; private String orderDate; private Integer amount; @DynamoDbPartitionKey public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } // First partition key attribute for the GSI. @DynamoDbSecondaryPartitionKey(indexNames = "OrdersByStatusDateAmount", order = Order.FIRST) public String getCustomerId() { return customerId; } public void setCustomerId(String customerId) { this.customerId = customerId; } // Second partition key attribute for the GSI. @DynamoDbSecondaryPartitionKey(indexNames = "OrdersByStatusDateAmount", order = Order.SECOND) public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } // First sort key attribute for the GSI. @DynamoDbSecondarySortKey(indexNames = "OrdersByStatusDateAmount", order = Order.FIRST) public String getOrderDate() { return orderDate; } public void setOrderDate(String orderDate) { this.orderDate = orderDate; } // Second sort key attribute for the GSI. @DynamoDbSecondarySortKey(indexNames = "OrdersByStatusDateAmount", order = Order.SECOND) public Integer getAmount() { return amount; } public void setAmount(Integer amount) { this.amount = amount; } }

Verwenden Sie für die Abfrage einen zusammengesetzten Schlüsselindex

Wenn Sie einen zusammengesetzten Schlüsselindex abfragen, verwenden Sie die addSortValue() Methoden addPartitionValue() und im Key Builder. Fügen Sie Werte in derselben Reihenfolge wie die in den Anmerkungen definierten Order Werte hinzu. Alle Partitionsschlüssel sind erforderlich. Sortierschlüssel sind optional und können von links nach rechts eingegeben werden.

Sie erstellen ein QueryConditionalObjekt, um die Bedingung für die Abfrage anzugeben. Verwenden Sie diese Option keyEqualTo für exakte Übereinstimmungen oder für eine Sortierschlüsselbedingung wie sortGreaterThan sortLessThansortBetween,, odersortBeginsWith. Die Bedingung gilt für den letzten Sortierschlüssel, den Sie angeben.

In den folgenden Beispielen wird der globale Index OrdersByStatusDateAmountabgefragt und nach und nach Sortierschlüssel hinzugefügt, um die Ergebnisse einzugrenzen.

DynamoDbIndex<OrderItem> index = orderTable.index("OrdersByStatusDateAmount"); // All PENDING orders for customer-123. SdkIterable<Page<OrderItem>> allPending = index.query(q -> q .queryConditional(QueryConditional.keyEqualTo(k -> k .addPartitionValue("customer-123") .addPartitionValue("PENDING")))); // PENDING orders on a specific date. SdkIterable<Page<OrderItem>> pendingOnDate = index.query(q -> q .queryConditional(QueryConditional.keyEqualTo(k -> k .addPartitionValue("customer-123") .addPartitionValue("PENDING") .addSortValue("2025-11-04")))); // PENDING orders on a specific date with amount greater than 100. SdkIterable<Page<OrderItem>> filtered = index.query(q -> q .queryConditional(QueryConditional.sortGreaterThan(k -> k .addPartitionValue("customer-123") .addPartitionValue("PENDING") .addSortValue("2025-11-04") .addSortValue(100))));

Weitere Informationen finden Sie unter Multi-key Unterstützung für Global Secondary Index in DynamoDB.