---
title: "useSearchCollection"
description: "The useSearchCollection composable provides full-text search powered by SQLite FTS5, with prefix matching, BM25 ranking, and snippets."
canonical_url: "https://content.nuxt.com/docs/utils/use-search-collection"
---
# useSearchCollection

> The useSearchCollection composable provides full-text search powered by SQLite FTS5, with prefix matching, BM25 ranking, and snippets.

## Usage

Use the auto-imported `useSearchCollection` composable to search across one or more collections. It builds an FTS5 index from content sections and provides instant ranked search results.

```vue [app.vue]
<script setup lang="ts">
const { status, search } = useSearchCollection('docs')

const query = ref('')
const results = ref([])

watch(query, async (value) => {
  results.value = value ? await search(value) : []
})
</script>
```

<note>

`useSearchCollection` is client-only. The FTS5 index is built in the browser using SQLite WASM.

</note>

## Type

```ts
function useSearchCollection<T extends keyof PageCollections>(
  collection: MaybeRefOrGetter<T | T[]>,
  opts?: GenerateSearchSectionsOptions & { immediate?: boolean }
): {
  status: Ref<'idle' | 'loading' | 'ready' | 'error'>
  search: (query: string, opts?: SearchCollectionOptions) => Promise<SearchResult[]>
  init: () => Promise<DatabaseAdapter>
}
```

## API

### Parameters

- `collection`: A single collection key, an array of collection keys, or a reactive ref/getter. When the value changes, the FTS index is rebuilt for the new collections.
- `opts`: (Optional) Index-building options:

  - `immediate`: Whether to start building the index immediately. Default is `true`. Set to `false` to defer until the first `search()` call or explicit `init()`.
  - `ignoredTags`: Tags to ignore when extracting section content (e.g., `['code']`).
  - `minHeading`: Minimum heading level to split sections on (e.g., `'h2'`). Default is `'h1'`.
  - `maxHeading`: Maximum heading level to split sections on (e.g., `'h4'`). Default is `'h6'`.

### Return Values

- `status`: A reactive ref indicating the index state: `'idle'`, `'loading'`, `'ready'`, or `'error'`.
- `search(query, opts?)`: Execute a search query. Returns a promise with ranked results.

  - `query`: The search string. Supports prefix matching automatically (typing `compo` matches "composable").
  - `opts`: (Optional) Search options:
  
    - `limit`: Maximum results. Default is `20`.
    - `fields`: Restrict search to specific columns (`'title'` or `'content'`).
    - `minTermLength`: Skip terms shorter than this value. Default is `1`.
    - `weights`: Control ranking behavior.
    
      - `title`: Boost factor for title matches. Default is `20`.
      - `content`: Boost factor for content matches. Default is `5`.
      - `heading`: Exponent controlling heading-level boost (`0.5` = sqrt curve, `1` = linear, `0` = disabled). Default is `0.5`.
    - `snippet`: Return highlighted text excerpts.
    
      - `columns`: Which columns to snippet (`['title']`, `['content']`, or both). Default is `['content']`.
      - `around`: Number of tokens around the match. Default is `30`.
      - `tag`: HTML tag for highlighting. Default is `'mark'`.
- `init()`: Manually trigger index building. Useful when `immediate: false`.

### Result Type

```ts
interface SearchResult {
  collection: string
  id: string
  title: string
  titles: string[]
  level: number
  content: string
  rank: number
  snippets?: { title?: string, content?: string }
}
```

## Examples

### Basic Search

```vue [SearchPage.vue]
<script setup lang="ts">
const { status, search } = useSearchCollection('docs')

const query = ref('')
const results = ref([])

async function onSearch() {
  results.value = query.value
    ? await search(query.value, { limit: 20 })
    : []
}
</script>

<template>
  <UInput v-model="query" :disabled="status !== 'ready'" @input="onSearch" />
  <ul>
    <li v-for="result in results" :key="result.id">
      <NuxtLink :to="result.id">{{ result.title }}</NuxtLink>
    </li>
  </ul>
</template>
```

### Multi-Collection Search

```vue [GlobalSearch.vue]
<script setup lang="ts">
const { status, search } = useSearchCollection(['docs', 'blog'])

const results = ref([])
const query = ref('')

watch(query, async (value) => {
  results.value = value
    ? await search(value, {
        limit: 20,
        snippet: { columns: ['content'], around: 40 },
      })
    : []
})
</script>
```

### Deferred Initialization

```vue [LazySearch.vue]
<script setup lang="ts">
const { status, search, init } = useSearchCollection('docs', {
  immediate: false,
})

async function onFocus() {
  if (status.value === 'idle') {
    await init()
  }
}
</script>
```

### Reactive Collections

```vue [VersionedSearch.vue]
<script setup lang="ts">
const version = ref('v4')
const collection = computed(() => `nuxt-${version.value}`)

const { status, search } = useSearchCollection(collection)
</script>

<template>
  <select v-model="version">
    <option>v3</option>
    <option>v4</option>
    <option>v5</option>
  </select>
</template>
```

When the collection value changes, the FTS index is dropped and rebuilt for the new collections.

## Compared to queryCollectionSearchSections

<table>
<thead>
  <tr>
    <th>
      
    </th>
    
    <th>
      <code>
        useSearchCollection
      </code>
    </th>
    
    <th>
      <code>
        queryCollectionSearchSections
      </code>
      
       + Fuse.js
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <strong>
        Dependencies
      </strong>
    </td>
    
    <td>
      None (built-in FTS5)
    </td>
    
    <td>
      Requires external library
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Index
      </strong>
    </td>
    
    <td>
      SQLite inverted index
    </td>
    
    <td>
      In-memory JS scan
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Speed
      </strong>
    </td>
    
    <td>
      O(log n) indexed lookup
    </td>
    
    <td>
      O(n) per query
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Snippets
      </strong>
    </td>
    
    <td>
      Built-in
    </td>
    
    <td>
      Manual
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Typo tolerance
      </strong>
    </td>
    
    <td>
      Prefix only
    </td>
    
    <td>
      Full fuzzy (edit distance)
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Multi-collection
      </strong>
    </td>
    
    <td>
      Native
    </td>
    
    <td>
      Manual merging
    </td>
  </tr>
</tbody>
</table>

Use `useSearchCollection` when you need fast, zero-dependency search. Use `queryCollectionSearchSections` with Fuse.js or MiniSearch when you need typo-tolerant fuzzy matching.


## Sitemap

See the full [sitemap](https://content.nuxt.com/sitemap.md) for all pages.
