Query DynamoDB en Go (AWS SDK v2)
Query lit une partition, éventuellement restreinte par la clé de tri (Query vs Scan explique quand c'est le bon choix, et les expressions de condition de clé listent chaque opérateur autorisé). Ce que l'AWS SDK for Go v2 ajoute, c'est QueryPaginator, qui transforme la boucle sur LastEvaluatedKey en boucle for — et t'enlève au passage, discrètement, toute occasion de t'arrêter.
Code
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))
}Explication
Limit ne borne pas ce que le paginateur lit. C'est celui qui coûte de l'argent. En posant Limit: aws.Int32(5) sur l'entrée ci-dessus et en l'exécutant sur une partition de 30 éléments d'environ 60 Ko chacun :
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 unitsLes trente éléments sont revenus. Limit est une taille de page, et le travail du paginateur est de continuer à demander jusqu'à épuisement des pages : les deux s'annulent exactement. AWS le définit comme "the maximum number of items to evaluate (not necessarily the number of matching items)" (récupéré le 2026-07-28). Si tu veux les cinq premiers éléments, fais toi-même un break après la première page.
Les petites pages coûtent légèrement plus cher, pas moins. La même partition lue sans Limit pagine en deux pages pour 220,0 unités ; à Limit: 5 il a fallu sept appels pour 222,0. Chaque page arrondit son propre total d'octets à la borne des 4 Ko supérieure : plus de pages signifie donc plus d'arrondis, plus six allers-retours de latence en plus. Baisser Limit pour « lire moins » ne t'apporte ni l'un ni l'autre.
La boucle fait toujours un appel de plus qu'il n'y a de données. La page 7 ci-dessus n'a renvoyé aucun élément. DynamoDB rend un LastEvaluatedKey dès que Limit a été atteint, qu'il reste quelque chose ou non, et HasMorePages() le croit. Un paginateur avec Limit termine donc sur une requête gâchée, et tout effet de bord par page (barre de progression, vidage de lot, ligne de log) se déclenche une fois sur une page vide. Protège-toi avec len(page.Items).
HasMorePages() vaut true avant la première requête. Il est initialisé à true pour que la boucle for s'exécute au moins une fois : c'est une condition de boucle, pas un contrôle « y a-t-il des données ». L'appeler pour décider s'il vaut la peine d'interroger répond toujours oui.
Les erreurs remontent page par page, et une lecture partielle est un état réel. NextPage renvoie la même erreur smithy enveloppée que n'importe quel autre appel : déballe-la avec errors.As contre *types.ProvisionedThroughputExceededException et compagnie plutôt que de comparer des chaînes. Le log.Fatalf de l'extrait jette les pages déjà collectées ; dans un service, tu veux généralement conserver items et signaler jusqu'où tu es allé.
ScanIndexForward est le seul moyen de lire une partition à l'envers. Pose ScanIndexForward: aws.Bool(false) pour un ordre décroissant de clé de tri. Il n'y a pas de « trier par » pour autre chose : l'ordre vient de la clé de tri, et s'il t'en faut un autre, il te faut un autre index. IndexName: aws.String("...") déplace la requête entière sur cet index.
Deux packages raccourcissent tout ça. github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression construit la condition de clé et les deux maps de placeholders à partir de expression.Key("Artist").Equal(expression.Value("Arturo Sandoval")), ce qui supprime les paires #hashKey/:hashKeyValue écrites à la main et, avec elles, le risque de mot réservé. attributevalue.UnmarshalListOfMaps(page.Items, &songs) transforme directement une page en []Song.
Le faire visuellement
Les deux maps de placeholders sont la partie qu'il vaut mieux générer que taper. Le DynamoDB Expression Builder gratuit assemble la condition de clé avec les ExpressionAttributeNames et ExpressionAttributeValues correspondants et émet le littéral Go, si bien que les noms et les valeurs ne peuvent pas diverger.
Pour lancer des requêtes sur tes propres tables — formulaire de condition de clé, grille qui pagine au défilement, copie de la requête en Go — télécharge DynoTable.
Exemples liés
- Query DynamoDB en Java — la même requête avec l'AWS SDK for Java 2.x.
- Scan DynamoDB en Go — quand tu ne peux pas cibler une partition par clé.
- Pagination —
LastEvaluatedKey,ExclusiveStartKey, et pourquoiLimitn'est pas une taille de page. - "Query condition missed key schema element" — la condition de clé nomme le mauvais attribut ou saute la clé de partition.
- "Query key condition not supported" — un opérateur inutilisable dans une condition de clé, comme contains ou une seconde condition de clé de tri.
Références
- 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
Mesuré le 2026-07-28 sur go1.26.5 avec aws-sdk-go-v2/service/dynamodb v1.62.1, sur DynamoDB Local (amazon/dynamodb-local) sur le port 9000, sur une partition de 30 éléments d'environ 60 Ko chacun. Les comptes par page et les mesures de capacité sont la sortie capturée. DynamoDB Local applique les règles d'arrondi documentées ; considère les unités absolues comme une démonstration de la forme et mesure le service avant de dimensionner.