Пустые результаты
Поиск возвращает `found: 0` для запросов, которые должны находить совпадения — диагностика отсутствующих документов, слишком узких фильтров, фильтров токенов с ограниченной областью и несоответствий `queryBy`.
Пустые результаты почти всегда вызваны одной из четырёх причин. Выполняйте проверки по порядку.
Симптом
{
"hits": [],
"found": 0,
"page": 1,
"perPage": 10,
"facetCounts": []
}200 с found: 0 — это не ошибка. Это означает «запрос был валиден, ни один документ не совпал».
Дерево решений
1. Заполнен ли индекс фактически?
- Поиск → Индексы → посмотрите на количество "Documents"
- Если 0 → см. [Ошибки индексации](/troubleshooting/ingest-failures)
2. Существует ли поле запроса в документах?
- queryBy перечисляет поля для поиска
- Если вы queryBy по полю, которого нет, ни один документ не может совпасть
3. Не слишком ли узкие фильтры?
- Полностью удалите filterBy и повторите
- Если результаты возвращаются, причиной был фильтр
4. Не комбинирует ли токен с ограниченной областью скрытый фильтр через И?
- Токены с ограниченной областью всегда комбинируют через И свой scopedFilter
- Декодируйте токен, чтобы увидеть, что добавляетсяПроверка 1: в индексе есть документы
curl -X GET https://app.aacsearch.com/api/v1/projects/<projectId>/indexes \
-H "Authorization: Bearer aa_admin_..."Посмотрите на поле documentCount у соответствующего индекса. Если 0, индексация не производилась или завершилась сбоем.
Вы также можете проверить из дашборда: Поиск → Индексы → колонка «Documents».
→ Если 0, перейдите к Ошибки индексации.
Проверка 2: queryBy соответствует индексированным полям
queryBy — это разделённый запятыми список полей, которые сканирует поисковый движок. Поле должно существовать в схеме индекса и быть строкового типа.
// ❌ Это никогда ничего не найдёт, если поле называется `name`, а не `title`
client.search({ q: "shoes", queryBy: "title" });
// ✅ Совпадение с фактическим полем
client.search({ q: "shoes", queryBy: "name,description" });Проверьте схему:
const indexes = await admin.listIndexes();
const products = indexes.find((i) => i.slug === "products");
console.log(products.fields);
// → посмотрите, какие поля имеют тип "string" или "string[]"Проверка 3: фильтры сужают до нуля
Удалите filterBy и перезапустите:
// Исходный — возвращает 0
await client.search({
q: "shoes",
queryBy: "name",
filterBy: "in_stock:=true && price:<50 && brand:=Nike",
});
// Удалите фильтры
await client.search({ q: "shoes", queryBy: "name" });
// → 247 результатов
// Добавляйте фильтры обратно по одному, чтобы найти проблемныйЧастая причина — сравнение строкового фасета с числовым оператором (:<, :>) — движок возвращает 0, потому что сравнение не может быть вычислено.
Проверка 4: комбинированный через И фильтр токена с ограниченной областью
Если вы используете токен с ограниченной областью, scopedFilter токена молча комбинируется через И с тем, что передаёт вызывающий. Со стороны запроса это невидимо.
Декодируйте токен, чтобы увидеть, что добавляется:
const [, payloadB64] = scopedToken.replace("ss_scoped_", "").split(".");
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
console.log(payload.scopedFilter);
// → "organization_id:=org_abc && availability:=in_stock"Если фильтр токена исключает документы, которые вы ожидаете, создайте новый токен с правильным фильтром (на серверной стороне; см. Токены поиска с ограниченной областью действия).
Токены с ограниченной областью могут только сужать доступ. Комбинация
через И обеспечивается функцией combineFilters() в
packages/api/modules/search/lib/scoped-token.ts — Жёсткий инвариант 4 в
кодовой базе. Расширить токен с ограниченной областью с клиента невозможно.
Другие причины
Допуск опечаток установлен в 0
По умолчанию AACsearch допускает небольшие опечатки. Если на индексе или в запросе установлено numTypos: 0, "shose" не совпадёт с "shoes".
client.search({ q: "shose", queryBy: "name", numTypos: 2 });Стоп-слова отфильтровали весь запрос
Частые слова ("the", "and") удаляются перед поиском. Запрос, состоящий только из стоп-слов, ничего не возвращает. Добавьте более специфичный термин.
Синонимы не загружены
Если вы ожидаете, что "sneaker" совпадёт с "shoe", проверьте, что набор синонимов опубликован:
const synonyms = await admin.listSynonyms(indexId);
console.log(synonyms);→ См. Поисковый API → мульти-поиск и запросы для полной конфигурации синонимов.
Недавно проиндексировано, но ещё не видно
Документы проходят через SearchIngestBuffer, прежде чем попасть в живой индекс. Типичная задержка < 30 секунд; холодный старт может быть дольше. Если вы только что отправили, подождите и повторите.
# Проверьте глубину очереди буфера (admin API)
curl -X GET https://app.aacsearch.com/api/v1/projects/<projectId>/usage \
-H "Authorization: Bearer aa_admin_..."Матрица решений
| Диагноз | Решение |
|---|---|
| Индекс пуст | Отправьте документы — см. Ошибки индексации |
Поле queryBy не существует | Используйте реальное поле; проверьте схему |
| Фильтр слишком узкий | Ослабьте filterBy; удалите и добавляйте обратно по одному условию |
| Токен с ограниченной областью исключает целевые документы | Создайте новый токен с ограниченной областью на серверной стороне с правильным фильтром |
| Опечатка или необычное написание | Установите numTypos в 1 или 2 |
| Недавняя индексация не видна | Подождите 30 секунд и повторите; проверьте глубину очереди буфера |
Диагностический пакет
| Поле | Примечания |
|---|---|
| ID организации | обязательно |
| Slug индекса | обязательно |
| Полное тело запроса | включая q, queryBy, filterBy, sortBy |
| Ожидаемое совпадение | один ID документа или external_id, который вы ожидали увидеть |
| Количество документов в индексе | из listIndexes() или дашборда |
| Используется ли токен с ограниченной областью | да/нет — если да, декодированная нагрузка (без подписи) |
Связанные страницы
Лимиты и квоты
Ответы 429 от AACsearch — диагностика per-key rate-лимитов, исчерпания месячной квоты и заголовков, по которым понятно когда повторять.
Медленный поиск
Задержка поиска выше ожидаемой — диагностика холодных стартов, завышенного `perPage`, сложного `filterBy`, отсутствующих фасетов и давления вышестоящего поискового движка.