AACSearch
Справочник API

Поиск

GET и POST /api/v1/indexes/{slug}/search — все параметры запроса, тело ответа и сопутствующие заголовки.

GET  /api/v1/indexes/{slug}/search
POST /api/v1/indexes/{slug}/search

Оба метода выполняют один и тот же запрос: GET принимает параметры в строке запроса, POST — в теле JSON, что удобнее для длинных выражений filter_by, векторных запросов и текста не в ASCII. Требуется право search:read; запрос списывает одну единицу поисковой квоты.

Короткий пример

curl -sS -G "$AAC_API/indexes/documentation/search" \
  -H "Authorization: Bearer $AAC_KEY" \
  --data-urlencode "q=тарифы и планы" \
  --data-urlencode "query_by=title,content" \
  --data-urlencode "query_by_weights=4,2" \
  --data-urlencode "filter_by=tags:=[billing]" \
  --data-urlencode "facet_by=tags" \
  --data-urlencode "sort_by=_text_match:desc,published_at:desc" \
  --data-urlencode "per_page=5"
curl -sS -X POST "$AAC_API/indexes/documentation/search" \
  -H "Authorization: Bearer $AAC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "тарифы и планы",
    "query_by": "title,content",
    "filter_by": "tags:=[billing]",
    "facet_by": "tags",
    "per_page": 5
  }'

Ответ

{
	"index": "documentation",
	"query": "тарифы и планы",
	"language": "ru",
	"found": 2,
	"out_of": 137,
	"page": 1,
	"per_page": 5,
	"took_ms": 18,
	"engine_ms": 4,
	"hits": [
		{
			"id": "pricing",
			"score": 2711,
			"document": {
				"id": "pricing",
				"external_id": "pricing",
				"title": "Тарифы",
				"content": "На бесплатном тарифе 10 000 поисков в месяц. Pro — 29 USD…",
				"url": "https://example.com/pricing",
				"source_type": "api",
				"organization_id": "org_01h9",
				"tags": ["billing"],
				"indexed_at": 1761214364
			},
			"highlights": [
				{ "field": "title", "snippet": "<mark>Тарифы</mark>", "matchedTokens": ["тарифы"] },
				{
					"field": "content",
					"snippet": "…29 USD в <mark>месяц</mark>…",
					"matchedTokens": ["месяц"]
				}
			]
		}
	],
	"facets": [
		{
			"field": "tags",
			"values": [
				{ "value": "billing", "count": 2, "highlighted": "billing" },
				{ "value": "api", "count": 1 }
			]
		}
	],
	"request_id": "req_9a7c3d1e5f0b2a4c6d8e0f1a"
}
ПолеЗначение
languageЯзык, определённый по q, используется как подсказка для стеммера
foundЧисло совпадений с учётом фильтров
out_ofСколько документов просмотрено в коллекции
took_msВремя платформы, включая квоту и логирование
engine_msВремя, которое сообщил поисковый сервис
hits[].scoreОценка текстового совпадения, чем больше — тем лучше
hits[].highlightsФрагменты с тегами <mark>, расставленными движком
grouped_byПоявляется только при group_by: { field, groups[] }

Пустая выдача — это 200 с found: 0 и пустым массивом hits. Такой запрос записывается в журнал как запрос без результатов.

Параметры

Все параметры опциональны, кроме q для POST (по умолчанию пустая строка, которую движок трактует как «всё подряд»).

ПараметрТипКомментарий
qstring ≤ 1000Текст запроса. Пустой означает «показать всё» (внутри — *)
profilestring ≤ 64Сохранённый профиль поиска, чьи настройки берутся как значения по умолчанию
query_bystringПоля через запятую, по умолчанию title,content,tags
query_by_weightsstringПо весу на каждое поле query_by, например 4,2,1; количество должно совпадать
filter_bystring ≤ 2000Выражение фильтра; не может ссылаться на organization_id
sort_bystring ≤ 200field:asc,field2:desc; допускается _text_match:desc
facet_bystringПоля фасетов через запятую
max_facet_valuesint 1–50По умолчанию 10, ограничено настройкой развёртывания
facet_querystringtags: frontend — поиск по фасетам с facet_query_num_typos (0–3)
pageintПо умолчанию 1, максимум 100 (SEARCH_MAX_DEEP_PAGE); большее значение отклоняется с 422 VALIDATION_ERROR, а не обрезается. Для более глубокого обхода используйте offset
per_pageintПо умолчанию 10; значение обрезается до лимита развёртывания (SEARCH_MAX_PER_PAGE, по умолчанию 250), а не отклоняется
offsetintАльтернатива page
limit_hitsintОграничение на общее число рассматриваемых совпадений
num_typosint 0–3По умолчанию 2
min_len_1typo / min_len_2typoint 1–20Минимальная длина слова для допуска опечатки
typo_tokens_threshold / drop_tokens_thresholdint 0–10Поведение для длинных запросов
prefixbooleanПо умолчанию true; false отключает поиск по префиксу (семантический поиск принудительно его выключает)
prioritize_exact_matchbooleanПредпочитать точные токены совпадениям с опечатками
exhaustive_searchbooleanОбмен задержки на полноту
search_cutoff_msint 0–60000Прервать запрос к движку по истечении бюджета
group_by / group_limitstring / int 1–50Одно поле, одна группа результатов на значение
highlight_fields, highlight_full_fieldsstringПоля для фрагментов
highlight_start_tag, highlight_end_tagstring ≤ 20Заменить <mark> своими тегами
snippet_thresholdint 1–500Длина фрагмента вокруг совпадения
include_fields, exclude_fieldsstringПроекция возвращаемого документа
vector_querystringembedding:([0.1,0.2], k:10, alpha:0.6) для явного kNN
semanticbooleanГибридный поиск по полю автоэмбеддинга индекса
alphafloat 0–1Вес вектора при semantic=true: 0 — только ключевые слова, 1 — только вектор
aclstring[] ≤ 32Принципалы user:<id>, group:<id> или role:<id> для доступа к документам. Учитываются только для серверного ключа без allowedOrigins и запроса без заголовка Origin; иначе игнорируются, и поиск идёт как анонимный (только публичные документы)

