Начало работы с запросами ES|QL
В этом руководстве показано, как использовать ES|QL для запроса и агрегации данных.
Это начальное руководство также доступно в виде интерактивной Python-записной книжки в репозитории GitHub в elasticsearch-labs.
Предварительные требования
Чтобы следовать запросам в этом руководстве, вы можете настроить собственное развертывание или использовать публичную демонстрационную среду ES|QL от Elastic.
Сначала импортируйте примерные данные. В Kibana откройте главное меню и выберите Инструменты разработчика. Запустите следующие два запроса:
resp = client.indices.create(
index="sample_data",
mappings={
"properties": {
"client_ip": {
"type": "ip"
},
"message": {
"type": "keyword"
}
}
},
)
print(resp)
resp1 = client.bulk(
index="sample_data",
operations=[
{
"index": {}
},
{
"@timestamp": "2023-10-23T12:15:03.360Z",
"client_ip": "172.21.2.162",
"message": "Connected to 10.1.0.3",
"event_duration": 3450233
},
{
"index": {}
},
{
"@timestamp": "2023-10-23T12:27:28.948Z",
"client_ip": "172.21.2.113",
"message": "Connected to 10.1.0.2",
"event_duration": 2764889
},
{
"index": {}
},
{
"@timestamp": "2023-10-23T13:33:34.937Z",
"client_ip": "172.21.0.5",
"message": "Disconnected",
"event_duration": 1232382
},
{
"index": {}
},
{
"@timestamp": "2023-10-23T13:51:54.732Z",
"client_ip": "172.21.3.15",
"message": "Connection error",
"event_duration": 725448
},
{
"index": {}
},
{
"@timestamp": "2023-10-23T13:52:55.015Z",
"client_ip": "172.21.3.15",
"message": "Connection error",
"event_duration": 8268153
},
{
"index": {}
},
{
"@timestamp": "2023-10-23T13:53:55.832Z",
"client_ip": "172.21.3.15",
"message": "Connection error",
"event_duration": 5033755
},
{
"index": {}
},
{
"@timestamp": "2023-10-23T13:55:01.543Z",
"client_ip": "172.21.3.15",
"message": "Connected to 10.1.0.1",
"event_duration": 1756467
}
],
)
print(resp1) response = client.indices.create(
index: 'sample_data',
body: {
mappings: {
properties: {
client_ip: {
type: 'ip'
},
message: {
type: 'keyword'
}
}
}
}
)
puts response
response = client.bulk(
index: 'sample_data',
body: [
{
index: {}
},
{
"@timestamp": '2023-10-23T12:15:03.360Z',
client_ip: '172.21.2.162',
message: 'Connected to 10.1.0.3',
event_duration: 3_450_233
},
{
index: {}
},
{
"@timestamp": '2023-10-23T12:27:28.948Z',
client_ip: '172.21.2.113',
message: 'Connected to 10.1.0.2',
event_duration: 2_764_889
},
{
index: {}
},
{
"@timestamp": '2023-10-23T13:33:34.937Z',
client_ip: '172.21.0.5',
message: 'Disconnected',
event_duration: 1_232_382
},
{
index: {}
},
{
"@timestamp": '2023-10-23T13:51:54.732Z',
client_ip: '172.21.3.15',
message: 'Connection error',
event_duration: 725_448
},
{
index: {}
},
{
"@timestamp": '2023-10-23T13:52:55.015Z',
client_ip: '172.21.3.15',
message: 'Connection error',
event_duration: 8_268_153
},
{
index: {}
},
{
"@timestamp": '2023-10-23T13:53:55.832Z',
client_ip: '172.21.3.15',
message: 'Connection error',
event_duration: 5_033_755
},
{
index: {}
},
{
"@timestamp": '2023-10-23T13:55:01.543Z',
client_ip: '172.21.3.15',
message: 'Connected to 10.1.0.1',
event_duration: 1_756_467
}
]
)
puts response const response = await client.indices.create({
index: "sample_data",
mappings: {
properties: {
client_ip: {
type: "ip",
},
message: {
type: "keyword",
},
},
},
});
console.log(response);
const response1 = await client.bulk({
index: "sample_data",
operations: [
{
index: {},
},
{
"@timestamp": "2023-10-23T12:15:03.360Z",
client_ip: "172.21.2.162",
message: "Connected to 10.1.0.3",
event_duration: 3450233,
},
{
index: {},
},
{
"@timestamp": "2023-10-23T12:27:28.948Z",
client_ip: "172.21.2.113",
message: "Connected to 10.1.0.2",
event_duration: 2764889,
},
{
index: {},
},
{
"@timestamp": "2023-10-23T13:33:34.937Z",
client_ip: "172.21.0.5",
message: "Disconnected",
event_duration: 1232382,
},
{
index: {},
},
{
"@timestamp": "2023-10-23T13:51:54.732Z",
client_ip: "172.21.3.15",
message: "Connection error",
event_duration: 725448,
},
{
index: {},
},
{
"@timestamp": "2023-10-23T13:52:55.015Z",
client_ip: "172.21.3.15",
message: "Connection error",
event_duration: 8268153,
},
{
index: {},
},
{
"@timestamp": "2023-10-23T13:53:55.832Z",
client_ip: "172.21.3.15",
message: "Connection error",
event_duration: 5033755,
},
{
index: {},
},
{
"@timestamp": "2023-10-23T13:55:01.543Z",
client_ip: "172.21.3.15",
message: "Connected to 10.1.0.1",
event_duration: 1756467,
},
],
});
console.log(response1); PUT sample_data
{
"mappings": {
"properties": {
"client_ip": {
"type": "ip"
},
"message": {
"type": "keyword"
}
}
}
}
PUT sample_data/_bulk
{"index": {}}
{"@timestamp": "2023-10-23T12:15:03.360Z", "client_ip": "172.21.2.162", "message": "Connected to 10.1.0.3", "event_duration": 3450233}
{"index": {}}
{"@timestamp": "2023-10-23T12:27:28.948Z", "client_ip": "172.21.2.113", "message": "Connected to 10.1.0.2", "event_duration": 2764889}
{"index": {}}
{"@timestamp": "2023-10-23T13:33:34.937Z", "client_ip": "172.21.0.5", "message": "Disconnected", "event_duration": 1232382}
{"index": {}}
{"@timestamp": "2023-10-23T13:51:54.732Z", "client_ip": "172.21.3.15", "message": "Connection error", "event_duration": 725448}
{"index": {}}
{"@timestamp": "2023-10-23T13:52:55.015Z", "client_ip": "172.21.3.15", "message": "Connection error", "event_duration": 8268153}
{"index": {}}
{"@timestamp": "2023-10-23T13:53:55.832Z", "client_ip": "172.21.3.15", "message": "Connection error", "event_duration": 5033755}
{"index": {}}
{"@timestamp": "2023-10-23T13:55:01.543Z", "client_ip": "172.21.3.15", "message": "Connected to 10.1.0.1", "event_duration": 1756467} Набор данных, используемый в этом руководстве, предварительно загружен в публичную демонстрационную среду ES|QL от Elastic. Перейдите по ссылке ela.st/ql, чтобы начать работу.
Запуск запроса ES|QL
В Kibana вы можете использовать Консоль или Discover для запуска запросов ES|QL:
Чтобы начать работу с ES|QL в Консоли, откройте главное меню и выберите Инструменты разработчика.
Общая структура запроса ES|QL — это:
POST /_query?format=txt
{
"query": """
"""
} Введите фактический запрос ES|QL между двумя наборами тройных кавычек. Например:
POST /_query?format=txt
{
"query": """
FROM sample_data
"""
} Чтобы начать работу с ES|QL в Discover, откройте главное меню и выберите Discover. Далее выберите Попробовать ES|QL из строки меню приложения.
Отрегулируйте фильтр времени так, чтобы он включал временные метки в примере данных (23 октября 2023 года).
После переключения в режим ES|QL строка запроса отображает пример запроса. Вы можете заменить этот запрос запросами из этого руководства по началу работы.
Для облегчения написания запросов автодополнение предлагает варианты с возможными командами и функциями:
Вы можете настроить высоту редактора, перетащив его нижнюю границу.
Ваш первый запрос ES|QL
Каждый запрос ES|QL начинается с команды источника. Команда источника генерирует таблицу, как правило, с данными из Elasticsearch.
Команда FROM возвращает таблицу с документами из потока данных, индекса или псевдонима. Каждая строка в результирующей таблице представляет собой документ. Этот запрос возвращает до 1000 документов из индекса sample_data:
FROM sample_data
Каждый столбец соответствует полю и может быть доступен по имени этого поля.
Ключевые слова ES|QL регистронезависимы. Следующий запрос идентичен предыдущему:
from sample_data
Команды обработки
Команда источника может быть дополнена одной или несколькими командами обработки, разделенными символом "|" (pipe): |. Команды обработки изменяют входную таблицу, добавляя, удаляя или изменяя строки и столбцы. Команды обработки могут выполнять фильтрацию, проекцию, агрегацию и многое другое.
Например, вы можете использовать команду LIMIT, чтобы ограничить количество возвращаемых строк, максимум до 10 000 строк:
FROM sample_data | LIMIT 3
Для лучшей читаемости вы можете поместить каждую команду на отдельную строку. Однако это необязательно. Следующий запрос идентичен предыдущему:
FROM sample_data | LIMIT 3
Сортировка таблицы
Еще одной командой обработки является команда SORT. По умолчанию строки, возвращаемые FROM, не имеют определенного порядка сортировки. Используйте команду SORT, чтобы отсортировать строки по одному или нескольким столбцам:
FROM sample_data | SORT @timestamp DESC
Запрос данных
Используйте команду WHERE для запроса данных. Например, чтобы найти все события с продолжительностью более 5 мс:
FROM sample_data | WHERE event_duration > 5000000
WHERE поддерживает несколько операторов. Например, вы можете использовать LIKE, чтобы выполнить запрос с подстановкой по столбцу message:
FROM sample_data | WHERE message LIKE "Connected*"
Дополнительные команды обработки
Существует много других команд обработки, таких как KEEP и DROP для сохранения или удаления столбцов, ENRICH для обогащения таблицы данными из индексов в Elasticsearch, а также DISSECT и GROK для обработки данных. Обратитесь к командам обработки для обзора всех команд обработки.
Цепочки команд обработки
Вы можете объединять команды обработки, разделяя их символом "|": |. Каждая команда обработки работает с выходной таблицей предыдущей команды. Результатом запроса является таблица, созданная последней командой обработки.
В следующем примере сначала сортируется таблица по @timestamp, а затем результат ограничивается 3 строками:
FROM sample_data | SORT @timestamp DESC | LIMIT 3
Порядок команд обработки важен. Сначала ограничение результата 3 строками, а затем сортировка этих 3 строк, скорее всего, приведет к результату, отличающемуся от примера, где сортировка выполняется до ограничения.
Вычисление значений
Используйте команду EVAL для добавления столбцов в таблицу с вычисленными значениями. Например, следующий запрос добавляет столбец duration_ms. Значения в столбце вычисляются путем деления event_duration на 1 000 000. Другими словами: event_duration преобразуется из наносекунд в миллисекунды.
FROM sample_data | EVAL duration_ms = event_duration/1000000.0
EVAL поддерживает несколько функций. Например, чтобы округлить число до ближайшего числа с заданным количеством знаков, используйте функцию ROUND:
FROM sample_data | EVAL duration_ms = ROUND(event_duration/1000000.0, 1)
Вычисление статистики
ES|QL можно использовать не только для запроса данных, но и для агрегации данных. Используйте команду STATS для вычисления статистики. Например, медианной продолжительности:
FROM sample_data | STATS median_duration = MEDIAN(event_duration)
Вы можете вычислить несколько статистик одной командой:
FROM sample_data | STATS median_duration = MEDIAN(event_duration), max_duration = MAX(event_duration)
Используйте BY для группировки вычисленных статистик по одному или нескольким столбцам. Например, для вычисления медианной продолжительности по IP-адресу клиента:
FROM sample_data | STATS median_duration = MEDIAN(event_duration) BY client_ip
Доступ к столбцам
Вы можете получить доступ к столбцам по их имени. Если имя содержит специальные символы, нужно использовать кавычки с обратными апострофами (`).
Присвоение явного имени столбцу, созданному с помощью EVAL или STATS, является необязательным. Если вы не укажете имя, новое имя столбца будет равно выражению функции. Например:
FROM sample_data | EVAL event_duration/1000000.0
В этом запросе EVAL добавляет новый столбец под названием event_duration/1000000.0. Поскольку его имя содержит специальные символы, для доступа к этому столбцу нужно использовать кавычки:
FROM sample_data | EVAL event_duration/1000000.0 | STATS MEDIAN(`event_duration/1000000.0`)
Создание гистограммы
Для отслеживания статистики во времени ES|QL позволяет создавать гистограммы с использованием функции BUCKET. BUCKET создает удобные для восприятия размеры ведер и возвращает значение для каждой строки, соответствующее ведру, в которое попадает эта строка.
Комбинируйте BUCKET с STATS для создания гистограммы. Например, для подсчета количества событий в час:
FROM sample_data | STATS c = COUNT(*) BY bucket = BUCKET(@timestamp, 24, "2023-10-23T00:00:00Z", "2023-10-23T23:59:59Z")
Или медианной продолжительности в час:
FROM sample_data | KEEP @timestamp, event_duration | STATS median_duration = MEDIAN(event_duration) BY bucket = BUCKET(@timestamp, 24, "2023-10-23T00:00:00Z", "2023-10-23T23:59:59Z")
Обогащение данных
ES|QL позволяет обогатить таблицу данными из индексов в Elasticsearch, используя команду ENRICH.
Прежде чем вы сможете использовать ENRICH, вам сначала необходимо создать и выполнить политику обогащения.
Следующие запросы создают и выполняют политику под названием clientip_policy. Политика связывает IP-адрес со средой ("Разработка", "QA" или "Производство"):
resp = client.indices.create(
index="clientips",
mappings={
"properties": {
"client_ip": {
"type": "keyword"
},
"env": {
"type": "keyword"
}
}
},
)
print(resp)
resp1 = client.bulk(
index="clientips",
operations=[
{
"index": {}
},
{
"client_ip": "172.21.0.5",
"env": "Development"
},
{
"index": {}
},
{
"client_ip": "172.21.2.113",
"env": "QA"
},
{
"index": {}
},
{
"client_ip": "172.21.2.162",
"env": "QA"
},
{
"index": {}
},
{
"client_ip": "172.21.3.15",
"env": "Production"
},
{
"index": {}
},
{
"client_ip": "172.21.3.16",
"env": "Production"
}
],
)
print(resp1)
resp2 = client.enrich.put_policy(
name="clientip_policy",
match={
"indices": "clientips",
"match_field": "client_ip",
"enrich_fields": [
"env"
]
},
)
print(resp2)
resp3 = client.enrich.execute_policy(
name="clientip_policy",
wait_for_completion=False,
)
print(resp3) response = client.indices.create(
index: 'clientips',
body: {
mappings: {
properties: {
client_ip: {
type: 'keyword'
},
env: {
type: 'keyword'
}
}
}
}
)
puts response
response = client.bulk(
index: 'clientips',
body: [
{
index: {}
},
{
client_ip: '172.21.0.5',
env: 'Development'
},
{
index: {}
},
{
client_ip: '172.21.2.113',
env: 'QA'
},
{
index: {}
},
{
client_ip: '172.21.2.162',
env: 'QA'
},
{
index: {}
},
{
client_ip: '172.21.3.15',
env: 'Production'
},
{
index: {}
},
{
client_ip: '172.21.3.16',
env: 'Production'
}
]
)
puts response
response = client.enrich.put_policy(
name: 'clientip_policy',
body: {
match: {
indices: 'clientips',
match_field: 'client_ip',
enrich_fields: [
'env'
]
}
}
)
puts response
response = client.enrich.execute_policy(
name: 'clientip_policy',
wait_for_completion: false
)
puts response const response = await client.indices.create({
index: "clientips",
mappings: {
properties: {
client_ip: {
type: "keyword",
},
env: {
type: "keyword",
},
},
},
});
console.log(response);
const response1 = await client.bulk({
index: "clientips",
operations: [
{
index: {},
},
{
client_ip: "172.21.0.5",
env: "Development",
},
{
index: {},
},
{
client_ip: "172.21.2.113",
env: "QA",
},
{
index: {},
},
{
client_ip: "172.21.2.162",
env: "QA",
},
{
index: {},
},
{
client_ip: "172.21.3.15",
env: "Production",
},
{
index: {},
},
{
client_ip: "172.21.3.16",
env: "Production",
},
],
});
console.log(response1);
const response2 = await client.enrich.putPolicy({
name: "clientip_policy",
match: {
indices: "clientips",
match_field: "client_ip",
enrich_fields: ["env"],
},
});
console.log(response2);
const response3 = await client.enrich.executePolicy({
name: "clientip_policy",
wait_for_completion: "false",
});
console.log(response3); PUT clientips
{
"mappings": {
"properties": {
"client_ip": {
"type": "keyword"
},
"env": {
"type": "keyword"
}
}
}
}
PUT clientips/_bulk
{ "index" : {}}
{ "client_ip": "172.21.0.5", "env": "Development" }
{ "index" : {}}
{ "client_ip": "172.21.2.113", "env": "QA" }
{ "index" : {}}
{ "client_ip": "172.21.2.162", "env": "QA" }
{ "index" : {}}
{ "client_ip": "172.21.3.15", "env": "Production" }
{ "index" : {}}
{ "client_ip": "172.21.3.16", "env": "Production" }
PUT /_enrich/policy/clientip_policy
{
"match": {
"indices": "clientips",
"match_field": "client_ip",
"enrich_fields": ["env"]
}
}
PUT /_enrich/policy/clientip_policy/_execute?wait_for_completion=false В демо-среде по адресу ela.st/ql уже создана и выполнена политика обогащения под названием clientip_policy. Политика связывает IP-адрес со средой ("Разработка", "QA" или "Производство").
После создания и выполнения политики вы можете использовать её с командой ENRICH:
FROM sample_data | KEEP @timestamp, client_ip, event_duration | EVAL client_ip = TO_STRING(client_ip) | ENRICH clientip_policy ON client_ip WITH env
Вы можете использовать новый столбец env, добавленный командой ENRICH, в последующих командах. Например, чтобы вычислить медианную продолжительность по каждой среде:
FROM sample_data | KEEP @timestamp, client_ip, event_duration | EVAL client_ip = TO_STRING(client_ip) | ENRICH clientip_policy ON client_ip WITH env | STATS median_duration = MEDIAN(event_duration) BY env
Для получения дополнительной информации об обогащении данных с помощью ES|QL, обратитесь к разделу Обогащение данных.
Обработка данных
Ваши данные могут содержать неструктурированные строки, которые вы хотите структурировать, чтобы упростить анализ данных. Например, пример данных содержит сообщения журнала, такие как:
"Connected to 10.1.0.3"
Извлекая IP-адрес из этих сообщений, вы можете определить, какой IP-адрес принял наибольшее количество подключений клиентов.
Для структурирования неструктурированных строк во время запроса вы можете использовать команды ES|QL DISSECT и GROK. DISSECT работает, разбивая строку с использованием шаблона на основе разделителя. GROK работает аналогично, но использует регулярные выражения. Это делает GROK более мощным, но, как правило, также медленнее.
В этом случае регулярные выражения не нужны, так как шаблон message простой: "Connected to ", за которым следует IP-адрес сервера. Чтобы соответствовать этой строке, можно использовать следующую команду DISSECT:
FROM sample_data
| DISSECT message "Connected to %{server_ip}" Это добавляет столбец server_ip к строкам, у которых message соответствует этому шаблону. Для других строк значение server_ip равно null.
Вы можете использовать новый столбец server_ip, добавленный командой DISSECT, в последующих командах. Например, чтобы определить, сколько подключений принял каждый сервер:
FROM sample_data
| WHERE STARTS_WITH(message, "Connected to")
| DISSECT message "Connected to %{server_ip}"
| STATS COUNT(*) BY server_ip Для получения дополнительной информации об обработке данных с помощью ES|QL, обратитесь к разделу Обработка данных с помощью DISSECT и GROK.
Дополнительная информация
Для получения дополнительной информации об ES|QL, обратитесь к Справочнику по ES|QL и Использование ES|QL.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/esql-getting-started.html