Phrase and proximity
Phrase, multi-phrase, span, and interval queries use indexed positions. Configure the field with positional index options before relying on these queries.
PhraseQuery
PhraseQuery matches terms in order:
var exact = new PhraseQuery("title", "quick", "brown", "fox");
Slop is the maximum number of positional gaps allowed across the phrase:
var loose = new PhraseQuery(
"title",
slop: 2,
"quick",
"fox");
Slop 0 requires adjacent positions. A positive slop allows intervening positions, but PhraseQuery still uses the supplied term order. Use an unordered SpanNearQuery or IntervalsUnorderedSource when order must not matter.
The scorer first intersects documents containing every term, choosing a rare term as the lead, then verifies positions. Matching terms contribute their scoring factors. Slop is a match condition, not an extra proximity bonus, so a tighter occurrence does not automatically outrank a looser occurrence solely because of distance.
MultiPhraseQuery
Use MultiPhraseQuery when one phrase position accepts alternatives:
var query = new MultiPhraseQuery(
field: "body",
termGroups:
[
["quick", "fast"],
["brown"],
["fox", "vixen"],
],
slop: 1);
Explicit positions represent gaps or analysis graphs:
var query = new MultiPhraseQuery(
"body",
termGroups:
[
["new"],
["york", "nyc"],
["office"],
],
positions: [0, 1, 3],
slop: 0);
Every group must contain at least one term. Terms within a group are de-duplicated. All groups target the query field.
Multi-phrase scoring currently uses the query boost as its base score, with field boosts applied where present. Do not assume it has the same BM25 score distribution as PhraseQuery.
Span leaves and alternatives
SpanTermQuery is the leaf:
var machine = new SpanTermQuery("body", "machine");
var learning = new SpanTermQuery("body", "learning");
Combine alternatives with SpanOrQuery:
var technique = new SpanOrQuery(
new SpanTermQuery("body", "learning"),
new SpanTermQuery("body", "training"));
SpanNearQuery
Compose nested spans with an explicit order rule:
var near = new SpanNearQuery(
clauses:
[
machine,
technique,
],
slop: 3,
inOrder: true);
Set inOrder: false when either order is acceptable.
SpanNotQuery
Return include spans only from documents without an excluded span:
var included = new SpanNearQuery(
[
new SpanTermQuery("body", "search"),
new SpanTermQuery("body", "engine"),
],
slop: 4);
var excluded = new SpanTermQuery("body", "deprecated");
var query = new SpanNotQuery(included, excluded);
The current implementation applies exclusion to the whole document.
Span boundaries and containment
SpanFirstQuery limits matches to the start of a field. Use
SpanContainingQuery to return enclosing spans and SpanWithinQuery to return
their contained spans.
FieldMaskingSpanQuery reports positions from one field under another field
name, while SpanMultiTermQueryWrapper expands prefix, wildcard, fuzzy, regex,
or term-range matches into position-aware spans.
Performance
Positional queries read more postings data than term conjunctions. Cost grows with common terms, repeated positions, alternatives, and slop. Prefer selective terms, keep user-generated alternatives bounded, and use the simplest query that captures the requirement.
For another containment surface and deeper positional trees, see Intervals.