AACSearch / guide
Review a dataset and propose a schema
Submit a sample of your data, get a profiled proposal for the collection schema and field roles, check which capabilities it enables, then confirm it.
Importing data usually starts with a guess. You look at your records, decide which field is the title, which one is a facet, which one holds the price, and create a collection schema by hand. If the guess is wrong you find out later, from bad search results.
The dataset review turns that guess into a measurement. You submit a sample of your records — or a whole small file — and the platform returns:
- a profile of the sample: the fields it found, their observed types, and how completely they are filled;
- a proposal: a ready-to-use mapping of your fields to roles such as
title,priceorcategory, including the resulting schema andquery_by; - a capability assessment: which platform features that data can support.
Nothing is written until you confirm.
In the console
This is the Review data step on the Sources screen (/dashboard/sources).
You can paste a sample there, inspect the proposal and apply it in one click.
This page documents the same operations for API and pipeline use.
Before you begin
- A full API key — confirming a profile writes against a collection.
- A representative sample: up to 100 documents or 2 MB of text.
- No collection needed for the preview itself. Reviewing is how you decide what to create.
What you'll build
A collection schema you did not have to invent, and a stored, agreed profile that later imports follow.
Steps
1. Submit the sample
curl -X POST https://api.aacsearch.com/v1/ingest/preview \
-H "X-NOVA-API-KEY: $NOVA_API_KEY" -H "Content-Type: application/json" \
-d '{
"source": "documents",
"documents": [
{ "id": "1", "title": "Cordless drill 18V", "brand": "Acme", "price": 89.0, "in_stock": true },
{ "id": "2", "title": "Impact driver 18V", "brand": "Acme", "price": 119.0, "in_stock": false }
]
}'source selects how the sample is read:
source | Send | For |
|---|---|---|
documents | documents[] | JSON records you already have |
csv | content | A CSV export |
markdown | content | Prose or a docs dump |
html | content | A page or sitemap capture |
For text sources, send content instead of documents — mixing them is a
400. Use source_name to label the origin, and total_count to say your real
dataset is larger than the sample.
Optionally pass roles to assert what you already know, for example
{"price": "price"}, so the proposal starts from your knowledge instead of
inferring it. Fields you set are reported with role_source: "explicit";
inferred ones are "inferred".
Expected result: a 200 with profile, proposal and capabilities.
2. Read the profile
{
"profile": {
"version": 1,
"sample_count": 2,
"truncated": false,
"fields": [
{
"name": "title",
"types": ["string"],
"present_count": 2,
"null_count": 0,
"coverage": 1,
"role": "title",
"role_source": "inferred",
"reasons": ["unique text with high coverage"]
}
],
"domain_candidates": ["commerce", "generic"],
"warnings": []
},
"proposal": { "fields": [], "query_by": [], "roles": {}, "…": "…" },
"capabilities": [{ "id": "keyword_search", "data": "candidate", "…": "…" }]
}The profile describes the sample, not your whole dataset:
| Field | Meaning |
|---|---|
sample_count | How many records were profiled |
total_count | Your declared total, omitted when unknown |
fields[].types | Observed types; more than one means a conflict |
fields[].coverage | Fraction of records that carry the field (0–1) |
fields[].role | The assigned role, one of id, title, text, url, image, category, price, date, boolean, unknown |
fields[].reasons | Why that role was chosen |
domain_candidates | Best guesses: commerce, content, knowledge, generic |
truncated | The sample, or a parser, stopped early |
A truncated profile is not a dataset description
truncated: true means the profile covers only part of what you sent — a
parser hit its own bound, or you supplied fewer records than total_count.
Treat the proposal as a starting point and review it before confirming.
3. Check which capabilities the data supports
capabilities[] answers the question that matters before you build on the
schema. Each entry has an id — keyword_search, facets,
semantic_search, image_search, assistant or recommendations — and
assesses one dimension:
| Property | Values |
|---|---|
data | candidate (the sample supports it) or insufficient |
configuration | unknown |
entitlement | unknown |
verification | unverified |
reasons | Why, in words |
Only data is judged from your sample. Plan entitlement and configuration are
checked elsewhere — see limits and billing.
Verify: the capabilities you intend to use report data: "candidate". If one
does not, add the missing field at the source and submit the sample again — the
preview has no side effects, so iterate here rather than after importing.
4. Confirm the profile
Confirming stores the accepted proposal against a collection, so later imports follow the agreed roles instead of re-inferring them.
curl -X PUT https://api.aacsearch.com/v1/collections/products/profile \
-H "X-NOVA-API-KEY: $NOVA_API_KEY" -H "Content-Type: application/json" \
-d '{
"source": "documents",
"documents": [ { "id": "1", "title": "Cordless drill 18V", "price": 89.0 } ],
"roles": { "title": "title", "price": "price" }
}'The body uses the same shape as the preview — the sample and any roles you
settled on. Confirming re-runs the profile and stores the result.
Expected result: the stored profile, in the same shape as the preview response.
Verify: GET /collections/products/profile returns it. Confirming again
replaces it, so a later import follows the newer decision.
The collection must exist to confirm
The preview is free-standing, but confirming writes against
/collections/{collectionName}/profile. Create the collection first — see
incremental indexing.
Common problems
| Symptom | Cause | Fix |
|---|---|---|
400 documents source requires documents only; text sources require content only. | documents and content sent together, or neither | Send exactly one, matching source |
400 naming a parser | Malformed CSV/HTML, or content over 2 MB | Send a smaller, valid sample |
truncated: true with a parser_warnings warning | A parser stopped at its bound | Send a smaller sample and set total_count |
A capability reports insufficient | A field the feature needs is missing or sparse | Add the field at the source and re-submit the sample |
| More than 100 documents rejected | Sample cap | Trim to 100 representative records |
404 when confirming | The collection does not exist yet | Create it, then confirm |
Next
- Incremental indexing — create the collection and import at scale.
- CMS connectors — the same review inside the Sources workflow.
- Search profiles and releases — what to configure once the schema is set.
Incremental indexing
Keep a collection in sync with your catalogue — upserts, partial updates, batch imports with per-row results, deletes, async ingest jobs and zero-downtime reindexing.
CMS connectors
Which shop platforms sync into AACSearch, how a connector authenticates, what it sends, push and pull sync, CMS installations, where the console shows sync status, and the limits.