The Elasticsearch simple_query_string query parses user input with a limited Lucene-style operator syntax (+, -, |, *, ~, "...", ( )), then runs the resulting clauses across one or more fields. Unlike query_string, it never throws on invalid syntax - malformed parts are silently dropped. That makes it the standard choice for search boxes exposed to end users, where a stray quote or unbalanced parenthesis should not return a 400.
Syntax
{
"query": {
"simple_query_string": {
"query": "(quick OR brown) +fox -lazy",
"fields": ["title^3", "body"],
"default_operator": "or",
"analyzer": "standard",
"flags": "ALL",
"lenient": true,
"minimum_should_match": "50%",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"analyze_wildcard": false,
"auto_generate_synonyms_phrase_query": true
}
}
}
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
query |
string | - | User input. Required. |
fields |
array | index.query.default_field |
Fields to search; ^n suffix boosts. |
default_operator |
or | and |
or |
Combine bare terms with OR or AND. |
analyzer |
string | field analyzer | Override analyzer at query time. |
flags |
string | ALL |
Pipe-separated list of operators to allow. |
lenient |
bool | false | Ignore type-mismatch errors. |
minimum_should_match |
int / percent | - | Threshold for OR-combined tokens. |
fuzzy_prefix_length |
int | 0 | Leading exact chars for ~ fuzzy operator. |
fuzzy_max_expansions |
int | 50 | Cap on fuzzy variants. |
analyze_wildcard |
bool | false | Analyze terms containing *. |
auto_generate_synonyms_phrase_query |
bool | true | Build phrase queries from multi-word synonyms. |
Operators in the query text: + (must), - (must_not), | (OR), * (prefix), "..." (phrase), ~N (fuzzy / phrase slop), ( ) (grouping).
Available flags include AND, OR, NOT, PREFIX, PHRASE, PRECEDENCE, ESCAPE, WHITESPACE, FUZZY, NEAR, SLOP, ALL, NONE.
Examples
Multi-field search with field boost:
GET /articles/_search
{
"query": {
"simple_query_string": {
"query": "elasticsearch performance",
"fields": ["title^3", "body"],
"default_operator": "and"
}
}
}
Restrict allowed operators - only OR and NOT, no fuzzy or wildcard:
GET /articles/_search
{
"query": {
"simple_query_string": {
"query": "kafka | streams -deprecated",
"fields": ["body"],
"flags": "OR|NOT"
}
}
}
Quoted phrase with slop:
GET /articles/_search
{
"query": {
"simple_query_string": {
"query": "\"distributed search\"~2",
"fields": ["body"]
}
}
}
Prefix and fuzzy in one query:
GET /articles/_search
{
"query": {
"simple_query_string": {
"query": "elast* tunin~2",
"fields": ["title", "body"]
}
}
}
Performance and Use Notes
simple_query_string rewrites internally into a bool of match/match_phrase/prefix/fuzzy clauses across each listed field, so cost grows with both the number of fields and the operators used. Wildcard, prefix, and fuzzy operators are the expensive ones; restrict them via flags when the search box is public-facing.
When fields is omitted, the parser uses index.query.default_field (defaults to all text-typed fields). On wide indices this expands into a huge bool and slows the query dramatically - always specify fields explicitly. Leading wildcards are accepted but require scanning the term dictionary; combine with index_options: positions only where needed.
User-facing search bars driven by simple_query_string often turn into the dominant query cost on a cluster. Pulse tracks slow simple_query_string patterns - leading wildcards, missing fields, runaway fuzzy expansions - and recommends bounded flag sets and field lists for production search endpoints.
Common Mistakes
- Omitting
fieldsand accidentally searching everytextfield in the index. - Allowing the
FUZZYflag in production with nofuzzy_prefix_length; users typinga~2enumerate enormous term lists. - Confusing this with query_string, which throws on parse errors.
- Using
analyze_wildcard: trueagainst a stemming analyzer; the wildcard rarely survives stemming intact. - Boosting a
keywordsubfield (title.keyword^5) - keyword subfields will only match exact input, so the boost rarely fires.
Frequently Asked Questions
Q: What is the difference between simple_query_string and query_string in Elasticsearch?
A: simple_query_string uses a limited, forgiving operator set and ignores syntax errors; query_string supports the full Lucene query syntax and throws on malformed input. Use simple_query_string for end-user input, query_string for trusted internal callers building DSL.
Q: Which operators does simple_query_string support?
A: + (must), - (must_not), | (OR), * (prefix wildcard), "..." (phrase), ~N (fuzzy on terms, slop on phrases), and ( ) for grouping. The flags parameter restricts which of these are active.
Q: How do I boost a field in a simple_query_string query?
A: Append ^n to the field name in the fields array: "fields": ["title^3", "body"] makes matches in title count three times as much as matches in body.
Q: Why is my simple_query_string query slow?
A: The most common causes are not setting fields (so the query expands across every text field), enabling FUZZY with no prefix length, or letting users submit leading-wildcard terms. Restrict flags, set fuzzy_prefix_length to at least 2, and explicitly list fields.
Q: Does simple_query_string support phrase queries?
A: Yes. Quoting a phrase ("distributed search") produces a match_phrase query; appending ~N after the quoted phrase sets the slop.
Q: Can I disable wildcards in simple_query_string?
A: Yes - set flags to exclude PREFIX (and WHITESPACE, which can be used to inject wildcards). For example, "flags": "AND|OR|NOT|PHRASE" allows boolean operators and phrases but blocks *.
Related Reading
- Elasticsearch Match Query: single-field analyzed search.
- Elasticsearch Match Phrase Query: position-aware phrase search.
- Elasticsearch Bool Query: structured combination of clauses.
- Elasticsearch Fuzzy Query: direct control over fuzzy term matching.
- Elasticsearch Wildcard Query: explicit wildcard matching.