Query DynamoDB in Go (AWS SDK v2)
Query legge una partizione, opzionalmente ristretta dalla chiave di ordinamento (Query vs Scan spiega quando è la scelta giusta, e le key condition expression elencano ogni operatore ammesso). Quello che AWS SDK for Go v2 aggiunge è QueryPaginator, che trasforma il loop su LastEvaluatedKey in un ciclo for e, così facendo, ti toglie in silenzio la possibilità di fermarti.
Codice
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)
func main() {
ctx := context.TODO()
cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))
if err != nil {
log.Fatalf("load config: %v", err)
}
client := dynamodb.NewFromConfig(cfg)
paginator := dynamodb.NewQueryPaginator(client, &dynamodb.QueryInput{
TableName: aws.String("Music"),
KeyConditionExpression: aws.String(
"#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)"),
ExpressionAttributeNames: map[string]string{
"#hashKey": "Artist",
"#rangeKey": "SongTitle",
},
ExpressionAttributeValues: map[string]types.AttributeValue{
":hashKeyValue": &types.AttributeValueMemberS{Value: "Arturo Sandoval"},
":rangeKeyValue": &types.AttributeValueMemberS{Value: "C"},
},
})
var items []map[string]types.AttributeValue
for paginator.HasMorePages() {
page, err := paginator.NextPage(ctx)
if err != nil {
log.Fatalf("query: %v", err)
}
items = append(items, page.Items...)
}
fmt.Printf("Found %d items\n", len(items))
}Spiegazione
Limit non limita quello che il paginatore legge. È questo che costa soldi. Impostando Limit: aws.Int32(5) sull'input qui sopra ed eseguendolo su una partizione di 30 Item da ~60 KB ciascuno si ottiene:
page 1: Count=5 CU=37.0 page 5: Count=5 CU=37.0
page 2: Count=5 CU=37.0 page 6: Count=5 CU=37.0
page 3: Count=5 CU=37.0 page 7: Count=0 CU=0.0
page 4: Count=5 CU=37.0 total: 30 items, 222.0 unitsSono tornati tutti e trenta gli Item. Limit è una dimensione di pagina, e il compito del paginatore è continuare a chiedere finché le pagine non finiscono, quindi i due si annullano esattamente. AWS lo definisce "the maximum number of items to evaluate (not necessarily the number of matching items)" (consultato il 2026-07-28). Se vuoi i primi cinque Item, esci dal ciclo con break dopo la prima pagina.
Le pagine piccole costano leggermente di più, non di meno. La stessa partizione letta senza Limit pagina in due pagine per 220,0 unità; con Limit: 5 sono servite sette chiamate per 222,0. Ogni pagina arrotonda il proprio totale di byte al successivo confine di 4 KB, quindi più pagine significa più arrotondamento, più sei round trip di latenza in più. Abbassare Limit per "leggere di meno" non ti dà né l'uno né l'altro.
Il loop fa sempre una chiamata in più rispetto ai dati disponibili. La pagina 7 qui sopra ha restituito zero Item. DynamoDB restituisce un LastEvaluatedKey ogni volta che Limit è stato raggiunto, che segua qualcosa o no, e HasMorePages() gli crede. Quindi un paginatore con Limit finisce su una richiesta sprecata, e qualsiasi effetto collaterale per pagina (una barra di avanzamento, un flush di batch, una riga di log) scatta una volta su una pagina vuota. Metti una guardia su len(page.Items).
HasMorePages() è true prima della prima richiesta. È inizializzato a true perché il ciclo for parta, il che significa che è una condizione di ciclo, non un controllo "ci sono dati". Chiamarlo per decidere se valga la pena interrogare risponde sempre di sì.
Gli errori emergono per pagina, e una lettura parziale è uno stato reale. NextPage restituisce lo stesso errore smithy avvolto di qualsiasi altra chiamata, quindi spacchettalo con errors.As contro *types.ProvisionedThroughputExceededException e simili anziché confrontare stringhe. Il log.Fatalf dello snippet butta via le pagine già raccolte; in un servizio di solito vuoi conservare items e riportare fin dove sei arrivato.
ScanIndexForward è l'unico modo di leggere una partizione all'indietro. Imposta ScanIndexForward: aws.Bool(false) per l'ordine decrescente della chiave di ordinamento. Non esiste un "sort by" per nient'altro: l'ordine viene dalla chiave di ordinamento, e se ti serve un altro ordine ti serve un altro indice. IndexName: aws.String("...") sposta l'intera query su quell'indice.
Due package accorciano tutto questo. github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression costruisce la condizione di chiave ed entrambe le mappe di segnaposto a partire da expression.Key("Artist").Equal(expression.Value("Arturo Sandoval")), il che elimina le coppie #hashKey/:hashKeyValue scritte a mano e con esse il rischio di parole riservate. attributevalue.UnmarshalListOfMaps(page.Items, &songs) trasforma una pagina direttamente in []Song.
Fallo visivamente
Le due mappe di segnaposto sono la parte che vale la pena generare anziché digitare. Il Generatore di espressioni DynamoDB gratuito assembla la condizione di chiave con gli ExpressionAttributeNames e gli ExpressionAttributeValues corrispondenti ed emette il letterale Go, così nomi e valori non possono divergere.
Per eseguire query sulle tue tabelle — form per la condizione di chiave, una griglia che pagina mentre scorri, e copiare la richiesta come codice Go — scarica DynoTable.
Esempi correlati
- DynamoDB Query in Java — la stessa query con AWS SDK for Java 2.x.
- DynamoDB Scan in Go — quando non puoi entrare in una partizione tramite chiave.
- Paginazione —
LastEvaluatedKey,ExclusiveStartKeye perchéLimitnon è una dimensione di pagina. - "Query condition missed key schema element" — la condizione di chiave nomina l'attributo sbagliato o salta la chiave di partizione.
- "Query key condition not supported" — un operatore che la condizione di chiave non può usare, come contains o una seconda condizione sulla chiave di ordinamento.
Riferimenti
- Query — Amazon DynamoDB API Reference
- Use Query with an AWS SDK or CLI — Amazon DynamoDB Developer Guide
- dynamodb package — AWS SDK for Go v2 (pkg.go.dev)
- expression package — AWS SDK for Go v2 (pkg.go.dev)
- Querying tables — Amazon DynamoDB Developer Guide
Misurato il 2026-07-28 su go1.26.5 con aws-sdk-go-v2/service/dynamodb v1.62.1, contro DynamoDB Local (amazon/dynamodb-local) sulla porta 9000, su una partizione di 30 Item da ~60 KB ciascuno. I conteggi per pagina e le letture di capacità sono output catturato. DynamoDB Local applica le regole di arrotondamento documentate; tratta le unità assolute come una dimostrazione della forma e misura il servizio prima di dimensionare.