Skip to main content
POST /v1/namespaces/{ns}/search runs up to three ranked branches over one filtered row set. All branches are optional; at least one is required. label and filter apply to every branch.
Response — one independent ranked list per branch, with in-server execution time:

Filters

Two shapes are accepted:
  • Single equality: {"property": "project", "value": "conare"} — served straight from posting lists.
  • Array DSL: [property, op, value] with Eq, NotEq, Gt, Gte, Lt, Lte, In (array value), composed with ["And", [f1, f2, ...]] / ["Or", [...]] up to 16 levels.
Comparison is typed: numbers compare numerically, strings lexicographically (byte order), bools as false < true. A type mismatch or absent property matches nothing — including for NotEq — never errors. Unknown operators, empty And/Or lists, and non-array In values are 400s naming the offender.

Vector branch

Scores are cosine similarity on L2-normalized vectors, and always exact — the ANN index (IVF + RaBitQ 1-bit codes) shortlists candidates, then reranks them against full-precision vectors. Options: Filtered vector search returns exactly the ANN-on-the-matching-subset results — the engine widens probing to compensate for selectivity, so filters don’t quietly cost you recall. Determinism: for a fixed index state, identical query bytes with identical knobs return byte-identical hit lists — at any thread count or concurrency. Behind the scenes, a continuous sampler replays ~1% of ANN queries against brute-force ground truth and publishes recall; the credential-free GET /recall-slo endpoint reports fleet recall health.

Keyword branch

BM25 (k1=1.2, b=0.75) over the text property. Tokenizer: lowercase, split on every non-alphanumeric character — no stemming, no stopwords (word-tokenizer parity with Turbopuffer). match controls token combination:
  • "auto" (default) — require all tokens; if that yields fewer than max(5, top_k/8) hits, retry as any-token. The response reports which mode ran ("mode": "and" / "or").
  • "all" — every token required.
  • "any" — ordinary disjunctive BM25.

Chronological branch

Ranks by any integer property, asc or desc — the cheap “most recent first” leg of a hybrid query.

Projecting properties

include_props controls what rides along with each hit: omit it for id+score only (zero extra cost), pass a name array to project just those keys, or true for the full property map. Projection means a reranker can consume hits without a second lookup roundtrip.

Turbopuffer-compatible shim

POST /v2/namespaces/{ns}/query accepts the Turbopuffer read shape — {rank_by, filters, top_k, include_attributes} — and returns {"rows": [{"id", "$dist", ...}]} with $dist as cosine distance. rank_by: ["id", "asc"] with filters: ["id", "Gt", cursor] gives cursor pagination/export. Unsupported shapes are explicit 400s naming the field — never a silently different query.