Булевы значения принимают true/false и 1/0. Некорректные значения дают 422 VALIDATION_ERROR со списком замечаний Zod; корректные, но превышающие лимит движка — обрезаются.

{
	"error": {
		"code": "VALIDATION_ERROR",
		"message": "Request payload is invalid",
		"request_id": "req_3c7a1f5b9d2e4c6a8b0d2f4e",
		"details": {
			"issues": [
				{
					"code": "too_small",
					"path": ["num_typos"],
					"message": "Number must be greater than or equal to 0"
				}
			]
		}
	}
}

Семантический и гибридный поиск

semantic=true перестраивает запрос для индекса с полем автоэмбеддинга: поле эмбеддинга добавляется в query_by, prefix принудительно становится false (удалённый эмбеддер не умеет искать по префиксу), а в vector_query подставляется k, равный размеру страницы. alpha задаёт пропорцию.

curl -sS -G "$AAC_API/indexes/documentation/search" \
  -H "Authorization: Bearer $AAC_KEY" \
  --data-urlencode "q=сколько стоит тариф pro" \
  --data-urlencode "semantic=true" \
  --data-urlencode "alpha=0.6" \
  --data-urlencode "per_page=3"

Если поля автоэмбеддинга в индексе нет, запрос падает с 400 INVALID_QUERY и сообщением Index "…" has no auto-embedding field. semantic также требует функцию тарифа hybridSearch, а явный vector_query — vectorSearch. См. Семантический поиск.

Сохранённые профили и A/B

profile=<slug> применяет сохранённый профиль (query_by, веса, фасеты, сортировку, размер страницы) как значения по умолчанию; явно переданные параметры побеждают. Неизвестный слаг — 404 PROFILE_NOT_FOUND. Если у индекса включён settings.abTest и profile не передан, платформа детерминированно выбирает профиль по ключу и индексу: один и тот же ключ всегда попадает в одну корзину, и именно это делает сравнение в /analytics/experiments осмысленным. См. A/B-эксперименты.

Заголовки ответа

x-aac-quota-limit: 500000
x-aac-quota-remaining: 499996
x-aac-index: documentation
x-aac-profile: default
x-aac-charged-cents: 0
x-ratelimit-limit: 600
x-ratelimit-remaining: 412
x-ratelimit-reset: 1761214424

x-aac-charged-cents отличен от нуля только когда включённая в тариф квота исчерпана и блок оплатил кошелёк.

Смежные эндпоинты индекса

Они относятся к той же поверхности и используют ту же модель доступа:

ЭндпоинтПравоНазначение
GET /indexes/{slug}/statssearch:readЧисло документов, поля, объём запросов и средняя задержка за 24 часа
POST /indexes/{slug}/eventsanalytics:writeЗаписать клик или конверсию
GET /indexes/{slug}/widget-configsearch:readПрофили поиска, доступные индексу
POST /indexes/multi_searchsearch:readФедеративный поиск: индексы перечислены в теле запроса
GET/PUT /indexes/{slug}/synonyms; DELETE /indexes/{slug}/synonyms/{id}settings:writeОдно- и многосторонние синонимы
GET/PUT /indexes/{slug}/curations; DELETE /indexes/{slug}/curations/{id}settings:writeЗакрепление, скрытие и переписывание запросов
POST /indexes/{slug}/reindexsettings:writeПерестройка без простоя
curl -sS "$AAC_API/indexes/documentation/stats" \
  -H "Authorization: Bearer $AAC_KEY"
{
	"index": {
		"slug": "documentation",
		"collection": "aac_org_01h9_documentation",
		"documents": 137,
		"fields": [
			{
				"name": "title",
				"type": "string",
				"facet": false,
				"optional": true,
				"index": true,
				"sort": false,
				"infix": false
			},
			{
				"name": "tags",
				"type": "string[]",
				"facet": true,
				"optional": true,
				"index": true,
				"sort": false,
				"infix": false
			}
		],
		"created_at": "2026-10-01T08:20:11.000Z"
	},
	"queries_24h": 1841,
	"avg_latency_24h_ms": 17.42,
	"usage": {
		"plan": "pro",
		"period": "2026-10",
		"resetsAt": "2026-11-01T00:00:00.000Z",
		"searches": { "used": 4120, "limit": 500000 },
		"documents": { "used": 137, "limit": 50000 }
	},
	"request_id": "req_6e1b8d0a2c4f6a8d0b2e4c6a"
}

On this page