Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Usa indici secondari
La chiave primaria di una tabella definisce l'indice primario, che determina il modo in cui DynamoDB archivia e recupera gli elementi per impostazione predefinita.
Gli indici secondari forniscono chiavi alternative da utilizzare nelle operazioni di interrogazione e scansione. Gli indici secondari globali (GSI) dispongono di una chiave di partizione e di una chiave di ordinamento opzionale che possono differire da quelle della tabella di base. Al contrario, gli indici secondari locali (LSI) condividono la chiave di partizione dell'indice primario ma definiscono una chiave di ordinamento diversa.
Definisci le chiavi per gli indici secondari globali e locali
Gli attributi che partecipano agli indici secondari richiedono l'@DynamoDbSecondarySortKeyannotazione @DynamoDbSecondaryPartitionKey o.
La classe seguente mostra le annotazioni per due indici. Il nome GSI SubjectLastPostedDateIndexutilizza l'Subjectattributo per la chiave di partizione e il LastPostedDateTime per la chiave di ordinamento. L'LSI denominato ForumLastPostedDateIndexutilizza la ForumName come chiave di partizione e LastPostedDateTime come chiave di ordinamento.
Si noti che l'Subjectattributo ha un duplice ruolo. È la chiave di ordinamento della chiave primaria e la chiave di partizione del GSI denominato. SubjectLastPostedDateIndex
Classe MessageThread
La MessageThread classe è adatta all'uso come classe di dati per la tabella Thread di esempio nella 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 + '}'; } }
Crea l'indice
A partire dalla versione 2.20.86 dell'SDK for Java, il createTable() metodo genera automaticamente indici secondari dalle annotazioni delle classi di dati. Per impostazione predefinita, tutti gli attributi della tabella di base vengono copiati in un indice e i valori di throughput assegnati sono 20 unità di capacità di lettura e 20 unità di capacità di scrittura.
Tuttavia, se utilizzate una versione SDK precedente alla 2.20.86, dovete creare l'indice insieme alla tabella, come mostrato nell'esempio seguente. Questo esempio crea i due indici per la tabella. Thread Il parametro builderindexName() metodo del generatore di indici per associare i nomi degli indici specificati nelle annotazioni delle classi di dati al tipo di indice desiderato.
Questo codice configura tutti gli attributi della tabella in modo che finiscano in entrambi gli indici dopo le righe di commento 3 e 4. Ulteriori informazioni sulle proiezioni degli attributi sono disponibili nella 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)) ) );
Esegui una query utilizzando un indice
L’esempio seguente esegue una query sull’indice globale secondario ForumLastPostedDateIndex.
Dopo la riga di commento 2, create un QueryConditional
Si ottiene un riferimento all'indice che si desidera interrogare dopo la riga di commento 3 inserendo il nome dell'indice. Dopo la riga di commento 4, si chiama il query() metodo sull'indice che passa l'QueryConditionaloggetto.
È inoltre possibile configurare la query per restituire tre valori di attributo, come mostrato dopo la riga di commento 5. Se non attributesToProject() viene chiamata, la query restituisce tutti i valori degli attributi. Notate che i nomi degli attributi specificati iniziano con lettere minuscole. Questi nomi di attributi corrispondono a quelli utilizzati nella tabella, non necessariamente ai nomi degli attributi della classe di dati.
Dopo la riga di commento 6, scorri i risultati e registra ogni elemento restituito dalla query, inoltre memorizzalo nell'elenco per restituirlo al chiamante.
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; }
I seguenti elementi sono presenti nel database prima dell'esecuzione della query.
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}
Le istruzioni di registrazione alle righe 1 e 6 generano il seguente output della console.
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 query ha restituito elementi con un forumName valore di Forum02 e un lastPostedDateTime valore maggiore o uguale a 2023.03.31. I risultati mostrano message valori con una stringa vuota sebbene message gli attributi abbiano valori nell'indice. Questo perché l'attributo message non è stato proiettato dal codice dopo la riga di commento 5.
Usa chiavi composite per gli indici secondari globali (GSI)
L'SDK for Java 2.x DynamoDB Enhanced Client supporta chiavi composite per indici secondari globali. È possibile definire fino a quattro attributi chiave di partizione e quattro attributi chiave di ordinamento per un singolo GSI. Ciò elimina la necessità di concatenare più attributi in un'unica chiave di stringa sul lato client.
Utilizzate il order parametro nelle @DynamoDbSecondarySortKey annotazioni @DynamoDbSecondaryPartitionKey and per specificare la posizione di ogni attributo nella chiave composita. Il order parametro accetta valori dall'OrderFIRST:SECOND,, e. THIRD FOURTH
Annota la classe di dati con annotazioni chiave composite
L'esempio seguente modella una tabella degli ordini. La tabella di base utilizza orderId come chiave di partizione. Un GSI denominato OrdersByStatusDateAmountutilizza una chiave di partizione composita di customerId and e status una chiave di ordinamento composita di and. orderDate amount Questo design consente di interrogare gli ordini di un cliente filtrandoli per stato, data e soglia di importo.
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; } }
Esegui una query utilizzando un indice di chiave composito
Quando esegui una query su un indice di chiave composito, usa i addSortValue() metodi addPartitionValue() and sul generatore di chiaviOrder valori definiti nelle annotazioni. Tutte le chiavi di partizione sono obbligatorie. Le chiavi di ordinamento sono opzionali e possono essere fornite da sinistra a destra.
Si crea un QueryConditionalkeyEqualTo per corrispondenze esatte o per una condizione chiave di ordinamento come sortGreaterThansortLessThan,sortBetween, osortBeginsWith. La condizione si applica all'ultima chiave di ordinamento fornita.
Gli esempi seguenti interrogano il OrdersByStatusDateAmountGSI, aggiungendo progressivamente chiavi di ordinamento per restringere i risultati.
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))));
Per ulteriori informazioni, consulta Multi-key il supporto per l'indice secondario globale in DynamoDB