Skip to main content

Життєвий цикл рядка

Три види кроків покривають життєвий цикл із ключем id, усі через POST /v1/namespaces/{ns}/query:
  • UpsertN — повна заміна рядка за ключем зовнішнього id. Існуючі рядки з таким id видаляються, потім вставляється новий рядок. Заміна, а не merge: upsert без вектора над векторизованим рядком скидає вектор.
  • SetProps — перезаписує конкретні ключі на matched-потоці (починайте запит з NWhere); значення null видаляє ключ. Сам id змінити не можна — це UpsertN. Підходить для нечастих переписів атрибутів, не підходить для per-query лічильників.
  • DeleteN — видалити matched-потік (NWhereDeleteN) або передати ids для прямих видалень за зовнішніми id.

Кодування векторів

На рядок — одне з двох wire-кодувань (надсилати обидва — 400):
vector_b64 — це base64 вектора як little-endian масив f32 — ~4× менше по дроту і декодується memcpy замість парсингу JSON-чисел. Python-енкодер:
Обидва кодування дають біт-ідентичні збережені вектори та ідентичні результати пошуку. Розмірність фіксується першим векторним записом; невідповідність — 400.

Bulk ingest: POST /v1/namespaces/{ns}/bulk-vectors

Шлях для високої пропускної здатності seed’у — один бінарний фрейм на запит (Content-Type: application/octet-stream): маленький JSON-заголовок (dims, label, ids, спільні props) з подальшими row-major L2-нормалізованими fp16 значеннями. Порівняно з JSON+base64 це уникає багатократного перекодування мультигігабайтних payload’ів.

Restart-safe завантаження

Відновлювані завантажувачі передають ?expected_generation=<G>&expected_rows=<N>. Фрейм приймається лише коли namespace перебуває точно в цьому стані:
  • Той самий фрейм уже закоммічений → 200 з "replayed": true і збіжним request_fingerprint — без дубльованих рядків.
  • Інший payload на тій самій позиції → 409 write_conflict.
  • Успішні умовні записи повертають request_fingerprint, rows_before, rows_after — фіксуйте чекпоінт вашого батчу лише після отримання однієї з цих квитанцій.
Це робить «крах, рестарт, повторне надсилання» усією історією відновлення: нема жодних import-job’ів, за якими треба доглядати.

Компакція

Автокомпакція геометрична, тож загальна робота з компакції залишається лінійною в спожитих байтах. Завершуйте будь-яке bulk-завантаження явною компакцією — надішліть "compact": true на верхньому рівні останнього запиту запису:
Відповідь звітує "compacted": true/false. Компакція також будує ANN-індекс, коли таблиця стає достатньо великою; рядки, записані після snapshot індексу, brute-force мерджаться в результати, тож свіжість ніколи не приноситься в жертву.

Дедуплікація bulk-джерела

Bulk-фрейми за задумом додають наосліп — джерело, яке несе дубльовані id, тихо їх приземлює, і дублікати спалюють слоти top-k. {"DedupN": {}} узгоджує сховище з контрактом унікальності зовнішніх id (залишає останній записаний рядок для кожного id), а {"DedupN": {"dry_run": true}} — це аудит-перепис (лише census), який слід запускати після будь-якого bulk-завантаження, коли його джерело не може довести унікальність id — збіжна загальна кількість рядків не може виявити дублікатів, що ховаються всередині.

Правила повторів

Читання завжди можна повторити після збою транспорту. Для записів автоматично повторюваними є лише умовні bulk-фрейми (ідентичний фрейм + CAS-параметри → оригінальна квитанція або replayed: true). Ніколи не переграйте безумовний запис наосліп після втраченої відповіді — спершу узгодьте стан.