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