Архитектура и поисковый индекс

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

Индекс ускоряет поиск, но не заменяет исходные данные. Результат остается верным, пока источник обновляет документ после изменения текста, адреса, сайтов и прав. Понимание этой границы помогает выбрать место для доработки и найти причину, если выдача отстает от состояния объекта.

Параметры методов, PHP-примеры и порядок подключения собственного источника собраны в практическом руководстве Индексация собственного контента.

Как документ проходит через поиск

Поиск объединяет два потока с разной ответственностью. Источник готовит документы и поддерживает индекс. Пользовательский запрос читает индекс и возвращает только доступные результаты. Индексация и поиск могут идти одновременно. Метод CSearch::Index() координирует основную запись, связанные данные и выбранный движок, но не открывает для них общую транзакцию. Поэтому во время одиночной индексации запрос может увидеть промежуточное состояние документа.


Исходный объект ──> модуль-источник ──> поисковый документ ──> индекс
                                                                  │
Строка запроса ──> разбор ────────────────────────────────────────┤
Сайт, даты и область источника ───────────────────────────────────┤
Коды доступа пользователя ────────────────────────────────────────┤
Поисковый движок ──> полнотекстовое совпадение ───────────────────┘
                                                                  │
                                                                  v
                                                               выдача

Каждый этап меняет представление данных и отвечает за свой результат.

Этап

Входные данные

Результат

Побочный эффект

Подготовка документа

Исходный объект и правила его модуля

Массив полей поискового документа

Источник выбирает текст, URL, сайты и права

Индексация

Идентификаторы документа и подготовленные поля

Новая или обновленная запись

Модуль обновляет связанные сайты, права, параметры, теги и данные полнотекстового индекса

Выполнение запроса

Поисковая строка, сайт, фильтры и коды доступа

Разрешенные совпадения

Движок применяет свои правила полнотекстового поиска, а модуль учитывает область и права

Формирование результата

Данные записи и URL для выбранного сайта

Элемент выдачи

Компонент или PHP-код форматирует и показывает результат

Схема показывает участников поиска, но не задает порядок запросов к хранилищам. Конкретный движок может объединить полнотекстовый поиск, фильтры и проверку прав в одной операции.

Интерфейс не участвует в подготовке индекса. Поэтому замена шаблона компонента не добавит отсутствующий документ и не исправит устаревшие права. Сначала нужно восстановить синхронизацию с источником.

Из чего состоит поисковый документ

Поисковый документ хранит не исходный объект целиком, а только нужные для поиска поля. Эти поля определяют, что искать, где открыть результат, кому его показывать и как ограничить выборку.

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

Поле

Тип и допустимая форма

Обязательность

TITLE, BODY

Строки

Обязательны для новой записи

TAGS

Строка

Необязательно

URL

Строка

Необязательно для сохранения, но нужно для перехода к материалу, если SITE_ID не содержит адрес

SITE_ID

Строка, список идентификаторов сайтов или ассоциативный массив вида идентификатор сайта => URL

Обязательно для новой записи без LID

LID

Строковый идентификатор сайта

Альтернатива SITE_ID

DATE_CHANGE

Строка в формате DD.MM.YYYY HH:MI:SS

Обязательно, если нет LAST_MODIFIED

LAST_MODIFIED

Строка в формате даты и времени текущей культуры

Альтернатива DATE_CHANGE

DATE_FROM, DATE_TO

Строки в формате даты и времени текущей культуры либо false

Необязательно

PERMISSIONS

Массив числовых идентификаторов групп и строковых кодов доступа

Необязательно

PARAM1, PARAM2

Строки

Необязательно

PARAMS

Ассоциативный массив вида имя => значение или имя => список значений

Необязательно

USER_ID

Целое число

Необязательно

ENTITY_TYPE_ID, ENTITY_ID

Строки

Необязательно

CUSTOM_RANK

Целое число

Необязательно

INDEX_TITLE

Логическое значение

Необязательно

Поля SEARCHABLE_CONTENT, UPD, CUSTOM_RANK_SQL и ~DATE_CHANGE относятся к внутренней обработке. Модуль формирует их сам и не ожидает от источника.

Идентификаторы и область источника

