Skip to content

Formula scoring

Formula queries reshape a candidate score with Qdrant score-builder expressions. Use them after a retrieval stage when business signals such as freshness, popularity, distance, or a payload tier should influence ranking.

$score represents the upstream score. DEFAULTS makes missing payload values predictable instead of leaving their behavior implicit.

QQLBlend relevance and citation countTry in playground
WITH
candidates AS (QUERY 'distributed systems' USING dense LIMIT 100)
QUERY FORMULA $score * 0.8 + LOG(citation_count + 1.0) * 0.2 DEFAULTS (score = 0.0, citation_count = 0)
FROM papers
PREFETCH (candidates)
LIMIT 10;

Decay functions take a payload field followed by named (TARGET =, SCALE =, MIDPOINT =, DECAY =) or positional arguments. scale and midpoint/decay are numeric constants. TARGET can be a numeric constant or an ISO 8601 datetime string (e.g. TARGET = "2026-01-01T00:00:00Z"). When TARGET is a datetime string, the payload field automatically infers datetime_key.

FunctionChoose it when
EXP_DECAYThe effect should drop quickly near the target and then taper
GAUSS_DECAYValues near the target should receive the smoothest peak
LIN_DECAYA simple, linear reduction is easiest to reason about
QQLFreshness and popularity signalsTry in playground
QUERY FORMULA $score + EXP_DECAY(age_days, TARGET = 0.0, SCALE = 30.0, MIDPOINT = 0.5) + GAUSS_DECAY(popularity, TARGET = 100.0, SCALE = 25.0) DEFAULTS (score = 0.0, age_days = 365, popularity = 0)
FROM articles
LIMIT 10;

Function names are case-insensitive. $score (or score) holds the upstream candidate score when no DEFAULTS entry overrides it.

FunctionSignature
ABS, SQRT, LOG, LN, EXP, ACOSHNAME(expr)
POWPOW(base, exponent)
MAX / MINMAX(expr, expr, …) — largest/smallest of n ≥ 1 operands
GEO_DISTANCEGEO_DISTANCE(lat, lon, field) or GEO_DISTANCE({lat: ..., lon: ...}, field)
MATCH / MATCH_ANYMATCH(field, value) or MATCH_ANY(field, list)
EXP_DECAY, GAUSS_DECAY, LIN_DECAYNAME(field, TARGET = n, SCALE = n, ...) or positional
datetimeDATETIME('2026-01-01') — literal timestamp (canonical uppercase; lowercase still parses)
datetime_keyDATETIME_KEY('published_at') — payload timestamp field

MAX / MIN fold any number of operands (at least one), and ACOSH maps scores into a strictly positive range — together they give formula ranking hard bounds without CASE boilerplate:

QQLClamp a boosted score and shape with ACOSHTry in playground
QUERY FORMULA MAX(MIN($score * 2.0, 10.0), 0.0) + ACOSH(popularity + 1.0)
DEFAULTS (score = 0.0, popularity = 0)
FROM papers
LIMIT 10;

Formula precedence, highest to lowest, is unary -, multiplication/division, then addition/subtraction; operators are left-associative. A division may carry an explicit by-zero default with [DEFAULT = number]:

QQLDivision with a by-zero defaultTry in playground
WITH
candidates AS (QUERY 'distributed systems' USING dense LIMIT 10)
QUERY FORMULA $score / (views + 1.0) [DEFAULT = 0.0] DEFAULTS (score = 0.0, views = 0)
FROM docs
PREFETCH (candidates)
LIMIT 10;

Use CASE WHEN for a discrete condition. Keep the fallback explicit so a missing or non-matching value remains easy to audit.

QQLBoost a premium tierTry in playground
QUERY FORMULA CASE WHEN tier MATCH ANY ('premium') THEN $score * 1.5 ELSE $score END DEFAULTS (score = 0.0)
FROM docs
LIMIT 10;

Keep formula inputs indexed and measurable before adding them to a production ranking path.