Utiliser des indices secondaires - AWS SDK for Java 2.x

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Utiliser des indices secondaires

Les index secondaires améliorent l'accès aux données en définissant des clés alternatives que vous pouvez utiliser dans les opérations de requête et de numérisation. Les indices secondaires globaux (GSI) possèdent une clé de partition et une clé de tri qui peuvent être différentes de celles de la table de base. En revanche, les indices secondaires locaux (LSI) utilisent la clé de partition de l'index principal.

Annoter une classe de données avec des annotations d'index secondaires

Les attributs qui participent aux index secondaires nécessitent l'@DynamoDbSecondarySortKeyannotation @DynamoDbSecondaryPartitionKey ou.

La classe suivante montre les annotations pour deux indices. Le GSI nommé SubjectLastPostedDateIndexutilise l'Subjectattribut pour la clé de partition et LastPostedDateTime pour la clé de tri. Le LSI nommé ForumLastPostedDateIndexutilise le ForumName comme clé de partition et LastPostedDateTime comme clé de tri.

Notez que l'Subjectattribut joue un double rôle. Il s'agit de la clé de tri de la clé primaire et de la clé de partition du GSI nommé SubjectLastPostedDateIndex.

classe MessageThread

La MessageThread classe peut être utilisée comme classe de données pour l'exemple de table de threads figurant dans le manuel 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 + '}'; } }

Création de l'index

À partir de la version 2.20.86 du SDK pour Java, la createTable() méthode génère automatiquement des index secondaires à partir des annotations de classes de données. Par défaut, tous les attributs de la table de base sont copiés dans un index et les valeurs de débit allouées sont de 20 unités de capacité de lecture et 20 unités de capacité d'écriture.

Toutefois, si vous utilisez une version du SDK antérieure à la version 2.20.86, vous devez créer l'index en même temps que le tableau, comme indiqué dans l'exemple suivant. Cet exemple crée les deux index de la Thread table. Le paramètre builder possède des méthodes pour configurer les deux types d'index, comme indiqué après les lignes de commentaire 1 et 2. Vous utilisez la indexName() méthode du générateur d'index pour associer les noms d'index spécifiés dans les annotations de classe de données au type d'index souhaité.

Ce code configure tous les attributs de table pour qu'ils apparaissent dans les deux index après les lignes de commentaires 3 et 4. De plus amples informations sur les projections d'attributs sont disponibles dans le manuel du développeur 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)) ) );

Requête à l'aide d'un index

L'exemple suivant interroge l'index secondaire local ForumLastPostedDateIndex.

Après la ligne de commentaire 2, vous créez un QueryConditionalobjet obligatoire lors de l'appel de la méthode DynamoDbIndex.query ().

Vous obtenez une référence à l'index que vous souhaitez interroger après la ligne de commentaire 3 en transmettant le nom de l'index. Après la ligne de commentaire 4, vous appelez la query() méthode sur l'index qui transmet l'QueryConditionalobjet.

Vous configurez également la requête pour renvoyer trois valeurs d'attribut, comme indiqué après la ligne de commentaire 5. Si elle n'attributesToProject()est pas appelée, la requête renvoie toutes les valeurs d'attribut. Notez que les noms d'attributs spécifiés commencent par des lettres minuscules. Ces noms d'attributs correspondent à ceux utilisés dans la table, pas nécessairement aux noms d'attributs de la classe de données.

Après la ligne de commentaire 6, parcourez les résultats, enregistrez chaque élément renvoyé par la requête et stockez-le également dans la liste pour le renvoyer à l'appelant.

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

Les éléments suivants existent dans la base de données avant l'exécution de la requête.

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}

Les instructions de journalisation des lignes 1 et 6 génèrent la sortie de console suivante.

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}

La requête a renvoyé des éléments avec une forumName valeur de Forum02 et une lastPostedDateTime valeur supérieure ou égale à 2023.03.31. Les résultats affichent message des valeurs avec une chaîne vide, bien que les message attributs contiennent des valeurs dans l'index. Cela est dû au fait que l'attribut message n'a pas été projeté après la ligne de commentaire 5.