<!-- GENERATED FILE β€” do not edit; regenerate with `./do v2-docs` (from core/). -->

v2 Query Operator Reference (Beta)

The complete operator vocabulary of the v2 (Query2) JSON query language β€” where conditions, orderBy, select, query types, and config. v2 is in beta; see the v2 Introduction for context and the v1 reference for the production API.

A query is one JSON object. The same from/where is evidence for a plain query, a prediction, a recommendation, or relation analysis β€” see the Inference guide.

Where conditions

where is an object of field β†’ condition. A bare value means equality:

{ "from": "products", "where": { "category": "books" } }

Equality and tokens

OperatorMeaningExample
(value) / $isEquality (text fields tokenize){ "category": "books" }
$exactRaw, non-featurized exact value{ "color": { "$exact": "red" } }
$hasToken / membership. A single token, or an array (matches ANY){ "tags": { "$has": "sale" } } Β· { "tags": { "$has": ["sale","new"] } }
$has: { … }Same-member conjunction on a member-link Set/Array (a set of foreign keys): matches a row that has ONE member whose linked row satisfies all the sub-conditions β€” not "some member is A and some other is B". $exists is an interchangeable spelling, and the same object form works on $refs reverse links{ "items": { "$has": { "a": "fire", "b": "fighter" } } } β€” a basket with one item that is both

On a member-link's linked Text attribute (items.name where products.name is Text), $has matches by token β€” { "items.name": { "$has": "banana" } } finds baskets with a product named "pirkka banana" or "chiquita banana" (the shared token, not the whole phrase). select ["items.name"] still returns the whole names.

Text columns (type: "Text", with an analyzer) support three matchers:

OperatorMeaningExample
$matchTokenize the input and match rows containing all tokens (AND){ "description": { "$match": "wireless mouse" } }
$searchFull-text search β€” a Lucene-subset query language: bare terms (AND), "quoted phrases", OR, NOT / -term, and ( … ) groups{ "description": { "$search": "(wireless OR bluetooth) mouse -refurbished" } }
$hasA single analyzed token{ "description": { "$has": "wireless" } }

$match is the simple "all words present" matcher; $search is the expressive one when you need phrases, OR, or negation.

Ranges and prefixes

OperatorMeaningExample
$gt $gte $lt $lteComparison β€” numeric columns compare numerically; String columns compare lexicographically (the date-as-string cutoff idiom){ "n": { "$gt": 20 } } Β· { "month": { "$lte": "2024-07" } }
$startsWithPrefix match on a String column{ "sku": { "$startsWith": "FI-" } }
$modModulo (numeric) β€” [divisor, remainder] or {divisor, remainder}{ "n": { "$mod": [3, 1] } }
$numericAdaptive neighbourhood (binned), not an exact match{ "n": { "$numeric": 101 } }

$numeric matches a neighbourhood: Aito bins the column adaptively, so $numeric: 101 draws on nearby values instead of overfitting the single exact row β€” the mechanism that makes a number useful as evidence. A $gt on a non-numeric column fails loud.

Date & timestamp components

Date and Timestamp columns are queried by derived component. A Timestamp (a UTC instant) additionally exposes the sub-day components, computed from the instant at query time β€” raw units, so you bucket them how you like:

OperatorMeaning
$year $month $dayCalendar components
$weekday / $dayOfWeekDay of week (ISO 1=Mon..7=Sun / name)
$dayOfYear1–366
$hour $minuteTime of day (Timestamp only)
$quarter $weekOfMonthQuarter 1–4 / week-of-month 1–5 (Timestamp only)
$matchMatch the date as text
{ "from": "orders", "where": { "created": { "$weekday": 6 } } }
{ "from": "events", "where": { "ts": { "$hour": 9, "$quarter": 3 } } }

Nullability

OperatorMeaningExample
$exists / $definedHas a value (true) or is null/absent (false){ "color": { "$exists": true } }
null equality{ "field": null } is an alias for { "field": { "$exists": false } }{ "color": null }

Logical combinators

