Query Operations¶
db.query() is an async generator that yields paginated QueryResult[T] objects. Each page contains a list of validated model instances and an optional pagination token.
Basic query¶
from boto3.dynamodb.conditions import Key
async for page in db.query(
Order,
key_condition_expression=Key("order_id").eq("o1"),
):
for item in page.items:
print(item)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
model |
type[T] |
— | DynamoModel subclass to query |
key_condition_expression |
ConditionBase \| None |
None |
Key condition (required for most queries) |
index_name |
str \| None |
None |
Name of a GSI or LSI to query |
filter_expression |
ConditionBase \| None |
None |
Post-key filter applied after key lookup |
limit |
int \| None |
None |
Max items to evaluate per page |
exclusive_start_key |
dict \| None |
None |
Pagination token from a previous page |
consistent_read |
bool |
False |
Strongly consistent reads |
scan_index_forward |
bool |
True |
Sort ascending (True) or descending (False) |
projection_expression |
list[ProjectionAttr] \| None |
None |
Project specific fields |
return_consumed_capacity |
bool |
False |
Include consumed capacity in response |
Pagination patterns¶
Stream all items¶
query() automatically fetches subsequent pages using LastEvaluatedKey. The generator handles pagination for you:
async for page in db.query(Order, key_condition_expression=Key("order_id").eq("o1")):
for item in page.items:
process(item)
# loop exits naturally when there are no more pages
Collect all items at once¶
all_items = []
async for page in db.query(Order, key_condition_expression=Key("order_id").eq("o1")):
all_items.extend(page.items)
Single page with a continuation token¶
last_evaluated_key is None when there are no more pages:
async for page in db.query(Order, key_condition_expression=Key("order_id").eq("o1"), limit=25):
items = page.items
cursor = page.last_evaluated_key # None on the last page
break # take one page, save cursor for next request
Resume from a cursor:
async for page in db.query(
Order,
key_condition_expression=Key("order_id").eq("o1"),
limit=25,
exclusive_start_key=cursor,
):
items = page.items
break
Filtering¶
filter_expression is applied after the key lookup, meaning DynamoDB still reads and charges for all key-matched items. It does not replace the key condition.
from boto3.dynamodb.conditions import Attr, Key
async for page in db.query(
Order,
key_condition_expression=Key("order_id").eq("o1"),
filter_expression=Attr("total").gte(100),
):
print(page.items)
Sort order¶
# Descending (newest first)
async for page in db.query(
Order,
key_condition_expression=Key("order_id").eq("o1"),
scan_index_forward=False,
):
print(page.items)
Querying an index¶
from boto3.dynamodb.conditions import Key
async for page in db.query(
Order,
index_name="order_by_status",
key_condition_expression=Key("status").eq("pending"),
):
print(page.items)
See Indexes for index definition.
Projections¶
from aiodynamodb import ProjectionAttr
async for page in db.query(
Order,
key_condition_expression=Key("order_id").eq("o1"),
projection_expression=[ProjectionAttr("order_id"), ProjectionAttr("total")],
):
print(page.items)
See Projections for details.
QueryResult¶
Each page yielded by query() is a QueryResult[T]:
| Field | Type | Description |
|---|---|---|
items |
list[T] |
Validated model instances for this page |
last_evaluated_key |
dict \| None |
Pagination token; None on the last page |