Пакет esapi обеспечивает доступ к API-интерфейсам Elasticsearch через типы данных языка программирования Go. Например, чтобы проиндексировать документ, вы вызываете соответствующий метод на клиенте:
res, err := client.Index(
"my-index",
strings.NewReader(`{"title":"Test"}`),
client.Index.WithDocumentID("1"))
fmt.Println(res, err)
Пакет Go предоставляет тот же API, что и клиенты на других языках, обеспечивая единообразие взаимодействия с пользователем на разных языках программирования и облегчая общение в командах полиглотов. Следовательно, различные пространства имен API Elasticsearch доступны в качестве пространств имен на клиенте. Например, чтобы проверить работоспособность кластера, вы вызываете метод Cluster.Health() на клиенте; чтобы создать индекс, вы вызываете метод Indices.Create().
Метод возвращает esapi.Response и error. Ошибка возвращается всякий раз, когда запрос терпит неудачу; например, когда конечная точка недоступна или время ожидания запроса истекло. Тип esapi.Response - это легкая оболочка для *http.Response. Помимо отображения статуса ответа, заголовков и тела, он предоставляет несколько вспомогательных методов, таких как IsError(). Обратите внимание, что ответ 500 Internal Server Error по-прежнему является допустимым ответом, и поэтому в этом случае ошибка не возвращается - вызывающий код должен проверить статус ответа, чтобы правильно обработать ответ. Тип esapi.Response также реализует интерфейс fmt.Stringer, позволяющий печатать ответ во время разработки и отладки, как показано в примере выше.
Если вы присмотритесь, вы обнаружите, что вызов метода создает новый экземпляр структуры IndexRequest и вызывает его метод Do(). Вполне возможно создать экземпляр и вызвать метод самостоятельно - соответствующий код будет выглядеть так:
req := esapi.IndexRequest{
Index: "my-index",
DocumentID: "1",
Body: strings.NewReader(`{"title":"Test"}`),
}
req.Do(context.Background(), client)
Оба варианта функционально эквивалентны. API-интерфейс, ориентированный на методы, имеет незначительные накладные расходы, но также имеет определенные преимущества.
Во-первых, людям, возможно, легче читать и писать, поскольку поток кода более плавный, с более лаконичным именованием и более жестким интерфейсом.
Не менее важно, что он четко определяет, какие параметры API требуются (в приведенном выше примере это имя индекса и полезная нагрузка JSON), а какие - необязательные (идентификатор документа). Сравните с API Create(), который в сигнатуре метода дает понять, что требуется идентификатор документа:
$ go doc -short github.com/elastic/go-elasticsearch/v7/esapi.Create
type Create func(index string, id string, body io.Reader, o ...func(*CreateRequest)) (*Response, error)
...
Это особенно полезно для разработчиков, использующих автозавершение кода в своих IDE и редакторах.
Еще одно удобство, обеспечиваемое API-интерфейсом, ориентированным на методы, связано с параметрами, принимающими логические и числовые значения. Поскольку все типы имеют значение по умолчанию в Go, пакет не сможет определить, установлено ли значение false вызывающим кодом или это просто значение по умолчанию для типа bool; аналогичная проблема существует с типом int и значением 0. Это обычно решается в Go путем принятия указателя на значение в качестве аргумента, но это делает вызывающий код довольно многословным.
Следовательно, вместо того, чтобы объявлять переменную и передавать на нее указатель, вызывающий код может просто передать значение соответствующему методу, и он автоматически создаст указатель:
client.Reindex(
strings.NewReader(`{...}`),
client.Reindex.WithRequestsPerSecond(100),
client.Reindex.WaitForCompletion(true),
)
Примечание. Пакет объявляет вспомогательные функции esapi.BoolPtr() и esapi.IntPtr(), чтобы упростить использование полей, принимающих указатель, при прямом использовании структур запроса.
С более чем 300 различными, постоянно развивающимися API-интерфейсами Elasticsearch практически невозможно управлять базой кода вручную - единственный устойчивый режим обслуживания - это полностью сгенерированная база кода. К счастью, репозиторий Elasticsearch содержит исчерпывающую спецификацию для каждого API в виде набора документов JSON. Это основной инструмент для обеспечения согласованности между клиентами и для того, чтобы идти в ногу с эволюцией API Elasticsearch.
Генератор Go, который является частью набора внутренних пакетов, переводит определение API из JSON в исходный код Go, генерирует отдельные файлы, форматирует их с помощью gofmt и создает файл с типом esapi.API с "картой" всех API, используя отражение в Go. Затем этот тип встраивается в клиент.
Как отмечалось выше, одной из задач клиента Elasticsearch является отправка и получение данных, по умолчанию это полезная нагрузка JSON. Клиент Go представляет тело запроса и ответа просто как io.Reader, оставляя все кодирование и декодирование вызывающему коду. Для такой реализации есть несколько причин. Прежде всего, нет формальной спецификации для чрезвычайно изменчивой полезной нагрузки API, и поэтому о генерации кода не может быть и речи.
Примечание: предпринимаются многочисленные попытки улучшить эту ситуацию с целью сделать возможным создание полностью сгенерированного API, например, результатов поиска, компонентов Query DSL и т. д.
Другая причина связана с производительностью и расширяемостью. Оставляя кодирование и декодирование вызывающему коду, между ним и клиентом существует четкая граница, что упрощает рассуждения о производительности. Опытным путем кодирование и декодирование JSON имеет наибольшее влияние на производительность клиента, обычно выше, чем стоимость передачи по сети. Еще с одной точки зрения, передав кодирование и декодирование вызывающему коду, можно легко использовать сторонние пакеты JSON, которые в большинстве случаев значительно превосходят стандартную библиотеку. Чтобы увидеть примеры и тесты для различных пакетов JSON смотрите папку _examples/encoding в репозитории.
Примечание. Чтобы упростить передачу пользовательских полезных данных в API, клиент предоставляет тип esutil.JSONReader.
Читайте также:
- Клиент Go для Elasticsearch
- Клиент Go для Elasticsearch: пакет estransport
- Клиент Go для Elasticsearch: конфигурация и кастомизация
- Клиент Go для Elasticsearch: кодирование и декодирование полезной нагрузки JSON
- Клиент Go для Elasticsearch: массовая индексация
Комментариев нет:
Отправить комментарий