DynamoDB Query en Python (boto3)
Le paginateur query de boto3 est la raison pour laquelle cette page est courte : il masque entièrement LastEvaluatedKey. Il masque aussi un chiffre que tu voulais probablement, et c'est la partie à connaître avant de lui faire confiance. Pour savoir quand recourir à query tout court, voir Query vs. Scan.
Code
import boto3
client = boto3.client("dynamodb")
paginator = client.get_paginator("query")
items = []
for page in paginator.paginate(
TableName="Music",
KeyConditionExpression="#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)",
ExpressionAttributeNames={"#hashKey": "Artist", "#rangeKey": "SongTitle"},
ExpressionAttributeValues={":hashKeyValue": {"S": "Arturo Sandoval"}, ":rangeKeyValue": {"S": "C"}},
):
items.extend(page["Items"])
print(f"Found {len(items)} items")Le paginateur n'additionne pas ta facture
Sur un jeu d'essai de 600 morceaux, chacun d'environ 3,9 Ko et tous sous Artist = "Arturo Sandoval", la boucle produit trois pages : 271, 271 et 58 éléments, coûtant 128,5, 128,5 et 27,5 unités de lecture. Demande au même paginateur un résultat fusionné et voici ce que tu obtiens :
build_full_result() -> Items 600 Count 600 ScannedCount 600
ConsumedCapacity.CapacityUnits 128.5Count et ScannedCount ont été additionnés. ConsumedCapacity, non — c'est le chiffre de la première page, et le vrai total était 284,5. La configuration du paginateur DynamoDB de botocore est explicite sur le pourquoi : Count et ScannedCount sont déclarés comme clés de résultat, ConsumedCapacity comme clé non agrégée. Si tu journalises la capacité depuis build_full_result(), tu sous-déclares une lecture de partition complète de plus de moitié.
Les dictionnaires par page de la boucle for page in paginator.paginate(...) ci-dessus sont des réponses brutes : additionner toi-même page["ConsumedCapacity"]["CapacityUnits"] donne l'honnête 284,5.
Le Limit qui te coûte 58 allers-retours de plus
Limit est un paramètre query valide, donc paginate() l'accepte, et ce n'est pas le paramètre auquel s'attendent les utilisateurs de Python :
paginate(..., Limit=10) -> 61 pages, 10 items each
paginate(...) -> 3 pagesIl plafonne les éléments par requête, pas au total, donc le paginateur fait consciencieusement 61 appels HTTP pour récupérer les mêmes 600 éléments. Pour plafonner le total, utilise PaginationConfig={"MaxItems": 10} ; PaginationConfig["PageSize"] est le bouton qui correspond à Limit.
Mesuré le 2026-07-28 contre DynamoDB Local (amazon/dynamodb-local) avec boto3 1.43.58 sur CPython 3.14.6.
Explication
- Le client parle DynamoDB JSON dans les deux sens. Les valeurs entrent sous la forme
{"S": "Arturo Sandoval"}etYearrevient sous la forme{"N": "1994"}. L'API resource (boto3.resource("dynamodb").Table(...).query) convertit dans les deux sens et te rendDecimal('1994')— ce qui est juste pour de l'argent et surprenant la première fois qu'il refuse de s'additionner à unfloat. Key("Artist").eq(...)appartient uniquement à l'API resource. Le passer au client lève avant même que la requête ne parte :ParamValidationError: Invalid type for parameter KeyConditionExpression ... valid types: <class 'str'>. Le client veut la chaîne d'expression que cette page construit.- La condition de clé, c'est une égalité plus au plus une comparaison sur la clé de tri (
=,<,<=,>,>=,BETWEEN,begins_with). Mets tout le reste dans uneFilterExpression, que boto3 transmet telle quelle et que DynamoDB applique après la lecture.ScanIndexForward=Falseinverse l'ordre,IndexName="..."recible un index.
Le faire visuellement
Le DynamoDB Expression Builder écrit la condition de clé et la map typée ExpressionAttributeValues en Python prêt pour boto3, ce qui est justement la partie qui déraille quand tu tapes {"N": 2010} au lieu de {"N": "2010"}.
Pour pointer la même requête sur tes propres tables depuis un formulaire de condition de clé et lire les résultats dans une grille paginée, télécharge DynoTable.
Guides liés
- Query vs. Scan — pourquoi
queryest le bon choix par défaut. - Les expressions de condition de clé — tous les opérateurs légaux sur clé de partition/de tri.
- "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 que la condition de clé ne peut pas utiliser, comme contains ou une deuxième condition sur la clé de tri.