Идентификаторы MODULE_ID и ITEM_ID задают документ, а остальные поля описывают его содержимое и связи.

Поля PARAM1 и PARAM2 позволяют фильтровать документы по области источника. Источник может хранить в них тип материала, идентификатор раздела или другой признак. Поле PARAMS хранит именованные признаки с одним или несколькими значениями.

Содержимое и адрес результата

Поля массива $arFields TITLE, BODY и TAGS образуют текстовую основу поискового документа. Модуль очищает края строк, объединяет значения и передает подготовленное содержимое выбранному движку. Если INDEX_TITLE отсутствует или не равно false, модуль включает заголовок в подготовленный текст и отдельный индекс заголовков. Значение false отключает эти действия. Sphinx и OpenSearch самостоятельно собирают текст из TITLE и BODY, поэтому этот флаг не исключает заголовок из их полнотекстового поиска.

Метод читает LID, только если массив не содержит SITE_ID. URL из привязки к сайту имеет приоритет в результате поиска. Такая модель нужна, когда один материал доступен на нескольких сайтах по разным адресам. Для обычного списка идентификаторов сайтов модуль использует общий URL.

Даты и дополнительные связи

Метод преобразует DATE_CHANGE в формат даты Bitrix Framework перед сравнением и сохранением.

Поле LAST_MODIFIED имеет приоритет над DATE_CHANGE. Метод CSearch::Index() принимает его без преобразования, а при добавлении документа передает значение в Bitrix\Main\Type\DateTime. Если источник не учитывает формат текущей культуры, используйте DATE_CHANGE. Дата участвует в обновлении и сортировке, поэтому источник должен менять ее вместе с содержимым.

Поиск учитывает период из DATE_FROM и DATE_TO, когда запрос включает проверку дат. Поля USER_ID, ENTITY_TYPE_ID и ENTITY_ID относятся к специальным данным источников. Они не заменяют PERMISSIONS, MODULE_ID и ITEM_ID; для обычного документа собственного модуля их заполнять не требуется.

Поле CUSTOM_RANK хранит дополнительный вес документа. Подходящее правило пользовательского ранжирования заменяет переданный вес. Правила выбираются по сайту и области источника. Настройте порядок результатов по рекомендациям из статьи Ранжирование, теги и поисковые подсказки.

Права доступа

Модуль добавляет префикс G к числовому идентификатору группы в PERMISSIONS. Например, группа 2 превращается в G2.

Поиск проверяет права при выполнении запроса. Для авторизованного пользователя модуль сопоставляет коды документа с его кодами доступа. Для анонимного пользователя он ищет код G2. Администратор проходит эту проверку без ограничения по кодам.

Пустой массив прав не означает доступ для всех. Обычный пользователь не увидит документ без совпадающего кода. Передавайте права исходного объекта и обновляйте их сразу после изменения доступа.

Идентификация документа

Пара MODULE_ID и ITEM_ID защищает индекс от дублей. Хранилище поддерживает только одну запись с такой комбинацией. Повторная индексация того же ключа обновляет существующий документ и сохраняет его внутренний идентификатор индекса.

Источник должен выбирать ITEM_ID, который не меняется при редактировании объекта. Заголовок, URL или позиция в разделе для этой роли не подходят. Их изменение создаст риск потерять связь между исходным объектом и записью индекса.

Дополнительные поля не заменяют стабильный ключ. Например, PARAM1 и PARAM2 позволяют удалить или обновить группу документов, но модуль все равно находит отдельную запись по MODULE_ID и ITEM_ID.

Как меняется состояние записи

Жизненный цикл документа начинается в модуле-источнике. Модуль search применяет полученные изменения к основной записи и связанным данным.


Нет записи ──> добавление ──> актуальная запись
                                  │
                ┌─────────────────┼─────────────────┐
                v                 v                 v
          новое содержимое   новые права      новые сайты
                │                 │                 │
                └─────────────────┴─────────────────┘
                                  │
                                  v
                         обновленная запись
                                  │
                                  v
                               удаление

Изменение исходного объекта

Действие с индексом

Что меняется

Создан новый объект

Индексировать документ

Основная запись, полнотекстовые данные, сайты, права, параметры, заголовок и теги

