Перейти к основному содержимому

Типы индексов и маппинги

По умолчанию, seq-db не индексирует поля из записываемых данных, вместо этого есть специальный файл маппинга, в котором указаны индексируемые поля и используемые типы индексов.

Если же вам нужно автоматически индексировать все поля документа, то есть настройка mapping.path: auto, благодаря которой все поля документа будут проиндексированы как keyword тип.

Внимание: эта опция не подходит для продакшена (может резко увеличить размер индекса и стоимость запросов); используйте её только для демо и тестов.

Типы индексов

Ниже описаны типы индексов, поддерживаемые seq-db. На данный момент есть несколько видов индексов с разным поведением.

keyword тип

Тип поля keyword считает, что все значение поля это один токен, значение поля никак не разбивается на части. Обычно используется для таких данных как статусы, пространства имен, теги или любые другие данные, где при поиске нужно полное совпадение. Обратите внимание, что keyword индекс нужно использовать с осторожностью для высококардинальных полей, таких как идентификаторы трейсов и спанов или любые другие уникальные идентификаторы, потому что индексация высококардинальных полей способствует росту индекса.

Пример маппинга для поля с типом keyword:

mapping-list:
- name: level
type: keyword

path тип

Этот тип индексирует иерархические данные, такие как пути в файловой системе или url. Похож на path tokenizer в elasticsearch. Когда у поля тип path, во время индексации его значение разбивается на токены согласно иерархии поля.

Используется для поиска по началу пути или по полному пути. Например, все следующие документы будут удовлетворять запросу uri:"/my/path":

[
{"uri": "/my/path"},
{"uri": "/my/path/1"},
{"uri": "/my/path/1/"},
{"uri": "/my/path/1/one"}
]

Пример маппинга для path поля:

mapping-list:
- name: uri
type: path

text тип

Индекс для таких данных, где необходим полнотекстовый поиск: сообщения об ошибках или тела запросов. Этот тип индексирования используется для полей, содержащих неструктурированный текст на естественном языке, а также сообщения, написанные людьми, описания, сообщения об ошибках и другие текстовые поля в свободном виде.

Например, запрос message:"error" вернёт все документы, содержащие токен error. А запрос message:"error code" вернёт все документы, содержащие оба токена: error и code.

Пример маппинга текстового поля:

mapping-list:
- name: message
type: text

exists тип

Используется, когда важна наличие поля, а не его значение.
Этот тип маппинга следует применять, когда поле может присутствовать или отсутствовать в сообщении.

Например, для запроса _exists_:service будут найдены все документы, содержащие поле service, независимо от его значения.

Обратите внимание: запрос _exists_ будет работать и с другими типами полей.

Пример маппинга для exists поля:

mapping-list:
- name: service
type: exists

Параметры конфигурации

  • indexing.partial_field_indexing - если true, то будет проиндексирована только первая часть поля, если длина поля больше лимита, если false - при превышении лимита по размеру поле будет пропущено.
  • indexing.max_token_size - максимальный размер токена,по умолчанию 72.
  • indexing.case_sensitive - если false, то все значения будут приведены к нижнему регистру.
  • constant consts.MaxTextFieldValueLength - ограничивает максимальную длину текстового поля, текущий порог 32768 байт.

Индексирование объектов

seq-db также может индексировать логи, содержащие вложенные структурированные данные. В этом случае родительское поле должно иметь тип индекса object и содержать внутри объект mapping-list, который определяет, как именно должны индексироваться вложенные поля.

Например:

mapping-list:
- name: "myobject" # название поле, которое содержит вложенные json данные
type: "object"
mapping-list: # маппинг для вложенных полей
- type: "keyword"
name: "nested"
- type: "text"
name: "nestedtext"

Вложенные объекты и названия полей, содержащие точки

seq-db не делает различий между полями, которые индексируются внутри вложенного объекта, и полями, содержащими точку в имени.

Например, при использовании представленного ниже маппинга, будут проиндексированы как поле name, вложенное в объект с ключом user, так и поле user.name в корне лога.

mapping-list:
- name: user
type: object
mapping-list:
- type: keyword
name: name
- user.name: keyword

Индексация одного поля несколькими способами

Одно поле может быть проиндексировано несколькими способами одновременно. Это позволяет комбинировать различные стратегии индексирования для обеспечения более гибких возможностей поиска.

Например, поле можно индексировать одновременно как keyword и text, что позволяет выполнять как полнотекстовый поиск, так и поиск по полному совпадению.

Если для поля используются несколько индексов, то дополнительный тип должен иметь название, которое будет использоваться при поиске данных.

Пример маппинга:

mapping-list:
- name: message
types:
- type: text
- title: keyword
type: keyword
size: 18

В этом случае, поле с пустым title будет полем по умолчанию.

Для полей с не пустым title будет создано "неявное" поле - в нашем случае message.keyword. Используйте message.keyword для поиска по полному совпадению и message для полнотекстового поиска.

Названия "неявного" поля состоит из значений name и title, соединенных точкой между ними.

Пример маппинга

Рассмотрим конкретный пример. Определим маппинг и посмотрим, как будет проиндексирован тестовый документ.

Представим, что у нас есть следующий маппинг с явно указанными типами полей: text, keyword, path, exists.

mapping-list:
- name: message
types:
- type: text
- title: keyword
type: keyword
size: 18
- name: level
type: keyword
- name: foo
type: exists
- name: bar
type: keyword
- name: uri
type: path

Также есть size, которое позволяет указать максимальный размер значения поля. Если поле size не указано, будет использовано значение по умолчанию.

Детали реализации индексирования

Запишем документ используя маппинг (ID документа будет следующим: id = N):

{
"message": "hello world",
"some_number": 1,
"level": "info",
"foo": "aaa bbb ccc",
"bar": "ddd eee fff",
"uri": "/my/path"
}

Следующие метаданные будут созданы:

{
id: N,
tokens: [
"_exists_:message",
"message:hello",
"message:world",
"_exists_:message.keyword",
"message.keyword:hello world",
"_exists_:level",
"level:info",
"_exists_:foo",
"_exists_:bar",
"bar:ddd eee fff",
"_exists_:uri",
"uri:/my",
"uri:/my/path",
]
}

Заметим, что:

  • Для каждого поля были созданы дополнительные _exists_ токены.
  • Есть токены для поля message.keyword, которого нет в оригинальном документе, но оно указано в маппинге в качестве "неявного" типа для поля message.
  • У поля foo есть только _exists_ токен.
  • Значение поля bar проиндексировано как один токен, так как это keyword поле.
  • Для поля uri есть несколько токенов, по одному на каждый сегмент пути.
  • Поле some_number не проиндексировано, потому что оно не указано в маппинге.