В Elasticsearch существует четыре категории типов данных, а именно: основные типы данных, сложные типы данных, гео-типы данных и специализированные типы данных, которые мы сейчас и рассмотрим. Не стесняйтесь пропустить эту статью и перейти к следующей, если вы уже знакомы с различными типами данных.
Основные типы данных
Первая категория, о которой я расскажу, - это основные типы данных, начиная со строк.
Строки
Неудивительно, что строковые поля принимают строковые значения. Этот тип данных можно разделить на полный текст и ключевые слова, о которых я сейчас и расскажу.
Строки - полный текст
Полнотекстовые поля обычно используются для текстового поиска по релевантности, например, при поиске товаров по названию. Эти поля анализируются, что означает, что данные проходят через анализатор для преобразования строк в список отдельных терминов. Это происходит до того, как данные попадают в индекс, и именно это позволяет Elasticsearch искать отдельные слова в полнотекстовом поле. Полнотекстовые поля не используются для сортировки и редко применяются для агрегирования.
Строки - Ключевые слова
Тип keywords используется для хранения точных значений, таких как теги, статусы и тому подобное. Точное строковое значение добавляется в индекс как один термин, поскольку поля ключевых слов не анализируются. Поля этого типа обычно используются для фильтрации, например, для поиска всех товаров, которые находятся в продаже. Они также часто используются для сортировки и агрегирования.
Числовой
Следующим основным типом данных является числовой тип данных. Как вы уже догадались, этот тип данных используется для хранения числовых значений, таких как целые, плавающие и двойные числа, например, 1 и 1,5. Числовой тип данных поддерживает следующие числовые типы.
- long (знаковое 64-битное целое число)
- integer (знаковое 32-битное целое число)
- short (знаковое 16-битное целое число)
- byte (знаковое 8-битное целое число)
- double (двойная точность 64-битной плавающей точки)
- float (32-битная плавающая точка одинарной точности)
Даты
В Elasticsearch также существует тип данных "дата". Даты могут быть либо строкой, содержащей форматированные даты (например, 2022-01-01 или 2022/01/01 12:00:00), либо целым числом, представляющим секунды с момента наступления эпохи, либо длинным числом, представляющим миллисекунды с момента наступления эпохи. Последнее является способом внутреннего хранения дат в Elasticsearch.
Даты - форматы
При работе с датами можно выбирать их форматы. Формат по умолчанию определяется как дата с необязательным временем или количеством миллисекунд с момента наступления эпохи. Он определяется следующим образом: strict_date_optional_time||epoch_millis. Ниже приведены примеры некоторых форматов по умолчанию, которые вы можете использовать при добавлении дат.
- 2022-01-01 (только дата)
- 2022-01-01T12:00:00Z (дата, включая время)
- 000 (миллисекунды с момента наступления эпохи)
Обратите внимание, что парсер дат по умолчанию поддерживает форматы, определенные стандартом ISO, поэтому эти примеры не являются единственными форматами, которые вы можете использовать. Тем не менее, я бы рекомендовал использовать их в качестве условного обозначения в вашем проекте. Если вы определяете свой собственный формат даты, то вы можете использовать различные постоянные значения, которые предоставляет Elasticsearch и которые действуют как заполнители при определении формата.
Булево
Если поле может содержать только значения on или off, то для него подходит тип данных boolean. Как и в JSON, булевы поля могут принимать значения true и false. Они также принимают строки и числа, которые будут интерпретированы как булевы. Я бы лично не рекомендовал этого делать, если только вам это не нужно по какой-то причине. Ложные значения включают булево значение false, строку со значением "false", "off", "no", "0" или пустую строку (""), или число 0. Все, что не интерпретируется как false, будет интерпретировано как true.
Двоичные данные
В поле можно также хранить двоичные данные, например, файл. Эти данные будут храниться в виде строки в кодировке Base64 и не будут доступны для поиска. Примером может служить строка aHR0cHM6Ly9nLXNvZnQuaW5mbw==.
Сложные типы данных
Далее мы обсудим сложные типы данных.
Объект
Документы JSON являются иерархическими, то есть объект может содержать внутренние объекты. В Elasticsearch они сглаживаются перед индексированием и хранятся в виде простых пар ключ/значение. Рассмотрим следующий пример.
1 2 3 4 5 6 | { "message": "Некоторый текст...", "customer.age": 22, "customer.address.city": "Москва", "customer.address.country": "Россия" } |
Если объект customer имеет свойство age, то это свойство будет храниться в поле с именем customer.age. То же самое относится и к вложенным объектам, как вы можете видеть на примере объекта address.
Массив
Часто вам может понадобиться хранить массив значений. Вы можете удивиться, узнав, что в Elasticsearch нет типа массива. Это связано с тем, что любое поле по умолчанию может содержать ноль или более значений, без необходимости явного определения этого. Это означает, что если просто передать полю массив значений, Elasticsearch автоматически сохранит эти значения, даже для поля, которое было отображено, например, как строка. Однако обратите внимание, что все значения в массиве должны быть одного типа данных. Если явное отображение не определяет тип данных, то Elasticsearch определит его на основе первого значения в массиве.
Ниже приведено несколько примеров добавления массивов в поле Elasticsearch.
- Массив строк: ["Elasticsearch", "Elastic"].
- Массив целых чисел: [1, 2].
- Массив массивов: [1, [2, 3]] - эквивалент [1, 2, 3].
- Массив объектов: [{ "name": "Ivan", "age": 32}, { "name": "Olga", "age": 21}]
Наиболее заметным является массив массивов, который сплющивается в один массив значений. Помимо простых типов данных, в массив можно добавлять сложные типы данных, например, объекты.
Массивы - объекты
Выше я показал вам пример массива объектов. Однако это работает не так, как вы ожидаете. Как я уже говорил минуту назад, Elasticsearch сплющивает иерархии объектов в пары ключ/значение, потому что Lucene не имеет концепции внутренних объектов, как в JSON. Это означает, что вы не можете запрашивать каждый объект независимо от других объектов в массиве. Пожалуйста, рассмотрите следующий пример.
1 | {users: [{ "name": "Ivan", "age": 32}, { "name": "Olga", "age": 21}] } |
Этот массив объектов хранится примерно так:
1 | { "users.name": ["Ivan", "Olga"], "users.age": [21, 32] } |
Массив содержит два объекта user со свойствами name и age. Когда этот массив хранится в Lucene, все значения для данного свойства в объектах добавляются в виде массива в одно поле - в данном случае в поля users.name и users.age. При этом теряются ассоциации между свойствами. В данном конкретном примере потеряна ассоциация между именем Ivan и возрастом 32, поскольку значения не отсортированы. Следствием этого является то, что поиск пользователя по имени Ivan, которому 32 лет, вернет неверные результаты. Хорошей новостью является то, что существует решение этой проблемы, если вам нужно иметь возможность выполнять такой поиск.
Вложенный
Решением вышеупомянутой проблемы является вложенный тип данных. Этот тип данных следует использовать, когда вам нужно проиндексировать массивы объектов и сохранить независимость каждого объекта. Это означает, что значения всех объектов не будут смешиваться вместе, как вы видели выше. Внутри массива каждый объект индексируется как отдельный скрытый документ. Результатом использования этого типа данных является то, что вы можете запрашивать конкретные объекты на основе значений их полей с помощью специального запроса под названием nested. Внутри Elasticsearch происходит то, что вложенные объекты запрашиваются так, как если бы они были проиндексированы как отдельные документы. Технически это действительно так, но на самом деле вам не нужно об этом знать.
Типы геоданных
Далее мы кратко рассмотрим некоторые типы данных geo, которые, как не удивительно, используются для хранения географических данных.
1 2 3 4 5 6 7 8 9 10 | PUT my-index-000001 { "mappings": { "properties": { "location": { "type": "geo_point" } } } } |
Геоточка
Тип данных geo-point используется для хранения пар широта-долгота и может применяться для поиска документов в радиусе от некоторых координат, сортировки по расстоянию от некоторых координат и т.д. Значения для поля geo-point могут быть добавлены в четырех различных форматах. Первый - в виде объекта со свойствами lat и lon.
1 2 3 4 5 6 | { "location": { "lat": 41.12, "lon": -71.34 } } |
Второй - в виде строки с широтой и долготой, разделенными запятой, и в таком порядке.
1 2 3 | { "location": "41.12,-71.34" } |
Третий вариант - это геохэш, который я не собираюсь объяснять дальше.
1 2 3 | { "location": "drm3btev3e86" } |
И четвертый способ - в виде массива.
1 2 3 | { "location": [-41.34,41.12] } |
Обратите внимание, что по сравнению с другими форматами, широта и долгота поменялись местами. Это сделано для соответствия формату GeoJSON.
Гео-форма
Поле геофигуры может содержать такие фигуры, как прямоугольники и многоугольники, и поэтому может быть использовано для построения сложных фигур. Поэтому этот тип данных следует использовать, когда геоточек недостаточно.
Геофигура может быть построена различными способами, некоторые из которых включают добавление ее в виде строки или многоугольника. Линейка - это массив из двух или более позиций, который, по сути, является массивом массивов. Если массив содержит только две позиции, то результатом будет прямая линия. Многоугольник также складывается как массив массивов, где каждый массив содержит точки. Важно отметить, что первая и последняя точки во внешнем массиве должны быть одинаковыми, что замыкает многоугольник.
Специализированные типы данных
Далее мы кратко обсудим некоторые специализированные типы данных, применение которых довольно узко.
IPv4
Первым из них является тип данных IPv4. Неудивительно, что он используется для сопоставления адресов IPv4. Elasticsearch хранит значения для поля IPv4 как длинные значения.
Завершение
Существует также тип данных, который используется для функции автозаполнения и называется completion. Это так называемый префиксный суггестор, и хотя он не исправляет орфографию, он полезен для предоставления пользователю предложений во время поиска, например, в Google. Для этого он хранит преобразователь конечных состояний как часть индекса, что обеспечивает очень быструю загрузку и выполнение. Однако, если вы знаете, когда использовать этот тип, то это не так важно.
Счетчик токенов
Тип данных token_count - это целочисленное поле, которое принимает строковые значения. Это может показаться странным, но все происходит так: строковые значения анализируются, и количество лексем в строках индексируется. В качестве примера можно привести случай, когда свойство name имеет поле length типа token_count. Затем можно выполнить поисковый запрос, чтобы найти людей, чье имя содержит заданное количество лексем, например, разделенных пробелом.
Вложение
Существует также тип данных Attachment, который позволяет Elasticsearch индексировать вложения для многих распространенных форматов, таких как файлы PDF, электронные таблицы, презентации PowerPoint и другие. Вложения хранятся в виде строки в кодировке Base64. Эта функция доступна в виде плагина, который должен быть установлен на всех узлах. Это легко сделать, введя приведенную ниже команду, при условии, что узел работает в среде Linux.
1 | sudo /path/to/elasticsearchbin/plugin install mapper-attachments |
Если вы установите этот плагин, то обратите внимание, что после завершения установки необходимо перезагрузить каждый узел.
Вот и все! Это был обзор наиболее важных типов данных в Elasticsearch, которые вам, скорее всего, понадобятся или с которыми вы столкнетесь.