查询工具

useSearchCollection

useSearchCollection 组合式函数提供由 SQLite FTS5 支持的全文搜索,具备前缀匹配、BM25 排名和摘要片段功能。

用法

使用自动导入的 useSearchCollection 组合式函数在一个或多个集合中进行搜索。它会基于内容章节构建 FTS5 索引,并提供即时的排名搜索结果。

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>
useSearchCollection 仅在客户端可用。FTS5 索引会在浏览器中使用 SQLite WASM 构建。

类型

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

参数

  • collection:单个集合键、集合键数组,或响应式 ref/getter。值变化时,会为新的集合重建 FTS 索引。
  • opts:(可选)构建索引选项:
    • immediate:是否立即开始构建索引。默认值为 true。设为 false 可延迟到第一次调用 search() 或显式调用 init() 时再执行。
    • ignoredTags:提取章节内容时要忽略的标签(例如 ['code'])。
    • minHeading:拆分章节时使用的最小标题级别(例如 'h2')。默认值为 'h1'
    • maxHeading:拆分章节时使用的最大标题级别(例如 'h4')。默认值为 'h6'

返回值

  • status:表示索引状态的响应式 ref:'idle''loading''ready''error'
  • search(query, opts?):执行搜索查询。返回包含排名结果的 promise。
    • query:搜索字符串。自动支持前缀匹配(输入 compo 会匹配 “composable”)。
    • opts:(可选)搜索选项:
      • limit:最大结果数。默认值为 50
      • fields:将搜索限制在特定列('title''content')中。
      • minTermLength:跳过短于此值的术语。默认值为 1
      • weights:控制排名行为。
        • title:标题匹配的提升系数。默认值为 10
        • content:内容匹配的提升系数。默认值为 5
        • heading:是否让更高层级的章节(h1 > h2 > h3)排名更高。默认值为 true
      • snippet:返回高亮文本摘录。
        • columns:对哪些列生成摘录(['title']['content'] 或两者都可)。默认值为 ['content']
        • around:匹配项前后保留的 token 数。默认值为 30
        • tag:用于高亮的 HTML 标签。默认值为 'mark'
  • init():手动触发索引构建。适用于 immediate: false 的情况。

结果类型

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

示例

基本搜索

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>

多集合搜索

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>

延迟初始化

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

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

响应式集合

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>

当集合值发生变化时,FTS 索引会被删除并为新集合重建。

与 queryCollectionSearchSections 的对比

useSearchCollectionqueryCollectionSearchSections + Fuse.js
依赖无(内置 FTS5)需要外部库
索引SQLite 倒排索引内存中的 JS 扫描
速度O(log n) 索引查找每次查询 O(n)
摘要片段内置手动实现
拼写容错仅前缀匹配完整模糊匹配(编辑距离)
多集合原生支持手动合并

当你需要快速、零依赖的搜索时,使用 useSearchCollection。当你需要容错拼写的模糊匹配时,使用带有 Fuse.js 或 MiniSearch 的 queryCollectionSearchSections