Изменились заголовок, текст, теги или даты

Повторно индексировать тот же ключ

Переданные поля и данные полнотекстового индекса

Изменился адрес или набор сайтов

Повторно индексировать документ либо изменить привязки сайтов

Список сайтов и URL для каждого сайта

Изменились права

Повторно индексировать документ либо изменить коды доступа

Набор кодов, с которым поиск сравнивает права пользователя

Объект удален или больше не должен участвовать в поиске

Удалить запись

Основная запись и все связанные данные

Связи документа меняются отдельно от полнотекстового содержимого. Модуль обновляет сайты, именованные параметры и непустой набор прав до сравнения дат. Это обновляет связи в основном хранилище. При совпадении даты метод завершает работу до обновления внешнего движка. Для синхронизации прав и сайтов используйте специальные методы или принудительную индексацию полного документа; ограничения описаны в сценарии обновления.

Пустой набор PERMISSIONS не очищает сохраненные права при обычном обновлении документа. Одновременно пустые TITLE и BODY переводят существующий документ в удаленное состояние. Выбор метода для каждого перехода и ограничения групповых операций описывает руководство Индексация собственного контента.

Чем отличаются варианты переиндексации

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

Вариант

Что происходит с существующей записью

Когда использовать

Одиночная индексация

Модуль добавляет или обновляет документ по его стабильному ключу

После создания или изменения одного объекта

Переиндексация модуля

Источник повторно передает свои документы. В полном режиме модуль сначала удаляет записи этого источника

После массового изменения данных одного модуля

Неполная переиндексация

Модуль помечает обработанные документы идентификатором сеанса, обновляет измененные записи и удаляет старые записи, которые источник больше не вернул

Для восстановления актуальности без предварительной очистки всего индекса

Полная переиндексация

Модуль очищает общие таблицы индекса и хранилище выбранного движка, затем заново собирает документы

После смены движка или когда текущему индексу нельзя доверять

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

Ответственность поискового движка

Поисковый движок отвечает за полнотекстовую часть конвейера. Модуль вызывает CSearchFullText::getInstance() и выбирает реализацию по настройке full_text_engine. Затем он передает выбранной реализации добавление, обновление, удаление, очистку и выполнение запроса.

Код проекта должен работать с CSearch, а не с классом конкретного движка. Модель документа остается общей при смене реализации. Модуль search продолжает вести ключ MODULE_ID и ITEM_ID, привязки к сайтам, дополнительные параметры и коды доступа. Движок получает подготовленный текст и возвращает совпадения, но не становится владельцем исходного объекта.

Смена движка не требует менять PHP API и компоненты. При этом могут различаться морфология, ранжирование, поддерживаемые запросы, требования к окружению и порядок обслуживания. Сравните подходящие варианты в статье Выбор и настройка поискового движка.

Не обращайтесь к таблицам индекса или внешнему движку напрямую. Такой код обходит обработку сайтов, прав, событий и связанных данных. Он также усложняет смену движка и восстановление индекса.

Кто отвечает за актуальный результат

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

Участник

Ответственность

Не отвечает за

Модуль-источник

Содержимое документа, стабильный идентификатор, URL, сайты, права и своевременное обновление

Разбор общей поисковой строки и работу выбранного движка

Модуль search

Хранение общей модели, связи документа, проверку доступа и координацию индексации

Предметные правила исходного объекта

Поисковый движок

Полнотекстовый индекс, поиск совпадений и поддерживаемое ранжирование

Актуальность исходного объекта и его прав

Компонент или собственный интерфейс

Параметры запроса, навигацию и безопасный вывод

Добавление отсутствующих документов в индекс

Ищите причину сбоя с начала конвейера. Сначала убедитесь, что источник сформировал документ с правильным ключом, сайтами и правами. Затем проверьте наличие записи в индексе и только после этого разбирайте запрос, движок и шаблон выдачи.

Диагностика этапов поиска

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

Проверка документа в поисковой выдаче охватывает добавление, обновление, права и удаление. Таблица диагностики связывает симптомы с проверками и способами восстановления.

Для изменения отдельных этапов используйте события поиска, а для управления выдачей — запросы через CSearch.