Query parsers
|
This section documents the current Solr line (10.0; 9.10.x the maintained 9.x branch), written and verified against the Apache Solr Reference Guide. No specific patch version is pinned. Some capabilities (the Solr Operator on Kubernetes, the package-manager ecosystem, Learning To Rank model training, and expert plugin development) are linked, not documented in depth. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
A query parser turns the q parameter (and, for some parsers, other request parameters) into the
Lucene query actually executed. Which parser runs is chosen by defType — lucene (the standard
parser) unless a request handler’s config says otherwise — and any individual clause can switch
parsers inline with local params. This page covers the standard parser’s syntax, DisMax/eDisMax and
their many tuning knobs, local params and parameter dereferencing, and a tour of the specialised
parsers Solr ships for ranges over functions, joins, nested documents, vector search and more. For
the request parameters every parser shares (q, fq, fl, sort, start/rows) see
Query basics & parameters; for the function
syntax several of these parsers embed, see
Function queries.
The standard (Lucene) query parser
The standard (or Lucene) query parser reads q as the classic Lucene query-string grammar:
field:value terms, boolean operators (AND, OR, NOT, or the prefix +/-), grouping with
parentheses, phrases in double quotes, range syntax ([10 TO 20] inclusive, {10 TO 20} exclusive),
wildcards (sol?, sol*), fuzzy matching (solr~2), proximity ("solr apache"~5), and term
boosting (solr^3). It is the default parser (defType=lucene) and the fastest of the three general-
purpose parsers, but a syntax error anywhere in q fails the whole request, so it suits queries built
by your own application rather than raw end-user input. See
Standard Query
Parser.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q=name:solr AND (cat:electronics OR cat:memory) AND price:[10 TO 100]' \
--data-urlencode 'fl=id,name,price,score' \
--data-urlencode 'wt=json'
# https://solr.apache.org/guide/solr/latest/query-guide/standard-query-parser.html
Two request parameters shape how bare terms are interpreted: df overrides which field an unqualified
term (solr instead of name:solr) searches, and q.op overrides the default boolean operator
between clauses (OR unless the schema or config says otherwise).
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q=solr apache' \
--data-urlencode 'df=name' \
--data-urlencode 'q.op=AND'
DisMax and eDisMax
The standard parser rewards knowing the exact field a term lives in. DisMax and its superset
eDisMax (Extended DisMax) instead search several weighted fields at once and are forgiving of the
kind of free text a search box actually receives — a stray AND or unbalanced quote in eDisMax
degrades gracefully instead of erroring. Both are selected with defType=dismax /
defType=edismax; eDisMax is the one to reach for in new work, since it is a strict superset of
DisMax’s parameters. See
DisMax Query Parser
and
eDisMax Query Parser.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'defType=edismax' \
--data-urlencode 'q=solr memory' \
--data-urlencode 'qf=name^2 manu features' \
--data-urlencode 'pf=name^4' \
--data-urlencode 'mm=2<-25%' \
--data-urlencode 'tie=0.1' \
--data-urlencode 'wt=json'
| Parameter | Meaning |
|---|---|
|
Query fields — the fields |
|
Phrase fields — fields where the whole |
|
Like |
|
Default phrase slop applied to |
|
Slop applied to explicit phrase queries the user typed in quotes within |
|
Tie breaker for combining a term’s per-field scores (0.0 to 1.0): |
|
Boost query — one or more additional query clauses added to the score without being required to match, e.g. |
|
Boost function(s) — function query results added to the score, e.g. |
|
Minimum should match — how many of the (non-mandatory) |
eDisMax adds a boost parameter alongside bf/bq: instead of an additive score contribution, every
function listed in boost multiplies the score, which composes more predictably than another bf
term when several boosts are stacked.
Field aliasing and user fields
eDisMax lets a field alias stand in for several real fields: f.<alias>.qf=<fields> (and the
equivalent for pf) makes <alias>:value in q expand to a search across <fields>, which is handy
for exposing a friendly name like text over several concrete columns without a copy field.
uf (user fields) is the allow/deny list of field names an end user is permitted to search
explicitly inside q (title:foo) — it defaults to uf=* -query (every field except the raw
sub-query escape hatch); set it to something narrower, or to uf=-*, when q comes from untrusted
input and fielded search should be disabled entirely.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'defType=edismax' \
--data-urlencode 'q=body:solr' \
--data-urlencode 'qf=name features' \
--data-urlencode 'f.body.qf=name features includes' \
--data-urlencode 'uf=name manu cat body' \
--data-urlencode 'wt=json'
Local params and parameter dereferencing
Local params attach a small set of key-value pairs to one query clause, most often to switch that
clause to a different parser than the request’s overall defType. The syntax is
\{!key=value …} immediately followed by the clause’s value, wrapping curly braces required; a
value with no key name is taken as the type local param, so \{!dismax} is shorthand for
\{!type=dismax}. An explicit v key gives the clause’s value inline instead of appending it after
the closing brace, which is what makes local params composable inside fq, bq, and other multi-
valued parameters. See
Local Parameters in Queries.
# Two equivalent ways to run one clause through the dismax parser against a chosen field.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!dismax qf=name}solr rocks' \
--data-urlencode 'wt=json'
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!type=dismax qf=name v='"'"'solr rocks'"'"'}' \
--data-urlencode 'wt=json'
Parameter dereferencing — a local param value prefixed with $ — reads its value from another
request parameter instead of embedding it literally, which decouples query text (which may contain
spaces or braces of its own) from the surrounding param string and lets the same named parameter be
reused from several places in one request:
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!type=dismax qf=$myQf v=$qq}' \
--data-urlencode 'myQf=name manu features' \
--data-urlencode 'qq=solr memory' \
--data-urlencode 'wt=json'
Local params are also how fq filters get tagged for faceting exclusion (\{!tag=t}) and how several
of the specialised parsers below are invoked — every \{!…} form in the rest of this page is a
local params block.
Specialised parsers
Beyond the general-purpose parsers above, Solr ships a set of narrowly-scoped parsers, each invoked
via its own \{!name …} local params, for jobs the standard/DisMax parsers cannot express. See
Other Parsers for the full
list; this section covers the ones used most often.
frange and func: filtering and scoring by function
\{!frange} turns a function query into a range filter,
keeping only documents whose function value falls within l (lower bound) / u (upper bound), with
incl / incu (both default true) controlling whether each bound is inclusive. \{!func} instead
runs the function purely as the query value/score, without the surrounding function-query braces
val requires. Both are the idiomatic way to filter or sort on a computed value — distance, a
boosted combination of fields, age of a document — rather than a stored one.
# Keep only documents whose computed "popularity" function falls in [10, 100].
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q=*:*' \
--data-urlencode 'fq={!frange l=10 u=100}product(popularity,10)' \
--data-urlencode 'wt=json'
term and terms: exact-value queries from an external list
\{!term f=<field>}<value> builds a single exact-term query without running <value> through the
field’s analyzer — the counterpart to a term filter in other search engines, and the idiom for
turning one facet value straight into a filter query. \{!terms f=<field>} takes the same idea for a
list, matching any document whose field equals one of several comma-separated (or separator-
delimited) values, with a method local param (termsFilter, booleanQuery, automaton,
docValuesTermsFilter, …) to pick the underlying implementation for very large lists.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q=*:*' \
--data-urlencode 'fq={!term f=cat}electronics' \
--data-urlencode 'fq={!terms f=manu_id_s separator=,}apple,belkin,corsair' \
--data-urlencode 'wt=json'
join and block-join: relating documents without denormalizing
Solr has no native SQL-style join across collections, but two parsers cover the common cases without
denormalizing data into a single flat document. \{!join from=<field> to=<field>} matches documents
whose to field equals the from field of any document matched by the subordinate query — an
"IN (subquery)" over two independently-indexed sets of documents, optionally against another core or
collection via fromIndex, with method (index, dvWithScore, topLevelDV, or
crossCollection) choosing the join strategy for cardinality and scoring needs. See
Join Query Parser.
# Manufacturers with an id referenced by any product matching "ipod" in its title.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!join from=manu_id_s to=id}title:ipod' \
--data-urlencode 'wt=json'
Block-join is the alternative for documents that are genuinely parent/child (a product and its
variants, an invoice and its line items) indexed together as one nested block via
nested/child documents. \{!parent which=<parentFilter>}
takes a query matched against children and returns their parents; \{!child of=<parentFilter>} runs
the other direction, returning children of matched parents. Both accept filters to apply additional
fq-style filters only within the block-join evaluation, and \{!parent} accepts score
(none/avg/max/min/total) to aggregate child scores onto the parent. See
Block Join Query
Parser.
# Parent products that have a red variant in stock.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!parent which="content_type:product"}color_s:red AND inStock_b:true' \
--data-urlencode 'wt=json'
# The reverse: variants belonging to a parent in the "electronics" category.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!child of="content_type:product"}cat:electronics' \
--data-urlencode 'wt=json'
collapse: performant field collapsing
\{!collapse field=<field>} groups the result set by field, keeping one representative document per
group — the same outcome as
field collapsing/grouping, but implemented as a post-
filter that composes with faceting and is generally the faster choice for a single collapse field. It
takes min / max (a function or field deciding which group member survives) and sort (an explicit
sort for the representative).
# One document per manufacturer, keeping the highest-priced item from each.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q=*:*' \
--data-urlencode 'fq={!collapse field=manu_id_s max=price}' \
--data-urlencode 'wt=json'
knn: approximate nearest-neighbor vector search
\{!knn f=<denseVectorField> topK=<k>}[v1,v2,…] finds the topK documents whose stored dense
vector is closest to the query vector, using the field’s configured similarity function
(cosine/dot-product/Euclidean). Because it wraps a vector search rather than a term lookup, it is
typically combined with a filter (fq) or with \{!knn …} inside a bq/boost clause rather than
run alone. Full coverage, including indexing dense-vector fields, is in
Dense vector search.
curl "http://localhost:8983/solr/techproducts/select" \
--data-urlencode 'q={!knn f=embedding topK=10}[0.12,0.98,...,0.44]' \
--data-urlencode 'wt=json'
Other utility parsers: prefix, boost, switch, surround, min_hash
A handful of narrower parsers round out the set:
| Parser | Purpose |
|---|---|
|
An unanalyzed prefix match against |
|
Wraps |
|
Picks one of several |
|
The Surround query language: span/proximity operators ( |
|
Jaccard-similarity ("near duplicate") matching against a MinHash-encoded field, returning documents whose MinHash signature overlaps |
See Other Parsers for the
complete parameter reference of each, including the less common \{!field} and \{!complexphrase}
parsers.
Where to go next
-
Query basics & parameters — the
q/fq/fl/sort/paging parameters every parser shares. -
Function queries — the function syntax
frange,func,boost,bfand sort-by-function all build on. -
JSON Request API — expressing
query/filter/params(including local params) as a JSON body instead of URL-encoded parameters. -
Relevance & scoring — how DisMax/eDisMax’s boosts and
tieactually shape the final score. -
Grouping & collapse — the general grouping feature
\{!collapse}is a faster alternative to for a single field.