Skip to main content
You declare indexes once, at table creation, with an IndexSpec. Two index types, chained fluently.
IndexDeclare withPowers
Full-text (BM25)fts(column)keyword search, hybrid, the pushdown filter
Vector (IVF)vector(column, dim, n_cent, metric)semantic kNN, hybrid
Declare both on a table to enable hybrid search. Scalar columns need no index; filter them with SQL.
spec = (
    infino.IndexSpec()
    .fts("body")                               # BM25 over `body`
    .vector("embedding", 384, 64, "cosine")    # vector index over `embedding`
)

Full-text index: fts(column)

Builds a BM25 inverted index over a text column, powering bm25_search, token_match, and the hybrid / pushdown-filter paths. Call fts once per text column you want to search.

Vector index: vector(column, dim, n_cent, metric)

Builds an IVF (inverted-file) vector index for kNN.
ParameterTypeDescription
columnstringthe fixed-width vector column to index
dimintembedding dimension; must match your model’s output and the values you append
n_centintnumber of IVF partitions (centroids)
metriccosine / l2sq / negdot (Metric::Cosine …)distance metric (see Embeddings)
Tuning n_cent. It sets how many partitions the vectors are bucketed into. More partitions mean finer buckets and faster search at scale, at some recall cost per partition probed. Raise nprobe at query time to recover that recall. The engine clamps n_cent sensibly for small datasets, so a few dozen is a fine starting point; raise it as the table grows into the hundreds of thousands of rows and beyond.
You can index multiple text columns (call fts per column) and multiple vector columns. Scalar columns need no index declaration. Filter them with SQL (query_sql) or as a pushdown pre-filter on vector search (see Search).

See also

Last modified on June 29, 2026