Metadata — часть retrieval contract
Определите закрытую schema: tenant, ACL, язык, тип, дата действия, версия и source. Нормализуйте значения при ingestion; свободные строки и разные форматы дат превращают фильтр в случайность.
Pre-filter и post-filter
Pre-filter сужает множество до ANN и обычно лучше для прав доступа. Post-filter сначала ищет соседей, затем удаляет неподходящих и может вернуть меньше k. Проверяйте реальное поведение выбранного движка.
Cardinality влияет на индекс
Фильтр с двумя значениями и фильтр по миллионам user IDs создают разную нагрузку. Измеряйте селективность, число подходящих документов и latency по сегментам, а не только общий p95.
ANN и потеря результатов
При approximate search нужные кандидаты могут не попасть в просмотренную часть графа. Увеличение ef_search или iterative scans повышает recall ценой latency. Exact search используйте как контрольный baseline.
Дата и свежесть
Храните event time, valid_from/valid_to и ingestion time раздельно. Фильтр «последние 30 дней» должен опираться на определённое поле и timezone, иначе результаты невозможно воспроизвести.
Права не являются prompt-инструкцией
ACL применяется сервером до формирования контекста. Логируйте policy version и scope, но не содержимое закрытых результатов. Кэш должен включать tenant и permission fingerprint.
Как тестировать
Создайте запросы для пустого множества, редкого tenant, нескольких языков, обновлённых прав и удалённого документа. Сравните filtered recall с exact baseline и проверьте отсутствие cross-tenant результатов.