OperatorMeaningExample
$and $or $notCombine nested where-objects{ "$or": [ { "color": "red" }, { "size": "M" } ] }
field-scoped $or / $inIs-any-of: a value list on one field{ "id": { "$or": ["a", "b", "c"] } } Β· { "id": { "$in": [1, 2] } }
field-scoped $notNegated equality on one field{ "status": { "$not": "done" } }
field-scoped $andCombine field-scoped conditions (e.g. exclude a basket){ "id": { "$and": [ { "$not": "a" }, { "$not": "b" } ] } }
$onObserve a condition only where another holds ([prop, on]){ "$on": [ { "color": "red" }, { "size": "M" } ] }
$groupA correlated theme that votes by mutual corroboration (compression), not OR β€” for predictions where a set of tokens should count as one decorrelated signal{ "$group": [ { "tag": "a" }, { "tag": "b" } ] }

Combinators work on both collection tables and legacy table worlds.

Reference a stored row β€” $examine

Condition a prediction on the attributes of a linked entity you only hold a reference to: Aito looks the row up and expands the named attributes into evidence (equivalent to writing link.attr: <value> by hand). It works even for an entity with no rows of its own β€” the prediction generalizes through the attributes, not the unseen id. Requires basedOn; collections only.

OperatorMeaningExample
$examineOn a link field: reference a stored row by at (its target key β€” bare or { "id": … }) and condition on its basedOn attributes{ "account": { "$examine": { "at": "acme", "basedOn": ["industry"] } } }

Vector similarity

$nearest ranks rows by similarity to a query vector on a Vector column. It is a single where proposition that produces its own ordered, scored result set β€” the nearest rows first, each carrying its score as $similarity.

{ "from": "products",
  "where": { "$nearest": {
    "near":  { "embedding": [0.12, -0.03, 0.88] },
    "where": { "category": "shoes" },
    "having":{ "$similarity": { "$gte": 0.8 } },
    "limit": 10 } },
  "select": ["id", "name", "$similarity"] }
KeyMeaning
near{ <vector-column>: [query vector] } β€” the column to score and the query vector. Its length must equal the column's dimensions; a mismatch (or a non-finite component) is rejected.
whereOptional candidate filter β€” any where-object. Scoring runs only over the survivors, so limit is the top-k among matches, never a globally-nearest row the filter should have excluded.
havingOptional score floor on $similarity: { "$similarity": { "$gte": t } } (inclusive) or { "$gt": t } (exclusive).
thresholdSugar for having: { "$similarity": { "$gte": t } }.
limitTop-k cap β€” return at most this many nearest rows.

$similarity is the per-row score, exposed as a selectable field; rows come back ordered by it descending (an implicit orderBy $similarity). Its meaning follows the column's similarity setting: for cosine it is the cosine similarity in [-1, 1] (vectors are unit-normalised on ingest, so scoring is an exact dot product); for dotProduct it is the raw inner product. Rows whose vector is null are skipped, not scored.

$nearest is exact nearest-neighbour (a full scan of the candidates), not an approximate index β€” results are exact and reproducible, with ties broken by row order.

Vectors as prediction evidence β€” $cluster / $semantic

Beyond search, a Vector column can drive prediction. On a predict query, two operators turn similarity into evidence.

$cluster quantizes a vector into a categorical code (k-means), so it becomes an ordinary discrete feature the model reasons over:

{ "from": "tickets", "predict": "category",
  "where": { "embedding": { "$cluster": { "vector": [0.1, 0.9, 0.2], "k": 64 } } } }
KeyMeaning
vectorThe query vector to code. Or text β€” embedded via the column's embedder (see Vector search).
kCodebook size (number of clusters).
asOptional name for the derived code column (default <column>_cluster).

The vector is coded against the column's codebook and the condition rewrites to a plain equality on the code column β€” so the vector becomes ordinary categorical evidence. A single full-vector cluster recovers most of the exact-kNN lift.

$semantic blends the k nearest neighbours' predict-field values into the prediction β€” semantic-kNN late fusion, the continuous-similarity form:

{ "from": "tickets", "predict": "category",
  "where": { "embedding": { "$semantic": { "near": [0.1, 0.9, 0.2], "k": 20, "weight": 0.5 } } } }
