Статьи

Elasticsearch SQL

Двигатель Elasticsearch

Elasticsearch является одной из наиболее широко поисковых систем, используемых сегодня в ряде производственных развертываний. Она основана на поисковой библиотеке Lucene, и одной из ключевых функций, которую она предоставляет, является DSL-запрос на основе JSON поверх Lucene, который предоставляет более простой в использовании механизм взаимодействия с поисковой системой. Однако запрос DSL очень специфичен для Elasticsearch. Поддержка SQL, представленная в Elasticsearch 6.3, привела к стандартному механизму выполнения запросов к поисковой системе и сделала еще один шаг на пути к более легкому внедрению разработчиками, уже знакомыми с SQL. Хотя SQL изначально был разработан для использования с системами управления реляционными базами данных, он был реализован в широком спектре других систем (таких как базы данных NoSQL). Возьмем, к примеру, поддерживаемый SQL, предоставляемый в механизме распределенной обработки данных, таком как Apache Spark, или в системе вычислений на основе распределенного кэша, такой как Apache Ignite, где SQL является одним из основных средств запроса. В этой статье мы рассмотрим, как работает Elasticsearch SQL.

Предварительная настройка

Чтобы попробовать примеры из этой статьи, вам нужно запустить локальный экземпляр Elasticsearch (как минимум 6.3). В этой статье мы собираемся использовать последнюю версию Elasticsearch 7.5. Мы создадим индекс сообщений, который содержит сообщения из форума. Мы будем использовать Java-клиент Elasticsearch для подачи данных в индекс, и мы не собираемся предоставлять явное сопоставление для полей индекса (для простоты мы позволим Elasticsearch автоматически создавать его для нас). Сначала мы создадим проект Maven с зависимостью от клиента высокого уровня Java Elasticsearch (старый HTTP-клиент Elasticsearch устарел и планируется удалить в Elasticsearch 8.0):

1
2
3
4
5
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.5.0</version>
</dependency>

Мы создадим 10000 сгенерированных почтовых документов в индексе постов, используя следующий фрагмент кода:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")));
         
        String[] possibleUsers = new String[] {"Martin", "Jim", "John"};
        String[] possibleDates = new String[] {"2019-12-15", "2019-12-16", "2019-12-17"};
        String[] possibleMessages = new String[] {"Hello, Javaadvent !",
                "Cool set of blog posts. We want more !",
                "Elasticsearch SQL is great."};
         
        for(int i = 1; i <= 10000; i++) {
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("user", possibleUsers[ThreadLocalRandom.current().nextInt(0, 3)]);
            jsonMap.put("date", possibleDates[ThreadLocalRandom.current().nextInt(0, 3)]);
            jsonMap.put("message", possibleMessages[ThreadLocalRandom.current().nextInt(0, 3)]);
            IndexRequest request = new IndexRequest("posts")
                .id(String.valueOf(i)).source(jsonMap);
            client.index(request, RequestOptions.DEFAULT);
        }
         
        client.close();

Выполнение SQL-запросов

Мы можем использовать Kibana для запроса всех документов, где имя пользователя Martin, следующим образом:

1
2
3
4
POST /_sql?format=txt
{
    "query": "SELECT * FROM posts where user = 'Martin'"
}

Другим примером может быть подсчет всех документов, которые содержат слово Javaadvent в поле сообщения :

1
2
3
4
POST /_sql?format=txt
{
    "query": "SELECT count(*) FROM posts where message like '%Javaadvent%'"
}

Теперь, если вы хотите выполнить вышеупомянутые запросы в вашем Java-приложении, у вас есть несколько вариантов:

  • запустите его, используя драйвер Elasticsearch JDBC. Однако эта опция доступна только для платиновых и корпоративных подписок;
  • Клиент REST, вызывающий конечную точку SQL Elasticsearch. Этот вариант можно выбрать, если у вас есть только базовый (бесплатный) параметр Elasticsearch.

Вы можете использовать практически любой REST-клиент для Java, чтобы использовать второй вариант, но мы будем использовать низкоуровневый REST-клиент Elasticsearch:

1
2
3
4
5
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>7.5.0</version>
</dependency>

Следующий блок кода возвращает только 10 документов из индекса сообщений :

1
2
3
4
5
6
7
8
9
RestClient restClient = RestClient.builder(
                new HttpHost("localhost", 9200, "http")).build();
         
        Request request = new Request("POST""/_sql");
        request.setJsonEntity("{\"query\":\"SELECT * FROM posts limit 10\"}");
        Response response = restClient.performRequest(request);
        String responseBody = EntityUtils.toString(response.getEntity());
        System.out.println(responseBody);
        restClient.close();

Чтобы увидеть, как SQL-запрос выполняется за кулисами, вы можете использовать API перевода, предоставленный в конечной точке / _sql / translate. Мы можем запустить следующее в Kibana. Если мы хотим посмотреть, какой DSL-запрос сгенерирован для предыдущего SQL-запроса:

1
2
3
4
5
POST /_sql/translate
{
    "query": "SELECT * FROM posts limit 10",
    "fetch_size": 10
}

И мы должны получить результат, подобный следующему:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "size" : 10,
  "_source" : {
    "includes" : [
      "message",
      "user"
    ],
    "excludes" : [ ]
  },
  "docvalue_fields" : [
    {
      "field" : "date",
      "format" : "epoch_millis"
    }
  ],
  "sort" : [
    {
      "_doc" : {
        "order" : "asc"
      }
    }
  ]
}

Особенности Elasticsearch SQL

Мы продемонстрировали, как мы можем выполнять базовые запросы SQL. Механизм SQL Elasticsearch довольно богат и включает в себя:

  • ряд форматов ответа на запрос SQL, таких как csv, json, txt, yaml и другие;
  • применение дополнительной DSL-фильтрации запросов вместе с Elasticsearch SQL;
  • CLI, предоставляемый утилитойasticsearch -sql-cli, где вы можете напрямую выполнять SQL-запросы.

С точки зрения самой реализации SQL вы можете обратиться к поддерживаемым командам SQL и справочной документации по функциям и операторам SQL.

Вывод

В этой статье мы продемонстрировали, как использовать Elasticsearch SQL для взаимодействия с механизмом Elasticsearch. Есть большие шансы, что этот механизм станет более предпочтительным для использования, чем DSL-запрос на основе JSON. Однако Elasticsearch SQL не является заменой ему, а скорее построен на его основе и выполняет множество функций, предоставляемых поисковой системой.

Опубликовано на Java Code Geeks с разрешения Мартина Тошева, партнера нашей программы JCG . Смотреть оригинальную статью здесь: Elasticsearch SQL

Мнения, высказанные участниками Java Code Geeks, являются их собственными.