KQL
The Kibana Query Language (KQL) is a text-based query language for filtering data.
- KQL only filters data. It does not aggregate, transform, or sort data.
- KQL is different from the Lucene query language. Lucene has a different feature set.
Use KQL to filter documents by field existence, value, or range.
To compare KQL with Query DSL, ES|QL, and other languages, refer to Query languages.
Combine free text search with field-based search using KQL. Enter a term to match across all fields. Start typing a field name to get suggestions for fields and operators.
| Query type | Example |
|---|---|
| Exact phrase query | http.response.body.content.text:"quick brown fox" |
| Multiple values | http.response.status_code: (400 OR 401 OR 404) |
| Boolean query | response:200 or extension:php |
| Range query | account_number >= 100 and items_sold <= 200 |
| Wildcard query | machine.os:win* |
To match any of several values on one field, use parentheses and OR. For the full syntax, refer to Combining multiple queries.
To find documents where a field has an indexed value, use *. For example, documents where http.request.method exists:
http.request.method: *
This matches any indexed value, including an empty string.
Use KQL to match a number, text, date, or boolean value. For example, documents where http.request.method is GET:
http.request.method: GET
The field name is optional. If you omit it, KQL searches all fields for the given value. For example, to search all fields for “Hello”:
Hello
On keyword, numeric, date, or boolean fields, the value must match exactly, including punctuation and case.
On text fields, Elasticsearch analyzes the value using the field’s mapping settings. For example, documents where http.request.body.content contains “null pointer”:
http.request.body.content: null pointer
Because this is a text field, the order of these search terms does not matter. Documents that contain “pointer null” also match. To search text fields for terms in that order, surround the value in quotation marks:
http.request.body.content: "null pointer"
Escape certain characters with a backslash, unless you surround the value with quotes. For example, either of these queries matches http.request.referrer https://example.com:
http.request.referrer: "https://example.com"
http.request.referrer: https\://example.com
Escape these characters:
\():<>"*
To find values in a range, use KQL range syntax. For example, http.response.bytes less than 10000:
http.response.bytes < 10000
For an inclusive range, combine conditions. For example, bytes greater than 10000 and less than or equal to 20000:
http.response.bytes > 10000 and http.response.bytes <= 20000
On multi-value fields, KQL tests each condition against every value in the array. number > 300 AND number < 400 matches "number": [500, 10]. 500 matches the first condition and 10 matches the second. If one value must satisfy every condition, use Query DSL.
You can also use range syntax for strings, IP addresses, and timestamps. For example, documents earlier than two weeks ago:
@timestamp < now-2w
For more examples on acceptable date formats, refer to Date Math.
To match a pattern, use a wildcard. You can use wildcards on keyword, text, and wildcard fields. They do not work on numeric, date, or boolean fields.
For example, machine.os values that begin with "win":
machine.os: win*
Only * is supported. It matches zero or more characters.
By default, you can put * at the start of a pattern. For example, url values that contain elastic:
url: *elastic*
Queries that start with * can slow searches.
query:allowLeadingWildcards advanced setting.
To exclude documents, use the not keyword (not case-sensitive). For example, documents where http.request.method is not GET:
NOT http.request.method: GET
To combine queries, use AND or OR (not case-sensitive). For example, GET requests or responses with status 400:
http.request.method: GET OR http.response.status_code: 400
To require both conditions, use AND:
http.request.method: GET AND http.response.status_code: 400
Use parentheses to set precedence. This example matches GET requests with status 200, or POST requests with status 400:
(http.request.method: GET AND http.response.status_code: 200) OR
(http.request.method: POST AND http.response.status_code: 400)
You can also use parentheses to match several values on one field. For example, GET, POST, or DELETE:
http.request.method: (GET OR POST OR DELETE)
You can also use wildcards to query multiple fields. For example, documents where any sub-field of datastream contains “logs”:
datastream.*: logs
If the matching fields have different types, the query can fail. For example, if datastream.* matches both numeric and string fields, datastream.*: logs returns an error. You cannot query numeric fields for string values.
Nested fields use a special syntax. Consider this document, where user is nested:
{
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
To find a user array value with first name “Alice” and last name “White”:
user:{ first: "Alice" and last: "White" }
If nested fields contain other nested fields, use the full path. Consider this document, where user and names are both nested:
{
"user": [
{
"names": [
{
"first": "John",
"last": "Smith"
},
{
"first": "Alice",
"last": "White"
}
]
}
]
}
To find a user.names array value with first name “Alice” and last name “White”:
user.names:{ first: "Alice" and last: "White" }