# ES|QL Syntax

ES|QL (Elasticsearch Query Language) uses a simple yet powerful syntax that allows you to filter, transform, and analyze data stored in Elasticsearch. The syntax is composed of a source command followed by an optional series of processing commands, separated by a pipe character (`|`).

## Basic Syntax

An ES|QL query typically looks like this:

source-command
| processing-command1
| processing-command2

The result of a query is the table produced by the final processing command. For an overview of all supported commands, functions, and operators, refer to Commands and Functions and operators.

You can also write an ES|QL query as a single line. For example:

source-command
| processing-command1
| processing-command2

## Identifiers

Identifiers in ES|QL need to be quoted with backticks (```) if they don’t start with a letter, `_` or `@` or if any of the other characters is not a letter, number, or `_`. For example:

```esql
FROM index
| KEEP `1.field`
```

When referencing a function alias that itself uses a quoted identifier, the backticks of the quoted identifier need to be escaped with another backtick. For example:

```esql
FROM index
| STATS COUNT(`1.field`)
| EVAL my_count = `COUNT(``1.field``)`
```

## Literals

ES|QL currently supports numeric and string literals.

### String Literals

A string literal is a sequence of unicode characters delimited by double quotes (`"`). If the literal string itself contains quotes, these need to be escaped (`\\"`). ES|QL also supports the triple-quotes (`"""`) delimiter, for convenience. Special characters CR, LF and TAB can be provided with the usual escaping: `\r`, `\n`, `\t`, respectively.

```esql
FROM index
| WHERE first_name == "Georgi"
```

### Numerical Literals

The numeric literals are accepted in decimal and in the scientific notation with the exponent marker (`e` or `E`), starting either with a digit, decimal point `.` or the negative sign `-`. The integer numeric literals are implicitly converted to the `integer`, `long` or the `double` type, whichever can first accommodate the literal’s value. The floating point literals are implicitly converted the `double` type.

1969    -- integer notation
3.14    -- decimal notation
.1234   -- decimal notation starting with decimal point
4E5     -- scientific notation (with exponent marker)
1.2e-3  -- scientific notation with decimal point
-.1e2   -- scientific notation starting with the negative sign

## Comments

ES|QL uses C++ style comments: double slash `//` for single line comments and `/*` and `*/` for block comments.

```esql
// Query the employees index
FROM employees
| WHERE height > 2
```

## Timespan Literals

Datetime intervals and timespans can be expressed using timespan literals. Timespan literals are a combination of a number and a qualifier. These qualifiers are supported: `millisecond`/`milliseconds`/`ms`, `second`/`seconds`/`sec`/`s`, `minute`/`minutes`/`min`, `hour`/`hours`/`h`, `day`/`days`/`d`, `week`/`weeks`/`w`, `month`/`months`/`mo`, `quarter`/`quarters`/`q`, `year`/`years`/`yr`/`y`. Timespan literals are not whitespace sensitive.

1day
1 day
1       day

## Example Queries with Timespan Literals

Here are some example queries using timespan literals:

1. Querying data from the last 7 days:

```esql
FROM logs
| WHERE @timestamp >= NOW() - 7d
```

2. Aggregating data on an hourly basis for the past 24 hours:

```esql
FROM logs
| STATS COUNT(*) BY timestamp = DATE_TRUNC(1h, @timestamp)
| WHERE timestamp >= NOW() - 24h
```

3. Finding the average response time per minute for the last hour:

```esql
FROM logs
| STATS AVG(response_time) BY minute = DATE_TRUNC(1m, @timestamp)
| WHERE @timestamp >= NOW() - 1h
```

4. Aggregating data on a weekly basis for the past year:

```esql
FROM logs
| STATS COUNT(*) BY week = DATE_TRUNC(1w, @timestamp)
| WHERE @timestamp >= NOW() - 1y
```

5. Finding the maximum response time per second for the last minute:

```esql
FROM logs
| STATS MAX(response_time) BY second = DATE_TRUNC(1s, @timestamp)
| WHERE @timestamp >= NOW() - 1m
```
