Эта статья является одиннадцатой в серии статей об анализе исходного кода elasticsearch. В этой статье начинается объяснение операции индексации. В следующих нескольких статьях мы продолжим обсуждение серии материалов, таких как создание документов, извлечение, обновление, удаление и контроль версий.
Документация
Сущность в системе хранения ElasticSearch называется документом, document. Если вы используете аналогию с реляционной базой данных, документ эквивалентен строке записей в базе данных. Документы в ElasticSearch имеют функцию, согласно которой одно и то же поле должно быть одного типа, то есть все документы, содержащие поле заголовка, должны иметь один и тот же тип поля заголовка, строковый или целочисленный.
Документ состоит из нескольких полей, каждое из которых может быть текстовым, числовым, датовым или сложным, например массивом строк. Тип поля очень важен в ElasticSearch, он связан с информацией о том, как выполняются различные операции анализа и сортировки. Elastic официально рекомендует использовать Mapping для изменения типа поля. В отличие от реляционных баз данных, ElasticSearch не обязательно должен иметь фиксированную структуру, каждый документ может иметь разные поля, и при разработке программы нет необходимости определять, какие поля существуют.
вид документа
В ElasticSearch типы документов позволяют программистам легко различать разные объекты в одном индексе. Каждый документ может иметь различную структуру, но в реальной производственной среде мы рекомендуем детализировать типы в документе, что очень поможет в дальнейшей разработке.
Сопоставление типов документов
Упомянутое выше сопоставление относится к тому факту, что ElasticSearch хранит информацию о полях в сопоставлении, этот тип информации является сопоставлением сопоставления. Каждый тип документа имеет собственное сопоставление, даже если оно не определено заранее при инициализации. В контенте, связанном с полнотекстовым поиском и инвертированным индексом, будет происходить процесс анализа документа, при этом каждое поле должно быть проанализировано по разным типам. Например, анализ числовых полей и текстовых полей должен быть разными процессами анализа, а анализ чисел не должен анализироваться в алфавитном порядке.
Используйте ResultAPI ElasticSearch для создания нового документа.
В ElasticSearch все документы являются данными, и все данные имеют определенные индексы и типы. Теперь давайте создадим документ с более распространенным примером:
Описанная выше операция означает, что мы создаемarticleиндекс и имяcomputerтип, идентификатор документа1.
Если все пойдет хорошо, этот способ создания RESTful API вернет ответ JSON, аналогичный следующему выводу:
Предыдущий ответ содержит информацию о статусе операции, показывает, где находится созданный документ, а также содержит уникальный идентификатор документа **_idи текущая версия_информация о версии. Он автоматически увеличивается с каждой новой версией ElasticSearch.
И когда ElasticSearch создает документ, если идентификатор документа не указан, идентификатор документа будет создан автоматически.
Как это делается? Мы объясним это с точки зрения исходного кода в следующем разделе.
Как создать новый документ в исходном коде ElasticSearch
В процессе создания узла, описанном в предыдущей статье, загружается модуль ActionModule.Этот модуль является модулем, который получает запрос RESTful, отправленный клиентом.ActionModule загружается следующим образом:
ActionModule actionModule = new ActionModule(false, settings, clusterModule.getIndexNameExpressionResolver(), settingsModule.getIndexScopedSettings(), settingsModule.getClusterSettings(), settingsModule.getSettingsFilter(), threadPool, pluginsService.filterPlugins(ActionPlugin.class), client, circuitBreakerService, usageService);
После загрузки ActionModule обработчик HTTP будет инициализирован с помощью метода ActionModule **initRestHandlers()**.Этот обработчик может анализировать запрос RESTful, отправленный клиентом в кластер ElasticSearch по протоколу http.
нагрузкаRestIndexActionобработчик индекса,
registerHandler.accept(new RestIndexAction(settings, restController))
Как показано на рисунке ниже, зарегистрируйте разные пути обработчика REST для разных соответствующих запросов.
Вы можете видеть, что в соответствующем пути контроллера есть индекс, тип и идентификатор, Если идентификатор не указан, идентификатор будет создан автоматически, и для отправки запроса необходимо использовать метод POST без указания идентификатора.
Поскольку нижний уровень контроллера в ElasticSearch реализуется Netty. Таким образом, после привязки порта Netty4HttpChannel будет прослушивать HTTP-запросы, полученные портом. После того, как контроллер ElasticSearch получит запрос, перенаправленный Netty4HttpChannel, он вызоветRestIndexActionметод вprepareRequest(). Метод возвращаетRestChannelConsumerэкземпляр типа, который является виртуальным классомBaseRestHandlerФункциональный интерфейс в . Читая метод, определенный этим интерфейсом, вы можете узнать, что запросы REST в ElasticSearch обрабатываются путем подготовки потребителя канала (потребителя канала), который представляет выполнение запроса канала.
Начать строительство после получения запросаIndexRequest, роль этого экземпляра заключается в преобразовании документа типа JSON в специальный и доступный для поиска индекс.
IndexRequestвернись первымRestRequestТри параметра, которые необходимы для создания экземпляра в :
- index: индекс документа
- тип: тип документа
- id: идентификатор, указанный документом
Затем получите по очереди дополнительные параметры:
- маршрутизация: контролирует запросы маршрутизации осколков. Используйте это значение для хеширования осколка, а не идентификатора.
- parent: Установите родительский идентификатор документа.
- конвейер: настройте конвейер загрузки перед выполнением индексного документа.
- источник: устанавливает байтовую форму индекса документа.
- тайм-аут: тайм-аут
- Refresh: анализ политики обновления.
- version_type: установить тип версии
- op_type: строка, используемая для указания, являются ли это данными индекса или новыми данными
Детали параметра следующие:
Эти параметры представляют собой все данные, которые NodeClient необходимо использовать при индексировании документов. NodeClient загружается при инициализации Node. Это симулированный клиент, используемый для выполнения операций на локальном узле.
методprepareRequestпоследнее возвращениеchannel -> client.index(indexRequest, new RestStatusToXContentListener<>(channel, r -> r.getLocation(indexRequest.routing())))
, потому что метод должен возвращатьRestChannelConsumerВозвращаемое значение типа, поэтому оно переписано в удобную для понимания кодовую версию версии jdk7, как показано ниже:
Самое главное в этом кодеNodeClientМетод index(), ключ к этому методу заключается в создании новогоTask,этоTaskСодержит идентификатор, тип, действие, описание, parentTask, startTime и другую информацию.
Эта задача будет удалена в более старых версияхTransportIndexActionобработки, но после версии 6.0TransportBulkActionзаменилTransportIndexAction. задача будет передана как параметрTransportBulkActionВ методе doExecute двумя другими параметрами являются BulkRequest и ActionListener.
void doExecute(Task task, BulkRequest bulkRequest, ActionListener<BulkResponse> listener)
BulkRequest содержит информацию, хранящуюся в документе, а ActionListener используется для отслеживания ответа или отказа действия для операций обратного вызова.
doExecuteМетод в основном делает следующее:
- Собрать все индексы в запросе
- Отфильтруйте несуществующие индексы при построении карты индексов, которую мы не смогли создать. Оценка несуществующих индексов и индексов, которые невозможно создать, в основном зависит от того, имеет ли индекс псевдоним.
- Если отсутствуют индексы, создайте все недостающие индексы. Обратите внимание, что пакетная обработка данных начинается после завершения всех операций создания.
затем выполнитьTransportBulkActionКатегорияexecuteBulkспособ завершения посадки данных.