POST /v1/namespaces/{ns}/search виконує до трьох ранжованих гілок над одним відфільтрованим набором рядків. Усі гілки опціональні; потрібна хоча б одна. label і filter застосовуються до кожної гілки.
Фільтри
Приймаються дві форми:- Одна рівність:
{"property": "project", "value": "conare"}— обслуговується прямо з posting lists. - Масив-DSL:
[property, op, value]зEq,NotEq,Gt,Gte,Lt,Lte,In(значення-масив), композуються через["And", [f1, f2, ...]]/["Or", [...]]до 16 рівнів вкладеності.
false < true. Невідповідність типу чи відсутність властивості нічому не відповідає — включно з NotEq — і не є помилкою. Невідомі оператори, порожні списки And/Or та не-масиви для In — це 400 із зазначенням винуватця.
Векторна гілка
Оцінки — це косинусна подібність на L2-унормованих векторах, і завжди точні: індекс ANN (IVF + RaBitQ 1-бітні коди) відбирає кандидатів, потім реренкує їх проти повнорозмірних векторів. Опції:
Векторний пошук з фільтрами повертає рівно результати ANN-на-відповідній-підмножині — рушій розширює пробінг, щоб компенсувати селективність, тож фільтри не крадуть у вас recall тихо.
Детермінізм: за фіксованого стану індексу ідентичні байти запиту з ідентичними параметрами повертають байт-в-байт однакові списки збігів — за будь-якої кількості потоків чи конкурентності. За лаштунками безперервний семплер відтворює ~1% запитів ANN проти brute-force ground truth і публікує recall; ендпоінт
GET /recall-slo (без облікових даних) звітує про здоровʼя recall у флоті.
Гілка ключових слів
BM25 (k1=1.2, b=0.75) поверх властивості text. Токенайзер: нижній регістр, розбиття за кожним не-літеро-цифровим символом — без стемінгу, без stopwords (паритет word-токенайзера з Turbopuffer).
match контролює комбінацію токенів:
"auto"(за замовчуванням) — вимагати всі токени; якщо це дає менше ніжmax(5, top_k/8)збігів, повторити як будь-який токен. Відповідь повідомляє, який режим виконався ("mode": "and"/"or")."all"— кожен токен обовʼязковий."any"— звичайний диз’юнктивний BM25.
Хронологічна гілка
Ранжує за будь-якою цілочисельною властивістю,asc чи desc — дешева нога «спершу найновіше» гібридного запиту.
Проекція властивостей
include_props контролює, що їде разом із кожним збігом: пропустіть — і отримаєте лише id+score (без зайвих витрат), передайте масив імен — щоб спроектувати лише ці ключі, або true — щоб отримати повну мапу властивостей. Проекція означає, що реренкер може споживати збіги без другого round-trip запиту.
Turbopuffer-сумісний shim
POST /v2/namespaces/{ns}/query приймає форму читання Turbopuffer — {rank_by, filters, top_k, include_attributes} — і повертає {"rows": [{"id", "$dist", ...}]} з $dist як косинусною відстанню. rank_by: ["id", "asc"] разом із filters: ["id", "Gt", cursor] дає курсорну пагінацію/експорт. Непідтримувані форми — це явні 400 із назвою поля, а не тихо інший запит.