Двигатель 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, являются их собственными.  |