Search by term proximity and order with the Query DSL intervals query
The Query DSL intervals query finds documents based on the order and proximity of matching terms.
Unlike the match_phrase query, it lets you define flexible rules about how terms relate to each other.
You can allow gaps between terms, enforce term order, and combine multiple term patterns.
This tutorial is for developers who know basic Query DSL queries and want finer control over how matching terms relate to each other.
By the end of this tutorial, you can:
- Run a basic ordered proximity search using
all_ofwithmatch - Combine
all_ofandany_ofrules for flexible matching - Use the
prefixrule to match partial words - Apply a
filterrule to exclude unwanted terms from proximity matches
The code examples use Console syntax. You can convert examples into other programming languages in the Console UI.
To follow this tutorial, you need:
- Access to an Elasticsearch project or deployment. Refer to Choosing your deployment type for deployment options.
- A way to send requests, such as Console.
- Index privileges to create, write to, read, and delete the
booksindex, such as theallindex privilege. - Familiarity with basic Query DSL queries. It also helps to know how text analysis breaks text into terms at specific positions, because intervals rules match on those positions.
Create a books index and add several sample documents:
PUT /books
POST /books/_bulk?refresh=wait_for
{"index":{"_id":"1"}}
{"title":"Elasticsearch in Action","synopsis":"A practical guide to full text search with Elasticsearch. Covers queries, filters, and performance tuning."}
{"index":{"_id":"2"}}
{"title":"Search Fundamentals","synopsis":"Learn the basics of full text search including tokenization, analyzers, and relevance scoring."}
{"index":{"_id":"3"}}
{"title":"Faster Elasticsearch","synopsis":"Tips for fast and efficient search at scale. Covers caching, faster queries, and cluster optimization."}
{"index":{"_id":"4"}}
{"title":"Machine Learning for Search","synopsis":"Apply machine learning to improve search relevance. Covers learning to rank and query classification."}
{"index":{"_id":"5"}}
{"title":"Advanced Text Processing","synopsis":"Deep dive into text analysis and search pipelines. Full coverage of custom analyzers and token filters."}
The response shows "errors": false when all five documents are indexed.
By default, text fields use the standard analyzer.
It lowercases and tokenizes the text, so each word becomes a searchable term at a specific position.
To learn more, refer to Text analysis.
Use all_of with ordered: true to find books where full text appears immediately before search, with no gaps allowed:
GET /books/_search
{
"query": {
"intervals": {
"synopsis": {
"all_of": {
"ordered": true,
"max_gaps": 0,
"intervals": [
{
"match": {
"query": "full text",
"max_gaps": 0,
"ordered": true
}
},
{
"match": {
"query": "search"
}
}
]
}
}
}
}
}
ordered: truerequires the first interval (full text) to appear before the second (search).max_gaps: 0onall_ofrequires both intervals to be adjacent, with no words betweentextandsearch.
Example response
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"_id": "1",
"_score": 0.5,
"_source": {
"title": "Elasticsearch in Action",
"synopsis": "A practical guide to full text search with Elasticsearch. Covers queries, filters, and performance tuning."
}
},
{
"_id": "2",
"_score": 0.5,
"_source": {
"title": "Search Fundamentals",
"synopsis": "Learn the basics of full text search including tokenization, analyzers, and relevance scoring."
}
}
]
}
}
Documents 1 and 2 match because both contain full text search as three contiguous, ordered terms.
The other documents don't contain the phrase full text search.
Use any_of inside all_of to match alternative terms.
This query finds books where search appears within two positions of either machine learning or text, in any order:
GET /books/_search
{
"query": {
"intervals": {
"synopsis": {
"all_of": {
"ordered": false,
"max_gaps": 2,
"intervals": [
{
"match": {
"query": "search"
}
},
{
"any_of": {
"intervals": [
{ "match": { "query": "machine learning" } },
{ "match": { "query": "text" } }
]
}
}
]
}
}
}
}
}
ordered: falseallows the intervals to appear in any order.max_gaps: 2allows up to two unmatched positions between the intervals.any_ofmatches eithermachine learningortext.
Example response
{
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"hits": [
{
"_id": "1",
"_score": 0.5,
"_source": {
"title": "Elasticsearch in Action",
"synopsis": "A practical guide to full text search with Elasticsearch. Covers queries, filters, and performance tuning."
}
},
{
"_id": "2",
"_score": 0.5,
"_source": {
"title": "Search Fundamentals",
"synopsis": "Learn the basics of full text search including tokenization, analyzers, and relevance scoring."
}
},
{
"_id": "5",
"_score": 0.25,
"_source": {
"title": "Advanced Text Processing",
"synopsis": "Deep dive into text analysis and search pipelines. Full coverage of custom analyzers and token filters."
}
},
{
"_id": "4",
"_score": 0.19999999,
"_source": {
"title": "Machine Learning for Search",
"synopsis": "Apply machine learning to improve search relevance. Covers learning to rank and query classification."
}
}
]
}
}
Documents 1 and 2 match because text appears immediately before search (zero gaps).
Document 5 matches because text and search are two positions apart (analysis and and are between them).
Document 4 matches because search appears two positions after machine learning (to and improve are between them).
Document 3 doesn't match because its synopsis contains neither text nor machine learning near search.
The scores drop as the matching terms get farther apart. Documents 1 and 2 score highest because their matching terms are adjacent, and documents 5 and 4 score lower because other terms sit between the matches. The intervals query gives shorter matches a higher score.
The prefix rule matches any term that starts with a given set of characters.
This is useful when the input contains a partial word, such as when a user has typed only the start of a word in a search box.
Find books where search is immediately followed by a term that starts with relev:
GET /books/_search
{
"query": {
"intervals": {
"synopsis": {
"all_of": {
"ordered": true,
"max_gaps": 0,
"intervals": [
{
"match": {
"query": "search"
}
},
{
"prefix": {
"prefix": "relev"
}
}
]
}
}
}
}
}
- The
prefixrule matches any indexed term that starts withrelev, such asrelevanceandrelevant.
Example response
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_id": "4",
"_score": 0.5,
"_source": {
"title": "Machine Learning for Search",
"synopsis": "Apply machine learning to improve search relevance. Covers learning to rank and query classification."
}
}
]
}
}
Document 4 matches because its synopsis contains search relevance.
If you replace the prefix rule with a match rule for relev, the query returns no results, because relev isn't a complete term in the index.
Document 2 also contains relevance, but four other terms sit between it and search, so max_gaps: 0 excludes it.
The prefix rule can expand to match many terms depending on your data.
If a prefix matches more terms than the indices.query.bool.max_clause_count search setting allows, Elasticsearch returns an error.
To avoid this error, use the index_prefixes mapping option or keep prefixes specific enough to limit expansion.
Use the filter rule to exclude unwanted terms from a proximity match.
This query finds books where search appears near text, but only when analysis doesn't appear between them:
GET /books/_search
{
"query": {
"intervals": {
"synopsis": {
"match": {
"query": "text search",
"max_gaps": 5,
"ordered": false,
"filter": {
"not_containing": {
"match": {
"query": "analysis"
}
}
}
}
}
}
}
}
- The
not_containingfilter excludes intervals whereanalysisappears betweentextandsearch.
Example response
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"_id": "1",
"_score": 0.5,
"_source": {
"title": "Elasticsearch in Action",
"synopsis": "A practical guide to full text search with Elasticsearch. Covers queries, filters, and performance tuning."
}
},
{
"_id": "2",
"_score": 0.5,
"_source": {
"title": "Search Fundamentals",
"synopsis": "Learn the basics of full text search including tokenization, analyzers, and relevance scoring."
}
}
]
}
}
Documents 1 and 2 match because both contain text near search without analysis between them.
Document 5 also contains text near search and matched in Step 3.
However, its synopsis contains text analysis and search, so analysis appears between the two terms and the filter excludes the document.
Delete the books index:
DELETE /books
In this tutorial, you learned how to:
- Search for ordered, contiguous phrases with
all_ofandmax_gaps - Match alternative terms using
any_of - Match partial words using the
prefixrule - Exclude unwanted terms from proximity matches using a
filterrule
- Refer to the full Query DSL intervals query reference for all available rules and parameters, including
fuzzy,wildcard,regexp, andrangerules. - Learn how text analysis affects how terms are stored and matched.
- Explore full-text queries for other matching options.
- Use the
match_phrasequery when you need to match a phrase, usingslopto allow gaps between terms.