Skip to main content
Infino retrieves from the same table several ways. Pick the mode that matches the question; you can also compose any of them in SQL. Every search returns Arrow rows, and you can pass a projection to choose which columns come back.

Choose a search mode

You want to…UseWhy
Match exact keywords or termsFull-text (BM25)Lexical ranking over tokenized text
Find by meaning or paraphraseVector kNNSemantic similarity over embeddings
Cover both keyword and semantic intentHybridRRF fuses BM25 and vector rankings
Look up an exact id or valueexact_matchUnranked, precise
Filter, aggregate, or joinSQLCompose over the same rows
ModeRankedTunable recallText pre-filterCompose in SQL
BM25n/an/a✓ (bm25_search)
Vector kNN✓ (nprobe)✓ (pushdown)✓ (vector_search)
Hybrid✓ (RRF)n/a✓ (hybrid_search)
token_match / exact_matchn/an/an/a
SQLn/an/an/anative
Always pass a sensible top-k on production queries: it bounds both the work and the result size.

Full-text (BM25)

Ranked keyword search over an FTS-indexed column.
hits = docs.bm25_search("body", "cancel subscription", 5, mode="or")
ArgumentTypeDefaultDescription
columnstringrequiredthe FTS-indexed text column
querystringrequiredquery terms, tokenized by the index
kintrequirednumber of top results
modeor / andormatch any term (or) or require all terms (and)
projectionstring[]_id + scorecolumns to return

Unranked lookups

When you don’t need scoring, token_match (rows containing a token) and exact_match (rows whose column equals a value) return every matching row, unranked.
rows = docs.exact_match("doc_id", "1")
rows = docs.token_match("body", "billing")
exact_match and token_match run over an FTS-indexed column. Index the column you want to match, for example IndexSpec().fts("doc_id"), to look it up this way.
Semantic search over a vector-indexed column. Embed the query with the same model you used to index (see Embeddings).
hits = docs.vector_search("embedding", embed("cancel subscription"), 5)
# higher recall: probe more IVF partitions
hits = docs.vector_search("embedding", embed("..."), 5, nprobe=32)
ArgumentTypeDefaultDescription
columnstringrequiredthe vector-indexed column
queryfloat[]requiredthe query vector (same dim as the index)
kintrequirednumber of top results
nprobeintengine defaultIVF partitions to probe; higher = better recall, more work
rerank_multintengine defaultover-fetch multiplier for the exact-rerank stage
filtertext predicatenonepushdown pre-filter (below)
projectionstring[]_id + scorecolumns to return

Pushdown filter

Restrict the kNN to rows whose FTS-indexed column matches a text predicate. This is a pre-filter, where the kNN ranks only among matching rows, not a post-filter on the top-k.
hits = docs.vector_search("embedding", embed("..."), 5,
                          filter_column="body", filter_query="billing")
For scalar filtering (such as WHERE source = '...') or filtering the results of a search, query with SQL. Hybrid search runs BM25 and vector kNN and fuses their rankings with reciprocal-rank fusion (RRF), which is strong when a query has both keyword and semantic intent. It runs through query_sql via the hybrid_search table function. Pass the query text and the query vector as a comma-separated literal:
hybrid_search(table, text_column, query_text, vector_column, query_vector, k)
vec = ",".join(map(str, embed("cancel subscription")))
rows = db.query_sql(
    f"SELECT doc_id, body, score FROM "
    f"hybrid_search('docs', 'body', 'cancel subscription', 'embedding', '{vec}', 5) "
    f"ORDER BY score DESC"
)
Hybrid search needs both indexes on the table: an fts index on the text column and a vector index on the embedding column. Build the vector literal from your own embedding, and escape any user-supplied query text before putting it in SQL. See the SQL Reference for the full hybrid_search signature and how to compose it with joins and filters.

Limitations

  • Vector search is approximate (IVF). It trades exactness for speed; raise nprobe (and rerank_mult) to recover recall at some cost in work.
  • Bring your own embeddings. Embed queries with the same model and dimension you indexed with.
  • Filters in vector search are text predicates over an FTS-indexed column. For scalar filters, use SQL.
  • exact_match and token_match need an FTS-indexed column.

See also

Last modified on June 29, 2026