Команда розробників поєднала OpenSearch із SQLite FTS5 і зменшила частку відеопошукових запитів без результатів з 11,4% до 2,1%, зберігаючи при цьому затримку на рівні нижче 20 мс. Тепер користувачі, які вводять «blackpink jenny solo stag», бачать правильний результат «BLACKPINK Jennie SOLO stage» замість порожнього списку.
Чому ці зміни були необхідні
Журнали пошуку на платформі для хостингу відео виявили повторювану проблему: одна помилка в назві латиницею могла призвести до відсутності всіх збігів. Розширення SQLite FTS5, яке цінують за здатність зіставляти підрядки в текстах китайською, японською та корейською мовами (CJK), не підтримує нечітке зіставлення (fuzzy matching). Одна помилка в імені або назві пісні повністю ламає запит.
Існуючий конвеєр (pipeline) використовував SQLite як єдиний індекс. Він добре справлявся із запитами CJK, але не мав механізму захисту від помилок у латинській графіці. Тому команда почала шукати додатковий пошуковий рушій, який міг би забезпечити стійкість до помилок (typo tolerance), не відмовляючись від перевіреного рівня FTS5.
Як було додано OpenSearch
OpenSearch працює як основний пошуковий сервіс, тоді як SQLite залишається першоджерелом (source of truth). Обидві системи працюють паралельно: спочатку OpenSearch отримує запит користувача, і якщо він відповідає достатньо швидко, показуються його результати. Якщо в OpenSearch стається тайм-аут або помилка, запит перемикається на індекс SQLite FTS5. Така відмовостійка архітектура гарантує, що через мережевий збій рядок пошуку ніколи не залишиться порожнім.
Мультипольове відображення
Кожна назва відео індексується трьома способами в OpenSearch:
- title.std – обробляється стандартним аналізатором з використанням ASCII folding. Це нормалізує символи з діакритичними знаками та обробляє більшість помилок у латинській графіці.
- title.cjk – обробляється CJK-аналізатором, який створює біграми (двосимвольні токени). Це зберігає перевагу зіставлення підрядків, яку FTS5 забезпечує для азійських письмових систем.
- title.keyword – зберігається без змін для пошуку за точним збігом та сортування.
Роздільні поля дозволяють застосовувати правильний аналіз до кожного типу письма, не змішуючи стратегії токенізації.
Рівні підвищення релевантності (boost tiers)
Замість одного монолітного запиту команда створила багаторівневий запит, який автоматично ранжує результати:
- Точні збіги фраз у
title.keywordотримують найвищий boost, що гарантує домінування ідеальних збігів у списку. - Збіги CJK-біграм у
title.cjkотримують середній boost, зберігаючи якість пошуку азійськими мовами. - Нечіткі латинські збіги у
title.stdотримують нижчий boost, що дозволяє результатам із помилками з'являтися в списку, не затьмарюючи точні збіги.
Такий багаторівневий підхід спрощує налаштування: зміна одного значення boost змінює відносну важливість цілого класу збігів.
Розумна нечіткість (smart fuzziness)
Нечіткість (fuzziness) — можливість обмеженої кількості редагувань символів — застосовується лише до латинського поля. Команда вимкнула нечіткість для title.cjk, оскільки зміна навіть одного символу в CJK часто повністю змінює значення. Для латинського тексту запит використовує налаштування нечіткості AUTO в OpenSearch, яке масштабує дозволену відстань редагування залежно від довжини слова, забезпечуючи баланс між стійкістю до помилок та релевантністю.
Продуктивність та логіка відкату
Процедура пошуку обгортає виклик OpenSearch у блок try-catch:
- Якщо OpenSearch повертає результат протягом 400 мс, відображаються його результати.
- Якщо виклик викликає виняток (exception) або перевищує тайм-аут, система негайно повторно виконує запит через SQLite FTS5.
Це гарантує, що затримка мережі або збої в роботі сервісу ніколи не погіршать досвід користувача. Затримка пошуку залишалася на рівні нижче 20 мс.
Вимірюваний ефект
- Частка запитів без результатів для латинських запитів знизилася з 11,4% до 2,1%.
- Якість пошуку для CJK-запитів залишилася незмінною, що підтверджує: новий CJK-аналізатор зберіг переваги оригінального індексу FTS5.
- Сквозна затримка (end-to-end latency) стабільно трималася нижче цільового показника у 20 мс, що означає, що доданий рівень не уповільнив інтерфейс.
Уроки та компроміси
- Розділення folding та fuzziness – Folding (нормалізація символів) та fuzziness (обробка помилок) вирішують різні проблеми. Використання окремих полів запобігає ненавмисним взаємодіям між ними.
- Не сприймайте пошуковий індекс як першоджерело (source of truth) – SQLite залишається канонічним сховищем; OpenSearch — це похідне представлення, що оновлюється. Це запобігає розсинхронізації індексу (index drift) і спрощує відновлення після збоїв.
- Рівні boost спрощують налаштування – Групування пов'язаних збігів під одним коефіцієнтом boost зменшує кількість параметрів, які потребують коригування.
На що звернути увагу далі
Експеримент доводить, що невелика надбудова OpenSearch може кардинально покращити стійкість до друкарських помилок у багатомовних назвах відео, не жертвуючи перевіреними можливостями SQLite FTS5 для CJK. Для платформ, де релевантність пошуку безпосередньо впливає на час перегляду, таке покращення стає відчутною перевагою для користувацького досвіду.
