UC-CTL-002. Поиск по названию проекта (FTS: name / address / developer)
Назначение
Пользователь ищет проекты по названию, адресу или девелоперу через поле поиска ленты. Каталог выполняет
полнотекстовый поиск по витрине CatalogProjectCard с учётом русской морфологии и возвращает карточки,
отсортированные по релевантности, тем же контрактом, что лента UC-CTL-001. Текст запроса записывается в
user-activity как действие SearchPerformed (ADR-0054); каталог собственную историю поиска не хранит.
Metadata
| Поле | Значение |
|---|---|
| ID | UC-CTL-002 |
| Контекст | catalog (см. docs/06-services/catalog/) |
| Тип | основной |
| Статус | draft |
Актор
| Поле | Значение |
|---|---|
| Роль | Гость (с реф-cookie) / Инвестор / Агент / Девелопер / МенеджерПИН |
| Permissions / scope | как UC-CTL-001: гейт ленты (JWT или реф-cookie); permissions не требуются |
| Tenant | не применяется — платформенная витрина (ADR-0052 п.3) |
| Record-level | не применяется — только Status = Published |
Предусловие
- Выполняются предусловия UC-CTL-001 (витрина наполнена, гейт пройден).
- Лента открыта (UC-CTL-001) — поиск уточняет текущую выдачу.
Триггер
| Поле | Значение |
|---|---|
| Источник | UI input |
| Триггерящий элемент | Поле поиска ленты /lots / /hotels; Enter или кнопка поиска |
Основной Поток
- Пользователь вводит текст — название проекта, адрес или девелопера — и нажимает Enter/кнопку поиска.
- Интерфейс добавляет
searchTermв URL-параметры (шаринг ссылки на выдачу) и запрашивает ленту проектов с этим поисковым запросом (тот же контракт, что UC-CTL-001; поиск комбинируется с фильтрами UC-CTL-003 и сортировкой UC-CTL-004). - Каталог выполняет поиск:
- Проверка входа.
searchTermпосле trim — 2..128 символов, иначеValidationError(400). Гейт ленты — иначеCATALOG_FEED_GATE_REQUIRED(401). - Поиск. Полнотекстовый поиск по карточкам
Status = Publishedс учётом русской морфологии; ищется по полям название, адрес и имя девелопера (Name + Address + DeveloperName— дом catalog-project-card.md). По умолчанию порядок — по релевантности; при явной сортировке пользователя (UC-CTL-004) релевантность заменяется её ключами. - Состав карточек и гостевое маскирование цен/статусов — как UC-CTL-001.
- Результат. Список карточек, отсортированный по релевантности, с курсором пагинации.
- Проверка входа.
- Интерфейс заменяет ленту результатами поиска.
- Пагинация результатов — как UC-CTL-001 (keyset-cursor сохраняет
searchTerm). - Интерфейс отправляет событие поиска в
user-activity: действиеSearchPerformedс текстом запроса и идентификатором сессии/анонимной сессии. Дом истории действий —user-activity(ADR-0054), каталог собственную историю поиска не хранит; события действий пробрасываются в карточку лида (crm) и служат входом персонализации. - Пользователь очищает запрос крестиком/удалением текста — интерфейс убирает
searchTermиз URL и повторяет запрос: выдача возвращается к ленте UC-CTL-001.
Альтернативные Потоки
A1. Ничего не найдено
- Шаг 3 возвращает 0 результатов.
- Интерфейс показывает empty-state «По запросу ничего не найдено» с кнопкой сброса; событие
SearchPerformedвuser-activityотправляется всё равно (нулевые выдачи ценны для анализа). Возврат к шагу 1 или 7.
A2. Слишком короткий запрос
- Интерфейс не отправляет запрос при
searchTermкороче 2 символов (debounce + минимальная длина); каталог дублирует правило валидацией (400). - Возврат к шагу 1.
A3. Поиск в ленте объектов недвижимости /lots
- Тот же сценарий для ленты объектов недвижимости
/lots: полнотекстовый поиск по карточке объекта (Title + Number + Address + DeveloperName— catalog-property-object-card.md); ответ — карточки объектов недвижимости. - Остальные шаги идентичны; завершается как основной поток.
A4. Поисковый индекс недоступен или отстаёт
- Полнотекстовый поиск обслуживает Elasticsearch-проекция (../search/projects.md, ADR-0059) — витрина каталога источник её данных. При недоступности индекса каталог деградирует: отдаёт признак «поиск временно недоступен», интерфейс предлагает вернуться к ленте без текстового запроса (фильтры/сортировка по витрине продолжают работать). Возврат к шагу 7.
- Только что опубликованный проект становится находимым после доезда
ProjectCardRecomputedEventи индексации (секунды–минуты); скрытый — перестаёт находиться в том же окне. В интервале отставания выдача помечается признаком свежести. Поток не меняется.
Постусловие
- Лента заменена результатами поиска, отсортированными по релевантности (или явной сортировке).
- В
user-activityсозданActionEvent (SearchPerformed)с текстом запроса и сессией. - Состояние каталога не изменилось (read-only).
Возможные Ошибки
| Код | HTTP | Условие | Поведение клиента |
|---|---|---|---|
ValidationError | 400 | searchTerm после trim < 2 или > 128 символов | Подсветить поле, не слать запрос до исправления |
CATALOG_FEED_GATE_REQUIRED | 401 | Гейт ленты не пройден | Auth-модалка (UC-CTL-001 A1) |
Kafka Интеграционные События
| Событие | Topic | Когда публикуется | Consumers |
|---|---|---|---|
ActionEventRecorded (производит user-activity) | pin.user-activity.actions.v1 | после приёма события поиска (шаг 6) | crm (карточка лида), будущие рекомендации news |
Acceptance Criteria
| # | Критерий | Проверка |
|---|---|---|
| AC1 | Поиск находит проект по каждому из полей: название, адрес, имя девелопера | три запроса по трём полям одного проекта |
| AC2 | Морфология русского языка: «морской» находит «море» | тест словоформ |
| AC3 | Дефолтный порядок — по релевантности; при явной сортировке пользователя релевантность заменяется её ключами | сравнение выдач с sort и без |
| AC4 | Hidden/Delisted карточки не находятся поиском | скрыть проект → пропадает из выдачи |
| AC5 | Гостевое маскирование действует и в поисковой выдаче | запрос гостем с реф-cookie |
| AC6 | Поисковый запрос фиксируется ActionEvent (SearchPerformed) в user-activity, каталог историю не хранит | проверка записи в user-activity + отсутствие таблиц истории в схеме catalog |
| AC7 | searchTerm живёт в URL — открытие скопированной ссылки воспроизводит выдачу | e2e-тест шаринга |
| AC8 | Поиск обслуживает Elasticsearch-проекция; при недоступности индекса — деградация (сообщение + лента без текста), выдача не падает 500 | тест с выключенным индексом |
| AC9 | Только что опубликованная карточка находится поиском лишь после индексации *CardRecomputedEvent (окно свежести), а не мгновенно | тест лага проекции |
Обратные ссылки
Автоссылки: где используется этот документ.
- registries (1): Реестр use cases и user stories PIN
Связанные Документы
- API метод:
../api/public/get-projects.md,../api/public/get-property-objects.md. - Domain entity: ../domain/catalog-project-card.md, ../domain/catalog-property-object-card.md (поля поиска).
- События действий:
../../user-activity/domain/action-event.md(домActionEvent, ADR-0054). - Связанные UC: UC-CTL-001 (лента), UC-CTL-003 (фильтры комбинируются с поиском), UC-CTL-004 (сортировка результатов).