# Subindexes and several indexes

> Show a store's categories and pages beside its products in one search box: subindexes are searched with their index as one search, and a multi-index search runs several indexes' searches in one request.

A search box often shows more than products: the store's categories, its pages, its brands. Findlane does this two ways.

- **Subindexes** belong to an index, such as `products.categories` and `products.pages`. A search of the index can ask for them too, and the whole request counts as **one search**.
- **A multi-index search** runs searches of separate indexes in one request, such as a store's products and its blog. **Each search counts.**

## Subindexes

A subindex is a small index of its own, with its own records, settings and feed, named after its index: `products.categories`. It's searched through its index, with the index's public ID and allowed sites.

- An index can have up to 5 subindexes. They aren't counted among your plan's indexes.
- Their records count toward your plan's records. An index and its subindexes share the plan's [records per index](/docs/limits.md#plans).
- A key for an index opens its subindexes too.
- Deleting an index deletes its subindexes.

Add one on the index's **Overview**, under **Subindexes**, or ask your AI assistant ([`create_subindex`](/docs/agents.md)). Then fill it as any index: by its full name with the [API](/docs/api.md#records) or the [server SDK](/docs/server-sdk.md), with a [product feed](/docs/feeds.md), or by uploading records in the dashboard. The [WooCommerce plugin](/docs/woocommerce.md) fills `categories` and `pages` for you.

```ts
const categories = client.index("products").subindex("categories")
await categories.upsert([
  { objectID: "jackets", title: "Rain jackets", path: "Clothing > Jackets", url: "/c/rain-jackets", count: 42 },
])
```

### Searching them

Name the subindexes a search should search too, each with its own search. A subindex's search takes the main search's `q` and `highlight` unless it gives its own, and 5 results unless it says. `true` asks for that much.

```ts
const results = await client.search({
  q: "rain jaket",
  limit: 6,
  subindexes: { categories: { limit: 3 }, pages: true },
})

results.hits                          // products
results.subindexes?.categories        // { hits, total, … }, or { error, status }
```

Each subindex comes back under `subindexes` by name, with its results or, if its search failed, its `error` and `status`. One the index doesn't have is a 404 there, not an error for the whole search. The request counts as one search. If the edge's cache answers every part, it counts as none, as any cached search does.

The search box in [React](/docs/react.md#a-search-box) shows them as their own sections above the results:

```tsx
<SearchBox
  publicId="pub_your_public_id"
  hrefTemplate="{url}"
  subindexes={{
    categories: { limit: 3, label: "Categories", hrefTemplate: "{url}" },
    pages: { limit: 2, label: "Pages", hrefTemplate: "{url}" },
  }}
/>
```

From your server, an API key's search takes `subindexes` the same way.

## Several indexes in one request

To search separate indexes together, send their searches in one request, each naming its index's public ID. Every index must allow the page's site. Each search counts, and each can ask for its own subindexes.

```ts
const [products, posts] = await client.multiSearch([
  { q: "rain jacket", limit: 6 },                          // this client's index
  { index: "pub_blog_public_id", q: "rain jacket", limit: 3 },
])
```

Up to 10 searches. The answers come in the order asked: each its results with its `index`, or its `error` and `status`, such as a 403 for an index that doesn't allow the site. `multiSearch` throws only when every search failed.

Without the SDK, send `POST https://api.findlane.dev/api/public/search` with `{ "queries": [{ "index": "pub_…", "q": "…" }] }`, as `text/plain` so browsers don't ask first with a preflight.
