ProjectSearchDocument
Elasticsearch document ProjectSearchDocument — rebuildable search projection полнотекстового поиска
проектов (ЖК/апарт-отелей) публичного каталога (лента /hotels и главная, поиск по названию/адресу/
застройщику). Полнотекстовый поиск реализован на Elasticsearch (ADR-0059).
Назначение
Source of truth — CatalogProjectCard; проекция хранит только
индексируемые/фильтруемые/сортируемые поля карточки проекта. Ключевые возможности поиска — fuzzy,
транслитерация кириллица↔латиница и алиасы названий комплексов/застройщиков (ADR-0059 п.1). Поиск
объектов недвижимости — отдельная проекция property-objects.md.
Index
| Поле | Значение |
|---|---|
| Index alias | catalog-projects |
| Versioned index | catalog-projects-v1 |
| Owner service | catalog |
| Source of truth | CatalogProjectCard (catalog.project_cards) |
| Rebuild job | ProjectSearchRebuildJob |
Document Id И Routing
- Document id:
Idкарточки (Guid проекта = id вchessboard); платформенная витрина не tenanted (ADR-0052 п.3), tenant-префикс не применяется. - Routing key:
DeveloperId— проекты одного застройщика колокализуются (developer-facing scope-фильтр). - Delete/tombstone:
Status = Delistedили физическое удаление → удаление документа;Hidden→ документ остаётся, вырезается security-trimming-ом до выдачи.
Поля
| Поле | Тип | Indexed | Stored | Analyzer | Source | Security |
|---|---|---|---|---|---|---|
Id | keyword | да | да | — | Id | — |
DeveloperId | keyword | да | да | — | Developer.DeveloperId | routing/scope-filter |
Name | text | да | нет | ru_translit_fuzzy | Name | — |
Address | text | да | нет | ru_translit_fuzzy | Address | — |
DeveloperName | text | да | нет | ru_translit_fuzzy | Developer.DeveloperName | — |
RegionName | text | да | нет | ru_translit_fuzzy | RegionName | — |
CityName | text | да | нет | ru_translit_fuzzy | CityName | — |
SearchText | text | да | нет | ru_translit_fuzzy | Name ⊕ Address ⊕ DeveloperName ⊕ RegionName ⊕ CityName (copy_to) | основной матч запроса searchTerm |
Kind | keyword | да | да | — | Kind | фильтр «тип» (ResidentialComplex/ApartHotel) |
PropertyClass | keyword | да | да | — | PropertyClass | фильтр «класс» |
RegionId | keyword | да | да | — | RegionId (ссылка на справочник handbook) | фильтр «регион» |
CityId | keyword | да | да | — | CityId (ссылка на справочник handbook) | фильтр «город» |
ConstructionStatus | keyword | да | да | — | ConstructionStatus | фильтр «статус строительства» |
Price.Min | double | да | да | — | Price.Min (NullableRange<decimal>) | фильтр «ценовой диапазон» + сортировка |
Price.Max | double | да | да | — | Price.Max | фильтр |
PropertyObjectsAvailable | integer | да | да | — | PropertyObjectsAvailable | фильтр «есть доступные» |
PromotionBoost | integer | да | да | — | PromotionBoost | ранжирование «Рекомендованные» |
DeveloperPriority | integer | да | да | — | DeveloperPriority | ранжирование |
PopularityScore | double | да | да | — | PopularityScore | сортировка «по популярности» |
PublishedAt | date | да | да | — | PublishedAt | сортировка «по дате» |
Status | keyword | да | да | — | Status | security-trimming (Published) |
SchemaVersion | integer | да | да | — | документ | версия схемы проекции |
UpdatedAt | date | да | да | — | карточка UpdatedAt | freshness watermark |
IndexedAt | date | да | да | — | индексатор | freshness |
ru_translit_fuzzyОбщий с property-objects.md: русская морфология + ICU-транслитерация
- edge-ngram (typo-tolerance) + синонимы/алиасы (ADR-0059 п.1).
Source Events
| Event | Version | Transform |
|---|---|---|
ProjectCardRecomputedEvent | v1 | upsert документа из текущего состояния CatalogProjectCard (маппинг полей выше) |
ProjectCardRecomputedEvent (Status=Delisted) | v1 | delete документа |
Проекция наполняется инкрементально доменным событием карточки (тот же коммит, что пересчёт витрины) +
периодический/ручной ProjectSearchRebuildJob для bootstrap и восстановления консистентности.
Freshness
- SLA:
search(секунды–минуты; eventual относительно PostgreSQL,FreshnessView). - Watermark:
UpdatedAtкарточки в документе. - Stale behavior: показать результаты с freshness-маркером.
Security
- Tenant/brand/scope trimming до query execution (ADR-0059 п.3):
публичный поиск — только
Status = Published; developer-facing поиск — дополнительноDeveloperId == актор.CompanyId. - PII fields: none.
- Полнотекстовый поиск не индексирует secrets, tokens, payment/KYC data.
Rebuild
- Create versioned index
catalog-projects-v{N+1}(маппинг +ru_translit_fuzzy). - Backfill из
catalog.project_cards(Status != Delisted). - Validate counts/checksums против source.
- Atomically switch alias
catalog-projects(ADR-0029). - Keep previous index до окончания rollback-окна.
Деградация и частичный отказ
Полнотекстовый поиск и лента с searchTerm зависят от Elasticsearch; при недоступности индекса поиск
деградирует — пользователю отдаётся признак «поиск временно недоступен», а интерфейс предлагает ленту без
текстового запроса (сортировки/фильтры обслуживает витрина catalog.project_cards через API каталога и
продолжают работать). «Примерную» FTS-выдачу из PostgreSQL не строим — FTS-колонок в источнике нет по
построению (ADR-0059).
Только что опубликованный проект появляется в поиске (а скрытый — исчезает) после доезда
ProjectCardRecomputedEvent и индексации (секунды–минуты); в окне рассинхронизации выдача помечается
признаком свежести (FreshnessView). Точный статус для действий (бронь) поиском не подтверждается — это
делает источник.
Пересборка идёт в теневой индекс catalog-projects-v{N+1}; алиас catalog-projects переключается только
после валидации счётчиков/чек-сумм, поэтому частичный или упавший rebuild не отдаёт пользователю неполный
индекс — активным остаётся прежний до успешного switch.
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (1): Entity / Aggregate: CatalogProjectCard
- Use Cases (1): UC-CTL-002. Поиск по названию проекта (FTS: name / address / developer)
- index.md (1): Catalog Service (Pin.Catalog)
Связанные документы
- catalog-project-card.md — source of truth; property-objects.md — проекция объектов недвижимости.
- ADR-0059 (Elasticsearch-проекции), ADR-0008 (search projection), ADR-0029 (alias strategy).
- Шаблон: search-document-template.md.