В мультитенантном продукте худший баг поиска — не плохое ранжирование, а клиент, увидевший чужую запись. Фильтрация по тенанту в собственном бэкенде работает, пока кто-нибудь не забудет условие WHERE. AACSearch переносит границу в ключ: что ключ может читать, решается на сервере для каждого запроса — что бы ни прислал клиент.
Одна коллекция на клиента — для жёсткого разделения и индивидуальных схем, или одна общая коллекция с полем тенанта — для тысяч мелких тенантов.
Ограничьте ключ списком коллекций или навяжите фильтр вроде tenant_id каждому его поиску. Фильтр объединяется с фильтром вызывающей стороны, и убрать его нельзя.
Ваш бэкенд выводит короткоживущий ключ для вошедшего пользователя — суженный до его коллекций и ваших источников — и передаёт его фронтенду.
Коллекция на тенанта даёт каждому клиенту собственный индекс: отдельная схема, синонимы и ранжирование, а удаление клиента — это удаление коллекции. Подходит, когда тенантов меньше и они крупнее. Общая коллекция с принудительным фильтром подходит длинному хвосту — одна схема, один набор правил и поле тенанта, которое ключ фиксирует на сервере.
Обе модели могут сосуществовать в одной организации: корпоративные клиенты — на выделенных коллекциях, самостоятельные аккаунты — в общей. Код приложения в обоих случаях один и тот же поисковый вызов.
Ключ с ограничением доступа несёт свои ограничения с собой: разрешённые коллекции, принудительный фильтр, список разрешённых полей, скрывающий внутренние колонки, разрешённые источники и IP-адреса, лимит запросов. Они проверяются при каждом запросе, включая каждый элемент пакета multi_search, а принудительный фильтр действует и на подсказки, рекомендации и поиск источников для ассистента.
Браузерные ключи выводятся из родительского ключа, сами истекают максимум через семь дней и перестают работать вместе с родителем при его ротации или отзыве — у скопированного ключа ограничены и срок жизни, и область видимости.
Граница тенанта применяется после параметров клиента, поэтому специально сконструированный запрос не может её расширить.
Список разрешённых полей не пускает закупочные цены, внутренние заметки и векторы в ответы для ключей, которым не положено их видеть.
Один шумный тенант упирается в свой лимит, а не в общий — лимиты задаются на ключ и на браузерный ключ.
Создание, ротация и отзыв ключей записываются в журнал аудита и могут отправляться в ваши системы вебхуками.
Впервые встречаете термин? В глоссарии есть статья «Ключи с ограничением доступа» — объяснение с азов.
{
"allowed_collections": ["tickets_acme", "contacts_acme"],
"allowed_origins": ["https://app.example.com"],
"expires_in_seconds": 3600,
"rate_limit_per_minute": 300,
"user_token": "u_48121"
}
// -> { "key": "nssk_…", "scope": "search", "expires_at": … }
// search-only, these two collections, this origin, one hourУзнать больше
Лучший способ оценить поисковую платформу — не читать ещё одну сравнительную таблицу.
И только после этого принимайте решение.