Что делать, если вы хотите использовать SQL-запросы к Elasticsearch, но не купили X-Pack и у вас нет доступа к Elasticsearch SQL?
Вариант первый: смириться и продолжить писать REST-запросы
Вариант второй: использовать специальную библиотеку для SQL-доступа к Elasticsearch. Например, CData Elasticsearch Driver. Она существует в множестве вариантов и позволяет получить доступ к данным в Elasticsearch из любых средств разработки и программ (FireDAC Components, ADO.NET Provider, ODBC Driver, JDBC Driver, Power BI Connectors, BizTalk Adapter, PowerShell Cmdlets, Excel Add-In, Anypoint Connectors, SSIS Component).
Рассмотрим использование CData FireDAC Components for Elasticsearch в Delphi.
1. Подготовка Elasticsearch
1.1. Создадим индекс "sql_test" и сразу смаппируем поля
PUT http://localhost:9200/sql_test { "mappings": { "properties": { "name": { "type": "text" }, "address": { "type": "object", "properties": { "street": { "type": "text" }, "city": { "type": "text" }, "state": { "type": "text" } } }, "insured_ages": { "type": "integer" } } } }
1.2. Добавим в индекс "sql_test" тестовые данные
POST http://localhost:9200/sql_test/_doc { "name": "John Smith", "address": { "street": "Main Street", "city": "Chapel Hill", "state": "NC" }, "insured_ages": [ 17, 43, 45 ] } POST http://localhost:9200/sql_test/_doc { "name": "Joseph Newman", "address": { "street": "Oak Street", "city": "Raleigh", "state": "NC" }, "insured_ages": [ 23, 25 ] } POST http://localhost:9200/sql_test/_doc { "name": "John Second", "address": { "street": "Second Street", "city": "Chapel Hill", "state": "NC" }, "insured_ages": [ 77, 33, 44 ] }
Маппинг полей в индексе и данные позаимствованы из документации библиотеки CData FireDAC Components for Elasticsearch.
2. Подготовка тестовой программы
2.1. Создадим тестовое VCL-приложение, на главную форму которого добавим: объекты FireDAC (TFDConnection и TFDQuery) и контролы для интерфейса (TMemo - для ввода SQL-запроса, TDBGrid для отображения результатов SQL-запроса и 2 TCheckBox для параметров подключения):
2.2. Настроем подключение нашего приложения к серверу Elasticsearch. Для этого необходимо задать FDConnection всего несколько свойств. Нагляднее это сделать через диалог "FireDAC Connection Editor".
Для начала в свойстве "DriverName" выберем драйвер "CData.Elasticsearch" (на диалоге для этого есть combobox "Driver Id"). Затем укажем адрес сервера Elasticsearch (свойство "Server") и его порт (свойство "Port"). У меня локальный сервер, поэтому я прописал "localhost", а порт оставил без изменения - 9200. Если у вас все-таки куплен X-Pack, то вам для подключения к серверу Elasticsearch придется настроить еще параметры аутентификации (если она включена).
2.3. На нажатие кнопки "btnOpen" добавим обработчик, который будет выполнять наш запрос:
О параметрах подключения "FlattenObjects" и "FlattenArrays" я расскажу позже.procedure TMain.btnOpenClick(Sender: TObject); begin FDConnection.Params.Values['FlattenObjects'] := BoolToStr(cbFlattenObjects.Checked, True); FDConnection.Params.Values['FlattenArrays'] := IfThen(cbFlattenArrays.Checked, '3', ''); FDQuery.Open(Memo.Text); DBGridEh.OptimizeAllColsWidth; end;
3. SQL-запросы к Elasticsearch
CData Elasticsearch Driver рассматривает индекс Elasticsearch как таблицу. Поэтому для начала выполним простой запрос:
"Это просто праздник какой-то!" Вместо JSON из результатов REST-запроса к Elasticsearch мы получаем DataSet, который более привычен и прост в обработке.
Установим checkbox "FlattenObjects" и выполним запрос:
Как вы видите, поле "address" типа "object" с JSON-записью разделилось на три поля: "address.street", "address.city" и "address.state". Т.е. если параметр подключения FlattenObjects=True, то ключи вложенных объектов возвращаются в виде отдельных полей.
Теперь установим checkbox "FlattenArrays=3" и выполним запрос:
В DataSet добавились поля с элементами массива из поля "insured_ages". По умолчанию массивы возвращаются в виде строки JSON-массива. Но параметру подключения FlattenArrays можно задать количество элементов массива, которое нужно вернуть в качестве отдельных полей. У меня в примере FlattenArrays=3. Если при подключении установить FlattenObjects=True и задать FlattenArrays, то объекты, вложенные в элементы массива, также верутся в виде отдельных полей.
SQL-синтаксис у CData Elasticsearch Driver представляет собой микс из различных SQL-диалектов. Например, заметно влияние синтаксиса SQLServer, что позволяет написать запрос с TOP и квадратными скобками:
Обратите внимание, я обратился к элементу типа "object" (address.street) без включенного параметра "FlattenObjects".
CData Elasticsearch Driver предоставляет программисту большой выбор функций для обработки содержимого полей в SQL-запросе и составления условия выборки данных: Aggregate, JOIN, Date, Literal, Predicate, SQL, DATE, MATH, STRING, ORDER BY.
Например, агрегатные функции. Найдем максимальное значение среди элементов массива "insured_ages" во всем индексе:
или посчитаем сумму минимальных значений массива каждого документа в индексе:
А теперь замиксуем функции разного типа в одном запросе:
Как вы видите, в этом запросе функции: для работы с датой, для работы со строками, для обработки JSON и математические функции.
Поиск документов может производиться разным способом. Как стандартными возможностями SQL:
Так и с использованием специальных "predicate" функций:
Predicate функции, так же, что очень важно, позволяют эмулировать NoSQL-поиск Elasticsearch. Например, запрос:
соответствует POST-запросу к Elasticsearch:
Мои первые впечатления: CData FireDAC Components for Elasticsearch - это очень круто! Возможно даже, что реализованный в CData Elasticsearch Driver механизм SQL-запросов к Elasticsearch удобнее стандартного "Elasticsearch SQL" из X-Pack. Но все же ему не хватает ряда возможностей, которые реализуются с помощью REST-запросов. Поэтому ощутить всю мощь поисковых возможностей Elasticsearch, можно только через REST-запросы.
Комментариев нет:
Отправить комментарий