More retrieval patterns
Scoped filters, two-stage retrieval, CASE-routed verification, and pinned snapshots, all ordinary SQL over the same search functions.
One SQL plan returns the finished table
- One SQL statement retrieves, filters, joins, aggregates, and returns the finished table.
- A count, group by, or window function runs over the full candidate set inside the query plan.
- Hybrid retrieval hands back the rows a single retriever drops: the exact error code and the paraphrase of it, fused into one ranking.
Enforce the cohort in the query
The query defines and enforces the cohort: this tenant, this quarter, these priorities. The model receives the resulting rows.
SELECT _id, subject, score FROM hybrid_search('tickets', 'body', 'disk full on ingest', 'embedding', :q, 500) WHERE tenant_id = :tenant -- enforced AND created_at >= date_trunc('quarter', now()) AND priority IN ('p0', 'p1') ORDER BY score DESC LIMIT 20; -- → exactly this cohort, nothing outside it
Join summary-level and chunk-level retrieval
Two retrieval granularities, one statement. A table of document-summary embeddings picks the right documents; a chunk-level search picks the right passages inside them; the join ranks on both.
-- stage one: which documents are about this, by their summary embedding WITH docs AS ( SELECT _id AS doc_id, score AS doc_score FROM vector_search('doc_summaries', 'embedding', :q, 50) ) -- stage two: the best passages, but only inside those documents SELECT c._id, c.doc_id, c.text, round(0.4 * d.doc_score + 0.6 * c.score, 4) AS blended FROM vector_search('chunks', 'embedding', :q, 500) c JOIN docs d ON d.doc_id = c.doc_id -- two searches, one join ORDER BY blended DESC LIMIT 10; -- → whole-document context and passage precision, in one pass
Route only borderline scores to an LLM
A CASE expression can send only the borderline score band to an LLM for verification. The application supplies both thresholds.
SELECT _id, subject, score, CASE WHEN score >= :trust_threshold THEN 'trust' WHEN score >= :check_threshold THEN 'llm_check' ELSE 'drop' -- never reaches the context window END AS action FROM hybrid_search('tickets', 'body', :question, 'embedding', :q, 200) WHERE created_at > now() - interval '90 days' ORDER BY score DESC; -- → only rows between the two thresholds require a model check
The routing thresholds live in the query, so they are versioned, reviewed, and tuned like the rest of your SQL.
Debug the retriever before it ships
- Join
bm25_searchagainstvector_searchon_idand the rows on only one side are what a single retriever would have silently missed. - Run it per query class in CI: when the "meaning only" bucket grows, your embeddings and your vocabulary are drifting apart, and you find out from a query.
One consistent read, even while writes land
- Every query runs on one pinned snapshot, so a count and the rows behind it always come from the same version of the table, even while writes land concurrently.
- A retained snapshot lets you rerun yesterday’s query against yesterday’s data when the result changes.
Retrieval pattern questions
Why put filters and joins in the query instead of the agent?
The engine enforces tenant, time, and status constraints during retrieval, and aggregates operate over the full candidate set. The agent receives the bounded result instead of carrying access-control and counting logic in its prompt.
Where do the embeddings come from?
Infino can embed text on ingest using the model selected for the table. You can also send vectors from your own model. Keyword search and SQL run directly on text and columns.
Can a query combine document-level and chunk-level retrieval?
Yes, in one statement. Search a table of document-summary embeddings to pick candidate documents, join the result to a chunk-level search of the same corpus, and rank on both scores. Each search function returns a relation, so the join is ordinary SQL.
Can a query decide which rows need an LLM check?
Yes. A CASE expression over retrieval scores labels each row as trust, check, or drop. The application supplies the thresholds, and the routing logic is versioned with the rest of the SQL.
What happens if writes land while a query is running?
Every query runs on one pinned snapshot. The rows it reads and the count it computes come from the same version of the table, even while writes land concurrently.