Elasticsearch QueryString Query Syntax Notes
I recently started storing logs in Elasticsearch, but doing so requires a convenient UI for querying. For me, Kibana's features are too complex, and using Postman for queries is cumbersome. I eventually discovered a tool called Elasticvue, which I chose because it supports various browser extensions and desktop application versions.
The query interface for Elasticvue is primarily based on the query_string syntax, which is an extended version of the Lucene query syntax in Elasticsearch. For users familiar with SQL, query_string is easier to pick up than other DSL syntaxes, so I have compiled some commonly used syntax for quick reference.
You can check the Elasticvue official website for various browser extensions or installation files/links for the desktop application.
Tested version: Elasticsearch 9.1.4
Basic Syntax
Basic API Structure
{
"query": {
"query_string": {
"query": "your query string here", // Required parameter: query string (use "*" to search all documents)
"default_field": "content", // Optional parameter: default search field; if not specified, defaults to "*", searching all fields
"default_operator": "OR" // Optional parameter: default operator, defaults to OR
// Other optional parameters
}
},
"size": 10, // Optional parameter: number of results to return, defaults to 10
"from": 0, // Optional parameter: starting position, defaults to 0
"sort": [] // Optional parameter: result sorting
}When no field is specified, QueryString searches across all searchable fields.
Query Syntax
1. Basic Search
Simple keyword search:
appleMultiple terms (defaults to OR connection):
apple bananaSearch Behavior for Different Field Types
Elasticsearch uses different analysis strategies for different field types (official documentation):
- text field: Uses the standard analyzer, which tokenizes and converts to lowercase.
- keyword field: Uses the keyword analyzer, keeping the complete string unchanged.
- Numeric/Date/Boolean fields: Do not use an analyzer; they index the raw value.
- query_string: Selects the corresponding strategy based on the target field type to process the query string.
| Field Type | Query String | Behavior Description |
|---|---|---|
| text | apple banana | Equivalent to apple OR banana, matches if any term is found |
| keyword | "apple" "banana" | Must use double quotes to explicitly search for multiple complete strings, or use apple OR banana |
| keyword | apple banana | No results, as it is treated as a single complete string match |
| Numeric/Date/Boolean | "123" "456" | Multi-value search must explicitly specify values with double quotes, or use 123 OR 456 |
| Numeric/Date/Boolean | 123 456 | No results, as query_string does not automatically split multiple complete values |
JSON Multi-term Query Example (using escaped double quotes):
{
"query": {
"query_string": {
"query": "\"apple\" \"banana\""
}
}
}Exact phrase search (using double quotes):
"red apple"2. Boolean Operators
AND operator (both terms must exist):
apple AND bananaOR operator (at least one term must exist):
apple OR bananaNOT operator (excludes documents containing the term):
apple NOT bananaPlus sign (must include this term):
+apple bananaMinus sign (must exclude this term):
apple -bananaWARNING
English operators must be in all caps.
3. Field-Specific Queries
Search in a specific field:
title:appleSearch across multiple fields:
title:apple AND content:bananaMulti-value query (OR condition):
user_id:(1234 OR 5678)Field existence query:
_exists_:email // Query documents where the email field exists (not null)
NOT _exists_:phone // Query documents where the phone field does not exist (is null)Field specification priority: Explicit field in query string > fields parameter > default_field parameter.
4. Range Queries and Comparison Operators
Range Queries:
price:[10 TO 20] // Closed interval, includes 10 and 20
price:{10 TO 20} // Open interval, excludes 10 and 20
price:[10 TO *] // Greater than or equal to 10
price:[* TO 20] // Less than or equal to 20Comparison Operators:
price:>10 // Greater than 10
price:>=10 // Greater than or equal to 10
price:<20 // Less than 20
price:<=20 // Less than or equal to 20These two writing styles are functionally similar, and you can choose based on the context. However, testing shows that range query syntax has better compatibility across various parameter combinations. Here are test examples:
Limitations on using comparison operators:
Comparison operators (>, >=, <, <=) cause errors when used with the fields array parameter, but work correctly when using default_field or specifying the field directly in the query string.
✅ Working syntax:
// Method 1: No field specified
{
"query": {
"query_string": {
"query": ">=10"
}
}
}
// Method 2: Specify field in query string
{
"query": {
"query_string": {
"query": "price:>=10"
}
}
}
// Method 3: Use default_field parameter
{
"query": {
"query_string": {
"query": ">=10",
"default_field": "price"
}
}
}❌ Syntax that causes errors:
// Using the fields array causes the query to fail
{
"query": {
"query_string": {
"query": ">=10",
"fields": ["price"]
}
}
}✅ Solution: Use range query syntax instead
Range query syntax ([x TO y]) is compatible with the fields parameter and works correctly:
{
"query": {
"query_string": {
"query": "[10 TO *]",
"fields": ["price"]
}
}
}5. Wildcard Search
Wildcard search:
te?t // Question mark represents one character
test* // Asterisk represents zero or more characters6. Date and Time Queries
Basic Date Range Queries
Use range syntax for date queries:
timestamp:[2023-01-01 TO 2023-01-31]You can also use relative time for queries:
timestamp:>now-1d // Query data from the past 24 hoursCommon Relative Time Expressions:
now-1h: One hour agonow-1d: One day agonow-1w: One week agonow/d: Start of today (00:00:00)now/w: Start of this weeknow/M: Start of this month
Date and Time Formats
The Elasticsearch date type defaults to millisecond precision; if nanosecond precision is needed, use the date_nanos type.
Supported Formats:
- Standard format:
yyyy-MM-ddTHH:mm:ss.SSSZ(e.g.,2023-01-15T08:30:00.000Z) - Simplified format:
yyyy-MM-dd(e.g.,2023-01-15) - Default timezone is UTC.
Format Behavior Differences:
Different date precision formats have different behaviors during queries. Key differences:
// Querying by "year" matches the first second of that year
{
"query": {
"query_string": {
"query": "timestamp:2023" // Equivalent to ="2023-01-01T00:00:00Z"
}
}
}
// Querying by "month" matches the first second of that month
{
"query": {
"query_string": {
"query": "timestamp:2023-02" // Equivalent to ="2023-02-01T00:00:00Z"
}
}
}
// When precision reaches "day", behavior changes
// This queries the entire range of that date
{
"query": {
"query_string": {
"query": "timestamp:2023-03-01" // Queries >="2023-03-01T00:00:00Z" <"2023-03-02T00:00:00Z"
}
}
}
// When precision reaches "hour", it queries the entire range of that hour
{
"query": {
"query_string": {
"query": "timestamp:2023-03-01T08" // Queries >="2023-03-01T08:00:00Z" <"2023-03-01T09:00:00Z"
}
}
}
// When precision reaches "minute", double quotes are required (due to the colon)
{
"query": {
"query_string": {
"query": "timestamp:\"2023-03-01T08:00\"" // Queries >="2023-03-01T08:00:00Z" <"2023-03-01T08:01:00Z"
}
}
}Usage Notes
1. Standard format requires double quotes
Because the standard format contains a colon :, it is treated as a special character in QueryString and must be wrapped in double quotes:
❌ Incorrect syntax (causes parsing error):
{
"query": {
"query_string": {
"query": "timestamp:2023-01-15T08:30:00Z"
}
}
}✅ Correct syntax:
// Method 1: Wrap in double quotes
{
"query": {
"query_string": {
"query": "timestamp:\"2023-01-15T08:30:00Z\""
}
}
}
// Method 2: Use simplified format (no colon)
{
"query": {
"query_string": {
"query": "timestamp:2023-01-15"
}
}
}2. Date queries do not support comparison operators
When using comparison operators to query dates, the query will fail or produce an error:
// This query actually searches for the date in "all fields"
// instead of performing a comparison on the timestamp field
{
"query": {
"query_string": {
"query": "timestamp:>=\"2023-01-15T08:30:00Z\""
}
}
}
// If you use default_field or fields, it will directly cause a parsing error
{
"query": {
"query_string": {
"query": ">=\"2023-01-15T08:30:00Z\"",
"fields": ["timestamp"] // ❌ Will throw an error
}
}
}
{
"query": {
"query_string": {
"query": ">=\"2023-01-15T08:30:00Z\"",
"default_field": "timestamp" // ❌ Will throw an error
}
}
}✅ Correct approach: Use range query syntax
{
"query": {
"query_string": {
"query": "timestamp:[2023-01-15T08:30:00Z TO *]"
}
}
}3. Impact of custom formats
When a date type field has a specified format (other than the default strict_date_optional_time||epoch_millis), the query format must exactly match the specified format:
// Assuming the field is defined as follows
"timestamp": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss'Z'"
}Using the wrong format leads to different results:
// Specifying the field directly in the query: No results (silent failure)
{
"query": {
"query_string": {
"query": "timestamp:[2023-01-15T08:30 TO *]" // Format mismatch
}
}
}
// Using default_field or fields: Produces an error message
{
"query": {
"query_string": {
"query": "[2023-01-15T08:30 TO *]",
"default_field": "timestamp" // Will throw error: failed to parse date field
}
}
}Error message example:
failed to parse date field [2023-01-15T08:30] with format [yyyy-MM-dd'T'HH:mm:ss'Z']Other Parameters
1. Field-related Parameters
default_field vs fields:
default_field: Specifies a single field for default searching.fields: Specifies multiple search fields and their weights.
// Using default_field
{
"query_string": {
"query": "apple",
"default_field": "content"
}
}
// Using fields
{
"query_string": {
"query": "apple",
"fields": ["title^2", "content", "tags"]
}
}2. analyzer
Specifies how query_string processes and analyzes the query string. Elasticsearch provides various built-in analyzers; for a detailed list, refer to the official documentation.
{
"query_string": {
"query": "The Quick Brown Fox",
"analyzer": "standard"
}
}Important Concept: Index-time vs. Query-time Analyzers
Elasticsearch uses analyzers in two stages:
1. Index-time Analyzer
- Processes data being stored in the index.
- Example: text field stores
"Wing Chou"→ tokenized as["wing", "chou"].
2. Query-time Analyzer
- Processes the query string.
- The
analyzerparameter ofquery_stringcontrols this stage.
Example Explanation
Assuming the text field has stored "Wing Chou" and the index-time tokens are ["wing", "chou"]:
// ✅ Using standard analyzer
// Query string is analyzed as ["wing", "chou"], and the default operator is OR, so it matches the data regardless of whether it's wing or chou
{
"query_string": {
"query": "Wing Chou",
"analyzer": "standard"
}
}
// ❌ Using keyword analyzer, incorrect query condition
// Query string remains the complete "Wing Chou", which cannot match the tokenized results
{
"query_string": {
"query": "Wing Chou",
"analyzer": "keyword"
}
}
// Query string remains "Wing" (uppercase), cannot match "wing" (lowercase) in the data
{
"query_string": {
"query": "Wing",
"analyzer": "keyword"
}
}
// ✅ Using keyword analyzer, correct query condition
{
"query_string": {
"query": "wing",
"analyzer": "keyword"
}
}
{
"query_string": {
"query": "wing OR chou",
"analyzer": "keyword"
}
}3. analyze_wildcard
Controls whether wildcard expressions are analyzed. The official documentation states:
(Optional, boolean) If
true, the query attempts to analyze wildcard terms. Defaults tofalse.Note that even if set to
true, only queries ending in*are fully analyzed. Queries containing*at the beginning or in the middle are only normalized.
{
"query_string": {
"query": "Te*",
"analyze_wildcard": true,
"analyzer": "standard"
}
}Parameter Value Explanation
analyze_wildcard: false(default): Wildcard expressions are not processed by the analyzer.analyze_wildcard: true: Wildcard expressions are processed by the analyzer, but the method depends on the wildcard position:- Trailing wildcard (e.g.,
Te*): Fully analyzed. - Leading or middle wildcard (e.g.,
*Te*,T*e): Only normalized.
- Trailing wildcard (e.g.,
Observations and Questions from Testing
In actual testing, I found that the behavior of this parameter has some inconsistencies or is difficult to understand compared to the official documentation:
1. Behavior of Text fields
Regardless of whether analyze_wildcard is set to true or false, the query is case-insensitive:
// The following two queries yield the same results and both match the data
{
"query_string": {
"query": "name:Te*",
"analyze_wildcard": true
}
}
{
"query_string": {
"query": "name:Te*",
"analyze_wildcard": false
}
}2. Keyword fields without an analyzer specified
Regardless of whether analyze_wildcard is set to true or false, the query is case-sensitive:
// The following two queries yield the same results and both only match exact case
{
"query_string": {
"query": "email:Te*",
"analyze_wildcard": true
}
}
{
"query_string": {
"query": "email:Te*",
"analyze_wildcard": false
}
}3. Contradictory behavior when an analyzer is specified for Keyword fields
When analyzer: "standard" is specified for a keyword field, a phenomenon inconsistent with the official documentation appears (or perhaps my understanding of "full analysis" vs. "normalization" is incorrect):
// Leading or middle wildcard: Converted to lowercase (matches "normalization" description)
// Actual query: *te*
{
"query_string": {
"query": "email:(*Te*)",
"analyze_wildcard": true,
"analyzer": "standard"
}
}
// Trailing wildcard: Not converted to lowercase (contradicts "full analysis" description)
// Actual query: Te*
{
"query_string": {
"query": "email:(Te*)",
"analyze_wildcard": true,
"analyzer": "standard"
}
}According to the official documentation, trailing wildcards should be "fully analyzed," and theoretically Te* should be converted to te* by the standard analyzer, but the test result shows it remains Te*.
Processing Differences by Wildcard Position
| Wildcard Pattern | Official Description | Keyword + standard analyzer test |
|---|---|---|
Te* | Full analysis | Not converted to lowercase (Te*) |
*Te* | Normalization only | Converted to lowercase (*te*) |
*Te | Normalization only | Converted to lowercase (*te) |
T*e | Normalization only | Converted to lowercase (t*e) |
4. auto_generate_synonyms_phrase_query
Controls how synonyms are handled:
true(default): Automatically generates phrase queries for synonyms, maintaining word order and adjacency.false: Generates only standard synonym queries, ignoring word order.
For example, if "ny" and "new york" are defined as synonyms:
{
"query_string": {
"query": "ny restaurants",
"auto_generate_synonyms_phrase_query": true
}
}- true: Matches "ny restaurants" or "new york restaurants" ("new york" as a whole phrase).
- false: Matches "ny restaurants" or "new restaurants" or "york restaurants".
5. Weight Control: boost and Field Weighting
Elasticsearch provides two levels of weight control mechanisms:
5.1 Field Boost
Use the ^ syntax to adjust the weight of specific fields.
{
"query_string": {
"query": "apple iphone",
"fields": ["title^3", "description^2", "content"]
}
}- Function: Controls the relative importance of different fields in the same query.
- Mechanism:
- Each field independently calculates a base score (based on the BM25 algorithm).
- The score for the
titlefield is multiplied by 3. - The score for the
descriptionfield is multiplied by 2. - The score for the
contentfield is multiplied by 1 (default). - Finally, all weighted field scores are added together to get the final score.
- Important Note:
title^3does not mean the final score oftitleis 3 times that ofcontent; it means the base score of thetitlefield is amplified by 3 before being combined with other fields. The final score is also affected by factors like term frequency, inverse document frequency, and document length. - Scenario: When searching across multiple fields, some fields (like titles) represent the document topic better than others (like content).
Calculation Example (base scores are hypothetical):
Assuming a search for "apple", the base scores for each field are as follows:
| Field | Base Score | Weighted Score |
|---|---|---|
| title | 2.0 | 2.0 × 3 = 6.0 |
| description | 1.5 | 1.5 × 2 = 3.0 |
| content | 2.5 | 2.5 × 1 = 2.5 |
| Final Score | 11.5 |
Note: The above base scores are hypothetical examples used to explain the calculation logic. Actual scores will vary based on index state, document content, term frequency, etc. You must use the
_explainAPI to view the actual scoring process.
5.2 Query-level Boost
Adjusts the weight of the entire query clause.
{
"query_string": {
"query": "apple iphone",
"boost": 2.0
}
}- Function: Adjusts the importance of the entire query clause in a compound query (like a bool query).
- Important Limitation: If used alone, the
boostparameter has no effect on sorting (all document scores are multiplied by the same factor, so the relative order does not change). - Primary Use:
- In the
shouldclause of aboolquery, adjust the relative importance of different query conditions. - Make certain matching conditions have a greater impact on the final sorting than others.
- Reflect the importance differences of different search dimensions in business logic.
- In the
- Scenario: Combining multiple query methods (text search, exact match, range query, etc.) where you need to adjust their impact weight on the final sorting.
5.3 Combining Both
Example
{
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "apple",
"fields": ["title^2"],
"boost": 2.0
}
},
{
"query_string": {
"query": "iphone",
"fields": ["description"],
"boost": 4.0
}
}
]
}
}
}Calculation Explanation (base scores are hypothetical):
Assuming there are three documents:
| Document | title contains "apple" | description contains "iphone" | Score Calculation |
|---|---|---|---|
| Doc A | ✅ (Base 3.0) | ✅ (Base 2.0) | (3.0 × 2 × 2.0) + (2.0 × 1 × 4.0) = 20.0 |
| Doc B | ✅ (Base 2.5) | ❌ | (2.5 × 2 × 2.0) + 0 = 10.0 |
| Doc C | ❌ | ✅ (Base 2.5) | 0 + (2.5 × 1 × 4.0) = 10.0 |
Sorting Result: Doc A (20.0) > Doc B (10.0) = Doc C (10.0)
Analysis:
- Doc A matches both conditions and gets the highest score.
- Doc B only matches "apple" in the title: Base score 2.5 × Field boost 2 × Query boost 2.0 = 10.0.
- Doc C only matches "iphone" in the description: Base score 2.5 × Field boost 1 × Query boost 4.0 = 10.0.
Even though Doc C's query boost (4.0) is higher than Doc B's (2.0), because Doc B has a field boost (^2), the actual result still depends on the base scores.
Note: The above base scores are hypothetical; actual scores must be viewed using the
_explainAPI.
5.4 Key Differences
| Feature | Field Boost (^) | Query Boost (boost) |
|---|---|---|
| Scope | Different fields within a single query | Different query clauses in a compound query |
| Control Object | Relative weight between fields | Relative weight between query clauses |
| Location | In the fields parameter | Top-level parameter of the query clause |
| Used Alone | Effective (affects field score combination) | Ineffective (does not change sorting) |
| Typical Scenario | Title is more important than content | User search is more important than filter conditions |
6. Fuzzy Search (fuzziness and phrase_slop)
The tilde ~ has two different uses in QueryString, depending on its position:
6.1 Fuzzy Search (Tilde after a word)
apple~ // Tilde after a word indicates fuzzy search
apple~2 // Specifies fuzziness as 2- Corresponding parameter:
fuzziness. - Function: Handles spelling errors in a single word based on edit distance.
- Identification: Used after a word.
Fuzziness Value Limits:
- Valid values:
0,1,2, or"AUTO". - Values greater than 2 will cause an error:
Valid edit distances are [0, 1, 2].
Conditions for fuzziness parameter to take effect:
The fuzziness parameter only takes effect when a word in the query string uses ~ (but does not specify a number):
// ✅ Word has ~, no number, no fuzziness set: default fuzziness is 1
{
"query_string": {
"query": "apple~" // apple uses fuzziness 1 (default)
}
}
// ✅ Word has ~, no number: uses fuzziness parameter
{
"query_string": {
"query": "apple~",
"fuzziness": 2 // Takes effect, apple uses fuzziness 2
}
}
// ❌ Word has no ~: does not take effect
{
"query_string": {
"query": "apple banana",
"fuzziness": 1 // Does not take effect, both words are exact matches
}
}
// ❌ Word has ~N (explicit number): uses the number in the query string
{
"query_string": {
"query": "apple~2",
"fuzziness": 1 // Does not take effect, uses the 2 from the query string
}
}
// ⚠️ Mixed case: only words with ~ apply fuzzy search
{
"query_string": {
"query": "apple~2 banana",
"fuzziness": 1 // Does not take effect, apple uses 2, banana is exact match
}
}
{
"query_string": {
"query": "apple~ banana",
"fuzziness": 1 // Only takes effect for apple (fuzziness 1), banana is exact match
}
}Priority Rules:
~Nin the query string (explicit number): Uses that number directly.~in the query string (no number) +fuzzinessparameter: Uses thefuzzinessparameter value.~in the query string (no number) + nofuzzinessset: Default fuzziness is 1.- No
~in the query string: The word is an exact match; thefuzzinessparameter does not take effect.
⚠️ Important Note:
The fuzziness parameter must be used with ~ in the query string to take effect. If there is no ~ after the term, the term is treated as an exact match, regardless of the fuzziness parameter setting.
Fuzziness Setting Differences:
"fuzziness": "AUTO": Automatically adjusts based on word length. The default behavior is equivalent toAUTO:3,6, with the following rules:- Word length 0-2 characters: fuzziness = 0 (must be an exact match)
- Word length 3-5 characters: fuzziness = 1
- Word length 6+ characters: fuzziness = 2
"fuzziness": "AUTO:[low],[high]": AUTO mode with custom thresholds. For example,AUTO:4,7means:- Word length 0-3 characters: fuzziness = 0
- Word length 4-6 characters: fuzziness = 1
- Word length 7+ characters: fuzziness = 2
"fuzziness": 1or"fuzziness": 2: Fixed maximum allowed edit distance.
For detailed information, please refer to the official documentation.
Example:
apple~1can match spelling errors like "aple", "appla", etc.
6.2 Proximity Search (Tilde after a phrase)
"apple banana"~5 // Tilde after a phrase indicates proximity search- Corresponding parameter:
phrase_slop - Function: Handles the order and distance of words in a phrase.
- Identification: Used after a phrase enclosed in quotes.
Slop Value Calculation Logic:
Slop represents the minimum number of steps words need to "move," which can handle:
- Other words interspersed between the terms.
- Incorrect word order (swapped).
Calculation Explanation:
Assuming the index contains "quick brown fox jumps"
// Example 1: Interspersed words
Query: "quick fox"
Index: "quick brown fox"
→ "fox" needs to move 1 step to the left, skipping "brown"
→ slop = 1
// Example 2: Adjacent word order swapped
Query: "brown quick"
Index: "quick brown"
→ The two words swap positions
→ slop = 2 (Official documentation: swap cost is 2)
// Example 3: Non-adjacent word order swapped + interspersed
Query: "fox quick"
Index: "quick brown fox"
→ "fox" needs to move in front of "quick," crossing 2 positions
→ slop = 3Actual Example:
// slop = 0: Must match exactly
{
"query_string": {
"query": "\"quick brown\""
}
}
// ✅ Matches: "quick brown fox"
// slop = 1: Allows 1 word in between
{
"query_string": {
"query": "\"quick fox\"~1"
}
}
// slop = 2: Allows adjacent words to be swapped
// ✅ Matches: "quick brown fox"
// ❌ Does not match: "quick fox"
{
"query_string": {
"query": "\"brown quick\"~2"
}
}
// slop = 3: Allows more complex movement
// ✅ Matches: "quick brown fox"
{
"query_string": {
"query": "\"fox quick\"~3"
}
}Setting in API:
{
"query_string": {
"query": "apple~2 \"quick fox\"~3",
"fuzziness": "AUTO", // Global setting, overridden by specific values in the query
"phrase_slop": 2 // Global setting, overridden by specific values in the query
}
}Priority:
Values set using ~ in the query string override the global settings in the API parameters.
Pagination and Sorting
Pagination Parameters
{
"query": {
"query_string": {
"query": "apple"
}
},
"from": 0, // Starting position, defaults to 0
"size": 10 // Number of items per page, defaults to 10
}from: Specifies the starting result index (0 represents the first result).size: Specifies how many results to return.
Notes:
- Deep pagination (
from+sizetoo large) affects performance. - Elasticsearch defaults to limiting
from+sizeto no more than 10,000. - For processing large amounts of data, it is recommended to use the Search After or Scroll API.
Sorting Parameters
The sort parameter accepts an array, allowing you to specify multiple sorting conditions. The sorting priority is determined by the order in the array.
Sorting Syntax
Method 1: Simple field name (defaults to ascending)
{
"sort": ["price"] // Sort by price ascending
}Method 2: Field + sort direction object
{
"sort": [
{ "price": "asc" } // Sort by price ascending
]
}Method 3: Full configuration object
{
"sort": [
{
"price": {
"order": "desc", // Sort direction: asc (ascending) or desc (descending)
"missing": "_last" // Documents missing this field are placed at the end
}
}
]
}Multi-field Sorting
{
"query": {
"query_string": {
"query": "apple"
}
},
"sort": [
{ "price": "asc" }, // First priority: sort by price ascending
{ "created_at": "desc" }, // Second priority: if price is the same, sort by created_at descending
"_score" // Third priority: if other conditions are the same, sort by relevance score
]
}Special Sorting Values
"_score": Sort by query relevance score (defaults to descending)."_doc": Sort by the internal order of the document (fastest, but the order is not fixed).
Sorting Direction
"asc": Ascending - from smallest to largest."desc": Descending - from largest to smallest.
Handling Missing Values
Use the missing parameter to specify where documents missing the sorting field should be placed:
{
"sort": [
{
"price": {
"order": "asc",
"missing": "_last" // Options: _first (place at start), _last (place at end), or specify a default value
}
}
]
}Full Example
{
"query": {
"query_string": {
"query": "laptop"
}
},
"from": 0,
"size": 20,
"sort": [
{ "price": { "order": "asc", "missing": "_last" } },
{ "rating": "desc" },
"_score"
]
}Sorting Logic Explanation:
- Sort by price ascending first (those without a price are placed at the end).
- If prices are the same, sort by rating descending.
- If prices and ratings are both the same, sort by relevance score.
Special Character Escaping
Many special characters in QueryString have specific meanings. If you want to use them as ordinary characters, you need to escape them with a backslash \:
\+ \- \= \&\& \|\| \> \< \! \( \) \{ \} \[ \] \^ \" \~ \* \? \: \\ \/For example:
- Search for documents containing a plus sign:
title:\+1. - Search for documents containing parentheses:
content:\(sample\). - Search for documents containing quotes:
description:\"quoted text\".
Changelog
- 2025-04-13 Initial document created.
- 2025-10-03
- Refined phrasing and terminology.
- Corrected explanation of date query range syntax (date fields do not support comparison operators; range query syntax should be used).
- Corrected the weight calculation to include the missing field base score component.
- Added technical details.
