Облачная платформаAdvanced

Использование DSL для поиска

Язык статьи: Русский
Показать оригинал
Страница переведена автоматически и может содержать неточности. Рекомендуем сверяться с английской версией.

Когда необходимо взаимодействовать с кластером Elasticsearch для выполнения сложного полнотекстового поиска или анализа данных, язык предметной области (DSL) — ваш лучший выбор. Являясь основанным на JSON языком запросов, родным для Elasticsearch, DSL позволяет ясно и точно выражать сложную логику запросов, предоставляя при этом детальный контроль над тем, как выполняются запросы.

Что такое DSL?

Elasticsearch Query DSL — это JSON‑основанный язык запросов, определяющий структуру и семантику запросов поиска и извлечения данных. Он содержит два контекста:

  • Контекст запроса: В контексте запроса клаузула запроса отвечает на вопрос «Насколько хорошо этот документ соответствует этой клаузуле запроса?». Помимо определения того, соответствует ли документ, клаузула также вычисляет релевантный балл в поле метаданных _score. Пример такой клаузулы: match.
  • В контексте фильтра клаузула запроса отвечает на вопрос «Соответствует ли этот документ этой клаузуле запроса?». Ответ — простой Да или Нет. Баллы не вычисляются, но часто используемые фильтры автоматически кэшируются Elasticsearch для повышения производительности. Примеры таких запросов: term и range.

Запросы DSL обычно выполняются в Dev Tools Kibana. И тело запроса, и возвращаемая информация находятся в формате JSON.

В этой теме перечислены некоторые из наиболее часто используемых клаузул DSL‑запросов. Подробнее см. Query DSL.

Базовый запрос: match_all

Используйте match_all для сопоставления всех документов в индексе. Это эквивалентно SELECT * FROM table в SQL. Применяйте его, когда необходимо искать по всем документам.

Например, выполните следующую команду, чтобы сопоставить все документы в индексе test:

1
2
3
4
5
6GET /test/_search
{
"query": {
"match_all": {}
}
}

Составные запросы: объединение нескольких клаузул запроса

Используйте bool‑запрос с клаузулами, такими как must и filter, для построения составных условий запроса. Это аналогично клаузуле where в SQL. Применяйте этот запрос, когда необходимо задать несколько условий для фильтрации документов.

Например, выполните следующую команду, чтобы получить все документы, у которых статус — published и поле publish_date позже 2015-01-01 (условие фильтра), а заголовок или содержание содержат Search (условие поиска).

GET /_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "Search"
}
},
{
"match": {
"content": "search"
}
}
],
"filter": [
{
"term": {
"status": "published"
}
},
{
"range": {
"publish_date": {
"gte": "2015-01-01"
}
}
}
]
}
}
}

Различия между must и filter следующие:

  • must: Указывает условия, которым должны соответствовать документы. Эти условия влияют на оценку релевантности документов, и документы с более высокими оценками ранжируются выше в результатах.
  • filter: Также указывает условия, которым должны соответствовать документы, но эти условия не влияют на оценку релевантности. filter обычно более эффективен, чем must, что делает его более подходящим для фильтрации структурированных данных.

Для условий, не требующих оценки релевантности (например, статус, диапазон времени и категория), используйте filter для повышения производительности запросов.

Агрегации

Структура aggs (например, terms aggregation) используется для выполнения запросов агрегации. Она аналогична оператору Group by в SQL. Используйте её, когда необходимо группировать документы для расчёта метрик.

Например, выполните следующую команду, чтобы подсчитать, сколько раз разные заголовки встречаются в индексе test:

GET /test/_search
{
"aggs": {
"titles": {
"terms": {
"field": "title.keyword"
}
}
}
}

Причина использования title.keyword следующая:

  • Текстовые поля используются для полнотекстового поиска (они проходят токенизацию). Например, "Hello World" будет разбито на "hello" и "world". Если попытаться выполнить агрегацию непосредственно по текстовому полю, будет возвращена ошибка (Fielddata is disabled). Это происходит потому, что такая операция чрезвычайно требовательна к памяти.
  • Keyword fields используются для точного совпадения и агрегаций. Они сохраняют "Hello World" как единое значение.

По умолчанию кластер автоматически создаёт multi-fields для строк. Это означает, что title используется для поиска, а title.keyword — для агрегаций.