﻿---
title: Get started with ES|QL in Discover
description: Learn how ES|QL commands change the results you see in Discover by building one query step by step on the sample web logs.
url: https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/try-esql
products:
  - Elastic Documentation
  - Kibana
applies_to:
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Generally available
---

# Get started with ES|QL in Discover
In this tutorial, you explore the Kibana sample web logs in **Discover** with Elasticsearch Query Language (ES|QL). You build one query step by step and see how each command changes the results in the table and the chart.
You don't need a [data view](/elastic/docs-builder/docs/4302/explore-analyze/discover/discover-get-started#find-the-data-you-want-to-use), and you don't need ES|QL experience. For the rest of Discover, refer to [Explore fields and data with Discover](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/discover-get-started). For the language itself, refer to the [ES|QL reference](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/esql-syntax-reference).
By the end of this tutorial, you'll know the main elements of your query and how they shape the results you see in **Discover**. You'll practice how to:
- Query a data source with `FROM`.
- Keep only the columns you need with `KEEP`.
- Filter the results with `WHERE`.
- Find the top results with `SORT` and `LIMIT`.
- Count the results by group with `STATS`.
- Save your query as a Discover session.

<stepper>
  <step title="Before you begin">
    To follow this tutorial, you need the following:
    - ES|QL enabled in Kibana. It's enabled by default. On Elastic Stack deployments, an administrator can turn it off with the `enableESQL` advanced setting.
    - The Kibana sample web logs. Add them from [Add sample data](https://www.elastic.co/elastic/docs-builder/docs/4302/manage-data/ingest/sample-data). You can use your own indices instead. Replace `kibana_sample_data_logs` in the examples with a data source you can query, and replace the field names in later steps with fields from your data.
    Depending on the solution you use and the data you query, Discover can show slightly different columns and options than this tutorial. Refer to [Context-aware data exploration](/elastic/docs-builder/docs/4302/explore-analyze/discover/discover-get-started#context-aware-discover).To help you go faster with what you learn in this tutorial, or to go further once you know the basics, the ES|QL editor offers several tools. It suggests commands, fields, and values as you type, and its in-app help shows the syntax of each command. Depending on your version and setup, you can also browse data sources and fields, filter your data with KQL, or have AI write or fix a query. This tutorial has you write each command yourself so that you learn what it does. Refer to [Write queries with the ES|QL editor](/elastic/docs-builder/docs/4302/explore-analyze/query-filter/languages/esql-kibana#esql-kibana-get-started).
  </step>

  <step title="Query a data source">
    In ES|QL mode, the query decides which data you explore. There is no data view to select as in classic mode. Instead, the first command of every query names the data source, and the table and the chart show what that source returns.This first command is a [source command](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/source-commands):
    - [`FROM`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/from) is the generic ES|QL source command. It takes the names of the sources to read, for example, an index or a data stream. You can list several names or match them with a wildcard, such as `FROM logs-*`.
    - Other source commands serve specific cases. For example, [`TS`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/ts) queries time series data streams, and [`PROMQL`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/promql) runs a Prometheus Query Language (PromQL) query.
    Command names aren't case-sensitive, so `from` and `FROM` are the same.
    1. Open **Discover** from the navigation menu or the [global search field](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/find-and-organize/find-apps-and-objects).
    2. If the editor isn't in ES|QL mode yet, select **Query in ES|QL** (**Try ES|QL** in earlier versions) in the application menu. For other ways to switch, refer to [Switch between ES|QL and classic mode](/elastic/docs-builder/docs/4302/explore-analyze/discover/switch-esql-mode#switch-discover-query-mode).
    3. Set the time filter to the seven days before you installed the sample data. Kibana sets the sample timestamps relative to the day you install the data. If you installed it today, select **Last 7 days**. Otherwise, [set a custom range](/elastic/docs-builder/docs/4302/explore-analyze/query-filter/filtering#set-time-filter) that ends on the installation date.
       The sample web logs have an `@timestamp` field, so Discover uses it for the time filter and the chart over time. The time filter keeps only the results in the range you select, and the chart shows how they spread over that range.
       <tip>
       If you use your own data and it has no `@timestamp` field, refer to [Set the time filter for the table and the chart](/elastic/docs-builder/docs/4302/explore-analyze/discover/esql-results#_esql_and_time_series_data).
       </tip>
    4. Enter the following query in the editor:
       ```esql
       FROM kibana_sample_data_logs
       ```
       To query your own data, replace `kibana_sample_data_logs` with the name of your source. If you don't know the name, [browse the data sources from the editor](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/browse-esql-sources).
    5. Select **Search** (or **▶Run** in earlier versions).
    **Result:** The table lists up to 1,000 results by default, with the time and a **Summary** of each result. The chart shows how the results spread over those seven days. It counts all the matching results in the time range, not only the 1,000 rows in the table. If the table is empty, widen the time range.
    ![Discover in ES|QL mode with the query FROM kibana_sample_data_logs, a histogram of results over time, and a table with @timestamp and Summary columns](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/images/kibana-discover-try-esql-from.png)
    The table isn't the end of your exploration. To look at one result in detail, select `maximize` **View details** (**Toggle dialog with details** in earlier versions) on its row. The flyout lists all its fields, and you can filter the results from any of its values. Refer to [Explore individual result or document details in depth](/elastic/docs-builder/docs/4302/explore-analyze/discover/discover-get-started#look-inside-a-document).
  </step>

  <step title="Keep only the columns you need">
    Each result has dozens of fields, but the table shows only the time and a **Summary** by default. To answer a question, you usually need a few specific fields as their own columns. In this step, you keep four fields: the response size, the destination country, the operating system, and the response code.An ES|QL query is a chain of commands separated by pipes (`|`). Each command after the source command takes the results of the previous command, changes them, and passes them on. Commands run in the order you write them.Commands after the source command are processing commands. [`KEEP`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/keep) is one of them. It keeps only the columns you list, in that order. It doesn't remove any results.Once `KEEP` sets the columns, Discover builds a chart from them instead of the chart over time. The two charts use different rows. The chart over time uses every matching result in the time range. A chart built from your columns uses only the rows that the query returns, so at most 1,000 by default.
    1. Add a `KEEP` line to the query:
       ```esql
       FROM kibana_sample_data_logs
       | KEEP bytes, geo.dest, machine.os, response.keyword
       ```
       As you enter a field name, the editor suggests matching fields. Select a suggestion to insert it. Refer to [Autocomplete and in-app help](/elastic/docs-builder/docs/4302/explore-analyze/query-filter/languages/esql-kibana#esql-kibana-autocomplete).
    2. Select **Search**.
    **Result:** The table shows four columns: `bytes`, `geo.dest`, `machine.os`, and `response.keyword`. The number of results stays the same, and Discover now picks a chart that fits the columns you kept, such as `bytes` by `geo.dest`. The time filter still applies, even though `@timestamp` is no longer a column.
    ![Discover with a KEEP query on bytes, geo.dest, machine.os, and response.keyword, a chart of bytes by destination, and a table with those four columns](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/images/kibana-discover-try-esql-keep.png)
    You can also add a column from the fields list. This changes only the table, not the query, so the chart keeps showing the results over time. It works well for a quick look at a field. Use `KEEP` when the columns are part of your question, because they're saved with the query, for example, in a Discover session or on a dashboard. Refer to [Show specific columns in the results table](/elastic/docs-builder/docs/4302/explore-analyze/discover/esql-results#esql-kibana-results-table).
  </step>

  <step title="Filter the results">
    Filtering keeps only the results you care about. In this step, you exclude the results whose destination is the United Kingdom (`GB`).[`WHERE`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/where) keeps only the results that match a condition. A condition uses an [operator](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/functions-operators/operators), such as `==`, `!=`, `>`, or `<`, to compare a field with a value. You can combine conditions with `AND` and `OR`. Put text values in double quotation marks.Because `WHERE` removes results, it changes both the table and the chart.
    1. Add a `WHERE` line to the query:
       ```esql
       FROM kibana_sample_data_logs
       | KEEP bytes, geo.dest, machine.os, response.keyword
       | WHERE geo.dest != "GB"
       ```
       The `!=` operator keeps every result whose destination isn't `GB`.
    2. Select **Search**.
    **Result:** The results with `GB` as their destination are gone from the table and from the chart. The result count stays at 1,000 because of the default limit, but no `geo.dest` value is `GB`.You can also filter from the table, so you don't need to enter the field name and value. Hover over a value, then select **Filter for this** or **Filter out this**, and Discover writes the `WHERE` line for you. Refer to [Filter from a value in the results table](/elastic/docs-builder/docs/4302/explore-analyze/discover/esql-results#refine-esql-query-from-table).
    <tip applies-to="Elastic Cloud Serverless: Preview, Elastic Stack: Preview since 9.3">
      If you know KQL, you can also filter from the editor's [search bar](/elastic/docs-builder/docs/4302/explore-analyze/query-filter/languages/esql-kibana#esql-kibana-quick-search). When you submit a KQL query there, Discover replaces your whole query with a `FROM` command and a `WHERE KQL()` line that contains your KQL query. Commands such as `KEEP` are removed, so to keep building on your query, use `WHERE`.
    </tip>
  </step>

  <step title="Find the top results">
    Sorting and limiting bring the results you want to the top, such as the largest responses. In this step, you list the 10 results with the highest `bytes` value.[`SORT`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/sort) orders the results by a field, in ascending (`asc`) or descending (`desc`) order. [`LIMIT`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/limit) keeps only the first results. Because commands run in order, `SORT` followed by `LIMIT 10` returns the top 10. Without `SORT`, `LIMIT 10` returns any 10 results. `LIMIT` also replaces the default limit of 1,000 results.
    1. Add `SORT` and `LIMIT` lines to the query:
       ```esql
       FROM kibana_sample_data_logs
       | KEEP bytes, geo.dest, machine.os, response.keyword
       | WHERE geo.dest != "GB"
       | SORT bytes desc
       | LIMIT 10
       ```
    2. Select **Search**.
    **Result:** The table lists 10 results, starting with the highest `bytes` value. The chart now reflects only these 10 results.
    ![Discover with a query that sorts by bytes in descending order and limits to 10, a chart of bytes by destination for those results, and a table with 10 results](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/images/kibana-discover-try-esql-sort-limit.png)
    Sorting from a column header in the table is different. It reorders only the results already in the table, and it doesn't change which results the query returns. Refer to [Sort query results](/elastic/docs-builder/docs/4302/explore-analyze/discover/esql-results#_sorting).
  </step>

  <step title="Count the results by group">
    So far, each row in the table is one result. To find out which destinations appear most often, you need one row per destination, with a count. In this step, you count the results for each destination.[`STATS`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/stats-by) aggregates the results. An [aggregation function](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/functions-operators/aggregation-functions), such as `COUNT`, `AVG`, or `SUM`, computes a value, and `BY` sets the groups. In `STATS count = COUNT(*) BY geo.dest`, `COUNT(*)` counts the results in each group, and `BY geo.dest` makes one group per destination. `count =` names the new column, which is separate from the `COUNT` function.After `STATS`, each row is a group, not a single result. The query returns only the new `count` column and the `BY` column, `geo.dest`. That's why the query no longer needs `KEEP`, and why `SORT` now uses `count`. The query also drops `LIMIT 10`, so the table lists every destination instead of the first 10. The `WHERE` line stays before `STATS`, so the counts still exclude the United Kingdom.
    1. Replace the query with the following one:
       ```esql
       FROM kibana_sample_data_logs
       | WHERE geo.dest != "GB"
       | STATS count = COUNT(*) BY geo.dest
       | SORT count desc
       ```
    2. Select **Search**.
    **Result:** The table shows each destination as a group with its count, starting with the highest. The counts include every matching result in the time range, because the default limit applies to the rows the query returns, which are now the groups. The chart shows the same counts. You can expand a group to see the results behind it.
    ![Discover with a STATS query that counts results by destination, a chart of counts by destination, and a table of groups with one group expanded to show its results](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/images/kibana-discover-try-esql-stats.png)
    `STATS` can compute several values at once, or group results by time to show a trend. Refer to the [`STATS` command](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/commands/stats-by). To look at the results behind a group, refer to [Inspect grouped STATS results in Discover](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/inspect-grouped-stats).
  </step>

  <step title="Save your exploration">
    Your query holds your whole exploration. Save it as a Discover session to come back to it, share it, or build on it later.A Discover session saves the query, not a copy of the results. When you open the session again, Discover runs the query again, so the results reflect the current data.
    1. Select **Save** in the application menu.
    2. In the **Title** field, enter a name, for example `Results by destination`.
       To reopen the session with the same time range, turn on **Store time with Discover session**.
    3. Select **Save**.
    **Result:** Discover saves the session. To reopen it later, select **Open session** in the application menu, then select the session.To share the session, refer to [Share your Discover session](/elastic/docs-builder/docs/4302/explore-analyze/discover/discover-get-started#share-your-findings). To add the chart or the table to a dashboard, refer to [Keep the chart or the table](/elastic/docs-builder/docs/4302/explore-analyze/discover/esql-results#_edit_the_esql_visualization).
  </step>
</stepper>


## Next steps

- [Use Discover with ES|QL](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/use-esql): Explore the other ES|QL tasks in Discover, including variable controls.
- [Create lookup indices from Discover queries](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/create-lookup-indices): Add fields from a lookup index with `LOOKUP JOIN`.
- [Detect change points in Discover](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/detect-change-points): Find a spike, dip, or shift in a time series.
- [ES|QL reference](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/esql-syntax-reference): Look up commands, functions, and operators beyond this tutorial.
- [Use ES|QL in the Kibana UI](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/query-filter/languages/esql-kibana): Use editor tools, time parameters, AI assistance, and Fast mode.
- [Learn data exploration and visualization with Kibana](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/kibana-data-exploration-learning-tutorial): Follow a longer path from Discover into dashboards.


## Related pages

- [Discover](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover)
- [Explore fields and data with Discover](https://www.elastic.co/elastic/docs-builder/docs/4302/explore-analyze/discover/discover-get-started)
- [Optimize ES|QL query performance](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/4302/reference/query-languages/esql/esql-query-performance)