Skip to content

Indexes

DynamoDB supports two types of secondary indexes: Global Secondary Indexes (GSI) and Local Secondary Indexes (LSI). Both are defined via the indexes argument to @table().

Global Secondary Index (GSI)

A GSI lets you query on a different partition key than the table's primary key.

from aiodynamodb import DynamoModel, table
from aiodynamodb.models import GSI


order_by_status = GSI(
    name="order_by_status",
    hash_key="status",
    range_key="created_at",
)


@table(
    "orders",
    hash_key="order_id",
    range_key="created_at",
    indexes=[order_by_status],
)
class Order(DynamoModel):
    order_id: str
    created_at: str
    status: str
    total: int

GSI parameters

Parameter Type Description
name str Index name (must be unique among GSIs on this table)
hash_key str Partition key field for the index
range_key str \| None Sort key field for the index (optional)
projection str "ALL" (default), "KEYS_ONLY", or "INCLUDE"
non_key_attributes list[str] \| None Projected attributes when projection="INCLUDE"
provisioned_throughput ProvisionedThroughputTypeDef \| None Throughput for provisioned mode
on_demand_throughput OnDemandThroughputTypeDef \| None On-demand throughput configuration
warm_throughput WarmThroughputTypeDef \| None Warm throughput configuration

Local Secondary Index (LSI)

An LSI shares the table's partition key but uses a different sort key. It must be created at table creation time.

from aiodynamodb.models import LSI


order_lsi = LSI(
    name="order_by_total",
    range_key="total",
)


@table(
    "orders",
    hash_key="order_id",
    range_key="created_at",
    indexes=[order_lsi],
)
class Order(DynamoModel):
    order_id: str
    created_at: str
    total: int

LSI parameters

Parameter Type Description
name str Index name (must be unique among LSIs on this table)
range_key str Sort key field for the index
projection str "ALL" (default), "KEYS_ONLY", or "INCLUDE"
non_key_attributes list[str] \| None Projected attributes when projection="INCLUDE"

Combining GSI and LSI

from aiodynamodb.models import GSI, LSI

order_gsi = GSI(name="order_gsi", hash_key="order_id", range_key="total")
order_lsi = LSI(name="order_lsi", range_key="total")


@table(
    "orders",
    hash_key="order_id",
    range_key="created_at",
    indexes=[order_gsi, order_lsi],
)
class Order(DynamoModel):
    order_id: str
    created_at: str
    total: int

Index names must be unique within each index type (GSI names must be unique, LSI names must be unique).

Querying an index

Pass index_name to db.query():

from boto3.dynamodb.conditions import Key

# Query a GSI
async for page in db.query(
    Order,
    index_name="order_gsi",
    key_condition_expression=Key("order_id").eq("o1"),
):
    for item in page.items:
        print(item)
from boto3.dynamodb.conditions import Attr, Key

# Query an LSI with a filter
async for page in db.query(
    Order,
    index_name="order_lsi",
    key_condition_expression=Key("order_id").eq("o1"),
    filter_expression=Attr("total").gte(200),
):
    print(page.items)

See the Query guide for the full query() API.