KeyMeaning
nearThe query vector, or text (embedded via the column's embedder).
kNeighbours to vote (default 10).
weightBlend weight in [0, 1]: 0 = the token/naive-Bayes baseline only, 1 = pure kNN vote, 0.5 (default) = an even blend.

The k nearest rows vote their predict field, similarity-weighted, and the vote is fused with the ordinary prediction. $knn/$nn do the same with feature similarity instead of vector similarity (see below).

Text introspection

On a text field you can also read its analysis: $size (row count), $tokenCount (distinct tokens), $distinctCount (distinct values). Select them with a field.$op token β€” e.g. "select": ["note.$tokenCount"]. The value is a property of the whole column, so every returned row carries the same number (a per-row constant); pair it with "limit": 1 to read it once.

A dotted path follows a forward link β€” from a row to the row it points at (order.buyer resolves the order's user, and buyer.name reads that user's name). $refs follows a link the other way: from a row to the rows that point at it. $refs.<table>.<fk> is the set of <table> rows whose link <fk> targets this row β€” e.g. on a user, $refs.orders.buyer is that user's orders (the orders whose buyer is this user). Append an attribute to project it over that set: $refs.orders.buyer.product is the products of those orders.

It is an ordinary field β€” you query, select, and predict over it with the same operators a stored member-set uses. The query is identical whether the relation is stored on the row or discovered via the back-link; nothing is copied onto the referring row.

Link resolution is lazy, and a link's cross-table enrichment is optional. A link's target is resolved at query time, not validated when the schema is created β€” so you may declare a link before its target table exists, and a link whose target is missing, renamed, or deleted does not raise an error. Its linked columns and its cross-table prediction signal are simply absent for that query, and the result degrades gracefully to what the row itself carries. (This is the long-standing rep1 behaviour, preserved by design.) Cross-table priors additionally require the target to be a rep2 collection; a link to a rep1 (type: "table") target resolves as absent the same way. So if a predict seems to ignore a linked signal, confirm the target table exists and is a rep2 collection.

Where β€” over the referring set:

ConditionMeaningExample
$existsHas β‰₯1 referring row{ "$refs.orders.buyer": { "$exists": true } } β€” users with an order
$has on a projected attributeA referring row whose attribute matches{ "$refs.orders.buyer.product": { "$has": "gold" } } β€” users with a "gold" order
$exists/$has with an object (same-member filter)Restrict the referring rows before the existence check β€” ALL conditions hold on the SAME referring row; a condition col may itself be a forward link (item.tier β€” one more hop){ "$refs.orders.buyer": { "$exists": { "item.tier": "premium" } } }
<link>.$refs.… (forward-then-reverse)Resolve this row's forward link first, then its inverse links β€” two hops{ "sender.$refs.edges.subject": { "$exists": true } } β€” emails whose sender has an edge

Row-level $and of two $refs conditions intersects, e.g. a user with both a gold order and a web order:

{ "from": "users",
  "where": { "$and": [
    { "$refs.orders.buyer.product": { "$has": "gold" } },
    { "$refs.orders.buyer.channel": { "$has": "web" } } ] } }

Select β€” project the attribute over each row's referring set (an array per row):

{ "from": "users", "select": ["name", { "products": "$refs.orders.buyer.product" }] }
// β†’ { "name": "Alice", "products": ["gold", "silver"] }, …

Predict β€” use a $refs condition as where evidence to predict a field from the back-linked rows, without materialising anything onto the row:

{ "from": "users",
  "where": { "$refs.orders.buyer.product": { "$has": "gold" } },
  "predict": "segment" }

A same-member conjunction β€” one referring row that matches several attributes at once (an order that is gold and on web) β€” is the object form: { "$refs.orders.buyer": { "$exists": { "product": "gold", "channel": "web" } } }. Contrast the row-level $and above, which matches any gold order and any (possibly different) web order.

Beta: the basedOn keyword does not yet accept a $refs path; the where-evidence form above covers predicting from inverse links.

Ordering β€” orderBy

FormMeaning
"price" / { "field": "price", "desc": true }Sort by a field
{ "$asc": "price" } / { "$desc": "price" }Direction shorthands for the same (also work on "$p"/"$f"/"$lift", e.g. { "$asc": "$f" })
"$p"Rank by prediction probability
"$f"Rank get candidates by their frequency (count under the where)
"$lift"Rank get candidates by lift (how much the where raises each value's probability)
{ "$p": { "$context": <where> } }Rank candidates by P(condition in the from/context table)
{ "$similarity": { <textField>: <text> } }Rank rows by the BM25 relevance of the field against the text, emitted as a probability lift exp(thetaΒ·bm25) β€” 1.0 (neutral) for a no-match β€” so it is directly multipliable with a $p (a raw 0 would annihilate a $multiply). theta defaults to 0.33 (the tf-idf lift scale); override with "theta": <n>. On a get over a link, the field may be a linked text column. $sameness is an accepted alias.
{ "$bm25": { <textField>: <text> } }Same, but the raw BM25 score (0.0 for a no-match) rather than the lift. Ranking of a single $similarity/$bm25 orderBy is identical (the lift is monotone); the difference is the emitted value's scale and its composition behaviour.
{ "$vectorSimilarity": { <vectorField>: [<vector>] } }Rank rows by vector cosine against the query vector, emitted as a probability lift exp(thetaΒ·cos) β€” 1.0 (neutral) for an orthogonal or vector-less row β€” so it composes multiplicatively with a $p/$similarity (the probabilistic hybrid-search blend, ["$p", "$similarity", "$vectorSimilarity"]). theta defaults to 1.0. Only usable inside $multiply; the query vector must be supplied explicitly (text-embedding a near value is a follow-up).
{ "$vectorCosine": { <vectorField>: [<vector>] } }Same, but the raw cosine (0.0 for a vector-less row) rather than the lift. A single-term ranking is identical (the lift is monotone).
{ "$vectorIdf": { <vectorField>: [<vector>] } }Self-calibrating vector lift (1/p)^ΞΈ, where p is the row's cosine tail probability over the examined rows (the fraction at least as similar to the query) β€” a vector IDF, βˆ’log p. This is BM25's (1/p)^0.33 form applied to a similarity condition: the model-specific cosine scale is absorbed into p, so one ΞΈ (default 0.87) transfers across embedding models with no per-model tuning. Preferred over $vectorSimilarity for composing with $p/$similarity.
{ "$multiply": [ … ] }Rank by the per-row product of parts: the string "$similarity" (lift) or "$bm25" (raw) referencing the query's $match where-term, a { "$similarity": {field: text} } / { "$bm25": {field: text} } object, a { "$vectorSimilarity": {field: [vec]} } / { "$vectorCosine": {field: [vec]} } vector term, or a { "$p": { "$context": … } } part. ["$p", "$similarity", "$vectorSimilarity"] composes probability Γ— text-similarity Γ— vector-similarity.
{ "from": "impressions", "get": "product",
  "orderBy": { "$p": { "$context": { "purchase": true } } },
  "select": ["$value", "$p"] }

Projection β€” select

Plain column names, computed value-expression columns (arithmetic over fields β€” see Derived fields β†’ let), plus the predictive columns below. On a get over a link, the link TARGET's columns are selectable too β€” each candidate resolves them on its target row (get: "product" + select: ["name", "price"] returns each candidate product's own attributes):

ColumnMeaning
$valueThe candidate value
feature / fieldv1's names for the ranked candidate and the predicted field, accepted as select aliases on any ranked-value query (_predict / _recommend / _match), so a v1 body works unchanged over v2. feature is $value under its old name; field is the request's own target. Asked of a query that ranks nothing they fail loud, like any unknown column
$pIts predicted probability
$scoreThe value used by orderBy β€” for a predict/recommend ranking, equal to $p
$fThe candidate's frequency β€” count of rows where the predicted field equals this value, under the where
$liftThe candidate's lift β€” how much the where evidence raises its probability over its base rate
$whyThe explanation factor tree (see the Inference guide). The parameterized form { "$why": { "highlight": { "posPreTag": "<b>", "posPostTag": "</b>" } } } additionally marks the matched evidence tokens in the explanation with your tags
$highlightOn a search query: the matched field value with the query's tokens marked with tags β€” the search-hit form of $why's highlight. The parametric form { "$highlight": { "posPreTag": "<mark>", "posPostTag": "</mark>", "negPreTag": …, "negPostTag": …, "encoder": … } } sets the markup (SQL: startSel / stopSel on search(..))
$matchesOn a search query: the matched tokens and their positions in the field value
{ alias: "source" }Rename a column in the output β€” { "demandScore": "$score" }
{ alias: <value-expression> }A computed column β€” { "margin": { "$subtract": ["revenue", "cost"] } }. Any let value-expression (arithmetic over fields/constants; see Derived fields); evaluated the same way as let, so select and let share one vocabulary
{ alias: { "$p": { "$context": <where> } } }A named per-candidate contextual probability column
{ "$sum" | "$mean": { "$context": <field> } }Per-candidate aggregate of a context-table field over the candidate's where-filtered rows (bare, or wrapped in an alias) β€” e.g. a per-product conversion rate { "$mean": { "$context": "purchase" } }
$count / $sum:f / $avg:f / $min:f / $max:fRelational aggregate over the whole where selection β€” collapses all matching rows to ONE hit (SQL count(*), sum(f), …), ignoring offset/limit. Skips null cells; null over zero rows. Distinct from the per-candidate { "$sum": { "$context": … } } above; mixing an aggregate with a plain field is rejected (SQL would need a GROUP BY)
field.$predictionsA per-row predicted column: for each selected SOURCE row, the ranked distribution [ { "value": …, "p": … }, … ] over the field β€” computed from the row's OTHER fields, with the predicted field held out. Collections only; default top-N. (No leave-one-out; use _evaluate for an unbiased estimate)
field.$predictionThe argmax of the above β€” the single most likely value
{ alias: { "$predict": "field", "limit": n, "basedOn": [ … ] } }Object form of a predicted column β€” cap the distribution (limit) and/or generalize a predicted link's candidates by their attributes (basedOn)

Selecting an unsupported computed column fails loud (a 4xx), never a silent empty value. Aggregates and $f require candidates whose rows live in the from table itself β€” a dotted-path get (e.g. get: "context.week") is a known limitation (returns zeros; tracked on the gap matrix).

Derived fields β€” let

let defines inline computed fields from value-expressions, usable in select and orderBy. It is the join-free way to compute derived columns β€” margin, ratios, and the like β€” without a CTE or self-join:

{ "from": "sales",
  "let": { "margin":    { "$subtract": ["revenue", "cost"] },
           "marginPct": { "$divide": [ { "$subtract": ["revenue", "cost"] }, "revenue" ] } },
  "select": ["id", "margin", "marginPct"], "orderBy": "margin" }

A value-expression is one of:

FormMeaning
"revenue" / { "$field": "revenue" }A field's value
123 / { "$const": 2.0 }A constant
{ "$sum": [a, b, …] }Sum of the parts
{ "$subtract": [a, b] }a βˆ’ b
{ "$multiply": [a, b, …] }Product of the parts
{ "$divide": [a, b] }a / b
{ "$pow": [base, exp] }base raised to exp (element-wise)
{ "$normalize": expr }Scale so the column's values sum to 1.0 across the queried rows (a cross-row transform β€” e.g. a revenue share)
{ "$length": "field" }The per-row element count of an array/set field β€” a stored member-link set's size, or a $refs projection's count (graph degree / neighbour count). E.g. { "degree": { "$length": "$refs.edges.subject.relation" } }. Distinct from $count (count(*), which collapses the whole selection to one hit); non-array fields are rejected loudly
{ "$coalesce": [a, b, …] }The first defined part per row (SQL coalesce) β€” e.g. a NULL-safe fallback { "n": { "$coalesce": [ "note", { "$const": "n/a" } ] } }
{ "$cast": { "expr": e, "as": "int|bigint|decimal|text|boolean" } }Coerce e to a type (SQL CAST(e AS type)); an uncoercible value is undefined for that row
{ "$upper": e } / { "$lower": e }Per-row string case fold (SQL upper/lower)
{ "$charLength": e }Per-row string character length (SQL length(str)); distinct from $length (array element count)
{ "$dateTrunc": { "unit": u, "expr": e } }Truncate a timestamp DOWN to unit β€” year, quarter, month, week (ISO, Monday), day, hour, minute, second (SQL date_trunc(u, ts)). Calendar-correct in UTC; the result is a timestamp, so every instant in the bucket shares one value
{ "$concat": [a, b, …] }Per-row string concatenation (SQL concat / ||); an undefined part is treated as ''

Parts nest arbitrarily. A missing or non-numeric part, or division by zero, makes that row's value undefined.

Beta: let fields are usable in select, orderBy, and β€” for equality and membership β€” in where: where: { "margin": 6 } keeps the rows whose computed margin is 6, and where: { "margin": { "$in": [3, 6] } } keeps those whose margin is 3 or 6 (a same-field $or means the same). The field still projects. The condition is evaluated per row against the current selection and AND-composes with normal column filters (where: { "margin": 6, "revenue": 10 }). Still in progress (rejected with a clear error, never silently ignored): a range/operator on a let field, a let field mixed with other conditions under $or or inside $not, and using one as prediction evidence (e.g. basedOn: { "$numeric": "margin" }). For those, filter or predict on the source column(s) instead.

from β€” collections, views, and inline relations (Beta)

from names what a query reads. Besides a plain collection it accepts a view (a derived relation saved in the schema) or an inline relation expression (an ad-hoc join or union for a single query). All are queried, filtered, projected, and predicted exactly like a collection β€” a view is just the saved, materialised form of the same relation operators.

from formExampleReads
collection"orders"one collection
view"search_index"a saved view β€” union-merge or link-join
inline link-join{ "from": "orders", "join": { "table": "products", "on": { "$=": ["product", "id"] } } }a base foreign-key column exposed as a navigable link for this query; joined columns navigate via dotted paths (product.name), no content copied
inline union{ "union": ["appLogs", "backendLogs"] }several collections stacked into one relation (heterogeneous schemas unify column-by-column; lazy, no copy)
projected union{ "union": [ { "from": "customers", "select": { "id": "id", "content": { "$text": ["name", "notes"] } } }, … ] }each source mapped into one common schema β€” "col" renames a column, { "$const": v } a literal, { "$multiply": [...] } an arithmetic column (same vocabulary as let), and { "$text": [...] } concatenates Text fields into one analyzer-backed content column so a single $match/$search spans every source

Views are created and refreshed in the schema β€” see Schema Design β†’ Views for the full treatment (both kinds, worked examples, _refresh semantics), and Relationships, Links & Joins for how link-joins behave in a query. A view is a materialised snapshot β€” rebuild it with POST /api/v2/schema/{view}/_refresh after its sources change; an inline $text union is tokenised per query, so for a hot cross-collection search prefer a persisted union view (built once).

Query types (top level)

FieldMeaning
predict: "field"Rank a field's values by probability given where
recommend: "linkField" + goal: {…}Rank link candidates by P(goal)
relate: ["field", …]Return statistical relations (lift, info-gain), not rows
search: { "field": …, "text": … }Sugar: text match + rank by relevance
get: "field"Open a field's distinct values as candidates
basedOn: ["field", …]Project linked-table fields in as cross-table evidence
predict: "field.$feature"Non-exclusive (multi-label) predict of a member/array field: each member value is scored independently by P(field has value | where) β€” for tags, baskets, categories. The prediction target determines the mode: predict X is exclusive (candidates are distinct whole values), predict X.$feature is per-member. The v1-style exclusiveness flag is deprecated β€” if given, it must agree with the target or the request is rejected

Endpoints: /api/v2/_query is the unified entry; /_predict, /_search, /_recommend, /_relate are aliases that take the same body; /_batch runs a JSON array of queries. Also on v2, engine-dispatched (collections run natively; rep1 tables reuse the v1 pipeline):

EndpointMeaning
/_evaluateTrain/test-split quality measurement β€” see the Evaluation guide. Supports test conditions, { "$index": n } row selection, sampling selectors ($sample β€” incl. the {n, of, seed} form β€” and $hash with $mod, in test and testSource.where), testSource {from, where, limit}, $get bindings, operator conditions (e.g. a $lte month cutoff), and per-query config (inference profile + train-fitted calibration)
/_estimateEstimate of a numeric field given the where. Default: knn (v1's AdjustedKNN), so a model-less request matches the v1 engine on identical data. model: "regression" (pure transformation-pipeline regression) is the other v1 estimator; both knn and regression require plain-equality where conditions. model: "mean" is the posterior-mean (probability-weighted mean over the predicted candidates, weightedAverage why) and accepts the full where operator vocabulary
/_aggregate$sum / $mean (+ variance stats) / $min / $max / $f over the where-matching rows β€” array form (["price.$mean"], keys = the spec strings) or aliased object form ({ "conversion": "purchase.$mean" })
/_matchCandidate values of the match field ranked by calibrated probability given the where evidence, generalizing to evidence never seen verbatim (lowered to predict: <field>). Honours select / $why.

Config

FieldMeaning
config.aiInference profile preset β€” group (v2) (Group re-expression only, the default), high (And + Group), v1/and (legacy And-only), or fast/flat (plain naive Bayes); unknown names fail loud. (v1 and v2 name the V1/V2 engine defaults; And+Group is the opt-in high profile β€” it adds cost without improving accuracy on the corpora.) Also accepts an object form that additionally sets scoring options for this query β€” see below.
config.calibrateTemperature-calibrate probabilities once per DB state

Per-query scoring options β€” the config.ai object form

config.ai accepts either a preset name or an object. The object form selects the same preset (preset) and, in addition, overrides individual scoring options for that one request:

{ "from": "invoices", "predict": "Processor",
  "where": { "Description": "monthly cloud hosting" },
  "config": { "ai": { "preset": "v2", "nameBoost": false, "mediationT": 2.0 } } }

Options are resolved in layers β€” built-in defaults, then the deployment's ops settings, then this query β€” so an object naming one option changes exactly that option and leaves the rest at their defaults. Nothing is global: two concurrent requests can score with different options without affecting each other. Unknown keys, unknown values and out-of-range numbers are rejected with a 400 naming the option (never silently ignored). A query with no config.ai is scored exactly as before.

The three cost guards (mediationMaxCandidates, nameBoostMaxCandidates, stage4MaxClasses) bound work that grows quadratically with the candidate count; the memory guard (stage4ClassIndexMaxRows) bounds a transient per-state index, and hitRelAccuracy bounds how much of the relation-discovery pool is upgraded from sampled to exact statistics. All four behave the same way: a query may LOWER one β€” making itself cheaper β€” but a request to raise it above the deployment's configured ceiling is rejected with a 400 rather than silently clamped.

OptionTypeMeaning
presetstringThe inference profile β€” the same names as the string form.
designf | legacyScoring stack. f (default) is the redesigned stack; legacy restores the pre-redesign stack and inerts mediation, nameBoost and stage4.
mediationbooleanCompose a link-target prediction through a near-deterministic sibling link (e.g. predict acceptor through processor).
mediationTopMassnumber (0,1]Determinism gate for the sibling edge.
mediationMinSupportintegerMinimum mediator support for the composition to fire.
mediationTnumber >0Temperature flattening the sibling distribution.
mediationGammanumber [0,1)Prior mix-in, so no candidate is floored at 0.
mediationSiblingBasedOnbooleanEnrich the mediator stage with the linked table's attributes.
mediationDirectMixnumber [0,1]Mix the direct expert into the mediated probability.
mediationMaxCandidatesintegerCost guard β€” skip mediation above this candidate count.
nameBoostbooleanX→X name-identity boost — evidence text that embeds a candidate's own name.
nameBoostThetanumber >=0Boost strength.
nameBoostMaxCandidatesintegerCost guard for the boost.
stage4booleanPer-query redundancy weights (count each nat of evidence once).
stage4MaxClassesintegerCost guard for stage 4.
stage4ClassIndexMaxRowsintegerMemory guard — row ceiling for stage 4's row→class index (1 byte/row); above it counting falls back to a per-class scan. Results are identical either way.
memobooleanPer-state scoring memos. Result-identical either way; for A/B verification.
hitRelMaxNintegerGlobal cap on kept (candidate, known) relations.
hitRelPerCandintegerPer-candidate relation floor (0 = the global-cap-only legacy path).
hitRelAccuracynumber [0,1]How much of the relation-discovery pool is upgraded from sampled to exact statistics. 1 (default) upgrades all; lower is cheaper on large tables and may reorder marginal relations.
hitRelPoolFactornumber >= 0Size of the relation-discovery candidate pool, as 8 + maxN * factor. 2 (default) leaves the upgrade room to re-rank into the kept set; lower discovers from a smaller pool and does fewer exact upgrades.
neffTemperbooleanThe n_eff temper (finite-sample overconfidence shrinkage).
neffTemperModecount | harmonic | coverage | auton_eff estimator.
neffTemperKappanumber >0Temper kappa (ignored in auto).
neffTemperBoostOnlybooleanShrink boosts only, leaving suppressions intact.
neffRegularityFloorprecision | full | offField-regularity floor mode.

The same object form is accepted by /_evaluate (evaluate.config.ai), so an A/B of two scoring configurations is two measured runs, not a restart.

Feature-based nearest rows β€” $knn / $nn

Rank rows by feature similarity to an exemplar (text fields score by BM25). This is a where operator (the feature analog of the vector $nearest / $semantic above), not a config setting:

{ "from": "msgs", "where": { "$knn": { "near": { "text": "sim card" } } }, "limit": 5 }
{ "from": "msgs", "where": { "$nn": { "near": { "text": "sim card" }, "threshold": 0.5 } } }

$nn keeps only rows scoring above threshold (default 0.0). The v1 array form { "$nn": [ { "text": "…" } ] } is accepted with a single exemplar. $similarity is selectable on the results.

On a predict query, $knn/$nn become feature-kNN classification β€” the feature analog of $semantic: the k feature-nearest neighbours vote the predict field, blended with the ordinary prediction.

{ "from": "tickets", "predict": "agent",
  "where": { "$knn": { "near": { "text": "password reset" }, "k": 2, "weight": 0.5 } } }

k (neighbours to vote, default 10) and weight (blend in [0, 1], default 0.5) apply only in this predict context; as a plain search operator $knn/$nn page by the query's limit.

Population restriction β€” nested from

from accepts a restriction object instead of a table name:

{ "from": { "from": "invoices", "where": { "customer_id": "CUST-0000" }, "limit": 50000 },
  "where": { "gl_code": "1600" },
  "predict": "approver" }

Rows failing the inner where are masked out of the examined table β€” the population the query sees. This is different from adding the filter to the outer where: where is evidence (it conditions the prediction and contributes lift), while the nested from restricts the row population, so base rates, support counts and candidates all compute over the subset (the multi-tenancy idiom). The optional inner limit caps the restricted population to its first N rows. One restriction level; a restriction matching no rows, deeper nesting, and unsupported combinations (relate, bare search, $nearest/$knn, config.calibrate) all fail loud.

Itemset mining β€” relate: {"$patterns": …}

The market-basket primitive: which sets of a field's values co-occur more than chance. Candidates are the fields' MEMBERS β€” array/set elements, analyzed text tokens, or scalar values β€” mined greedily into variable-size itemsets (pairs seed, grow while the MDL gain holds, up to 6 items, support β‰₯ 2), then each itemset is scored against the where condition:

{ "from": { "from": "invoices", "where": { "customer_id": "CUST-0000" } },
  "where": { "gl_code": "1600" },
  "relate": { "$patterns": ["vendor", "category", "amount_band"] } }

Each hit carries related (the $and itemset), condition, lift, info, f (the itemset's support count) and n. Without a where, itemsets rank by their own support. The {"$related": {"relate": [...], "k": n, "to": {…}}} wrapper bounds the candidate set (k, default 32) and adds a narrowing target. Nested from composes (the multi-tenancy shape above): support counts and n are computed over the restricted population.

Not yet supported

  • Nested from with plain relate β€” typed 501 (bit-universe alignment); relate $patterns DOES compose with nested from.
  • basedOn $patterns (conjunction mining as predict evidence) β€” fails loud; planned.
  • Arithmetic score composition beyond $multiply β€” v1's $divide, $subtract, $pow, $normalize and friends are not ported; only $multiply composes ranking values on v2 (let covers derived fields).

All of these fail loud rather than degrade β€” a 4xx/501 with the reason, never a silently wrong 200.