139 lines
4.9 KiB
Markdown
139 lines
4.9 KiB
Markdown
---
|
|
title: "Search Plugin"
|
|
aliases: [plugin-search, payload-search, search-index]
|
|
tags: [payloadcms, plugin, search, indexing]
|
|
sources: [raw/plugins__search.md]
|
|
created: 2026-05-15
|
|
updated: 2026-05-15
|
|
---
|
|
|
|
## Overview
|
|
|
|
`@payloadcms/plugin-search` creates a dedicated `search` collection that mirrors only search-critical fields from your enabled collections. Records are automatically synced on document create/update/delete via hooks, and can be queried with standard Payload APIs — no third-party service required.
|
|
|
|
## How It Works
|
|
|
|
1. Plugin adds a `search` collection to your database with an index
|
|
2. Enabled collections get `beforeChange` + `afterDelete` hooks
|
|
3. On save → a lightweight search record (title, excerpt, slug, etc.) is created/updated
|
|
4. On delete → search record is removed
|
|
5. Queries hit the `search` collection directly — bypassing all hooks on the original collection
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
pnpm add @payloadcms/plugin-search
|
|
```
|
|
|
|
## Basic Setup
|
|
|
|
```ts
|
|
import { searchPlugin } from '@payloadcms/plugin-search'
|
|
|
|
export default buildConfig({
|
|
plugins: [
|
|
searchPlugin({
|
|
collections: ['pages', 'posts'],
|
|
defaultPriorities: {
|
|
pages: 10,
|
|
posts: 20,
|
|
},
|
|
}),
|
|
],
|
|
})
|
|
```
|
|
|
|
## Options Reference
|
|
|
|
| Option | Type | Default | Description |
|
|
|--------|------|---------|-------------|
|
|
| `collections` | `string[]` | required | Slugs of collections to index |
|
|
| `localize` | `boolean` | `true` | Add localization to `title` field if i18n is enabled |
|
|
| `defaultPriorities` | `Record<slug, number \| fn>` | — | Fallback `priority` on create; fn receives `doc` |
|
|
| `searchOverrides` | `Partial<CollectionConfig>` | — | Merge into the auto-created `search` collection config |
|
|
| `beforeSync` | `afterChange hook` | — | Modify/fallback search doc data before create/update |
|
|
| `syncDrafts` | `boolean` | `false` | Sync draft documents to search index |
|
|
| `deleteDrafts` | `boolean` | `true` | Delete search record when doc status changes to draft |
|
|
| `skipSync` | `async fn` | — | Return `true` to skip a specific doc/locale combination |
|
|
| `reindexBatchSize` | `number` | `50` | Batch size for on-demand reindexing |
|
|
|
|
### `beforeSync` — Modify Data Before Index
|
|
|
|
```ts
|
|
searchPlugin({
|
|
beforeSync: ({ originalDoc, searchDoc }) => ({
|
|
...searchDoc,
|
|
excerpt: originalDoc?.excerpt || 'Fallback excerpt',
|
|
}),
|
|
})
|
|
```
|
|
|
|
### `searchOverrides` — Extend the Search Collection
|
|
|
|
```ts
|
|
searchPlugin({
|
|
searchOverrides: {
|
|
slug: 'search-results',
|
|
fields: ({ defaultFields }) => [
|
|
...defaultFields,
|
|
{ name: 'excerpt', type: 'textarea' },
|
|
],
|
|
},
|
|
})
|
|
```
|
|
|
|
### `skipSync` — Conditional Indexing
|
|
|
|
```ts
|
|
searchPlugin({
|
|
skipSync: async ({ locale, doc, collectionSlug, req }) => {
|
|
if (!locale) return false
|
|
const tenant = await req.payload.findByID({ collection: 'tenants', id: doc.tenant.id })
|
|
return !tenant.allowedLocales.includes(locale)
|
|
},
|
|
})
|
|
```
|
|
|
|
`skipSync` is called **once per locale per document**. Return `true` = skip, `false` = proceed.
|
|
|
|
## Priority & Sorting
|
|
|
|
- Every search record gets a `priority` field
|
|
- Use `?sort=priority` (ascending) to order results by collection type
|
|
- `defaultPriorities` sets the initial value at create time
|
|
- Can be a static number or a function: `({ doc }) => doc.featured ? 1 : 10`
|
|
|
|
## On-Demand Reindexing
|
|
|
|
- Navigate to the `search` collection in the Admin Panel
|
|
- Click the **Reindex** pill (top-right action slot)
|
|
- Select a specific collection or "all" to rebuild indexes
|
|
- Useful when adding the plugin to an existing project with existing documents
|
|
|
|
## TypeScript
|
|
|
|
```ts
|
|
import type { SearchConfig, BeforeSync } from '@payloadcms/plugin-search/types'
|
|
```
|
|
|
|
## Key Takeaways
|
|
|
|
- **First-party Algolia alternative** — no external service; runs on your own DB
|
|
- **Static snapshots bypass hooks** — queries on `search` collection don't trigger hooks on original docs, making them significantly faster
|
|
- **You control what's indexed** — only sync fields you need (title, slug, excerpt)
|
|
- **Priority field enables ranked results** — pass `?sort=priority` to order by collection or document importance
|
|
- **`skipSync` is per locale** — called once per locale per document; useful for multi-tenant locale filtering
|
|
- **Draft handling is opt-in** — `syncDrafts: false` by default; set `deleteDrafts: true` to remove drafts from search
|
|
- **Reindex button** covers existing data migration when adding plugin to existing projects
|
|
|
|
## Related
|
|
|
|
- [[wiki/payloadcms/plugins|Plugins Overview + Official]] — all 10 official plugins
|
|
- [[wiki/payloadcms/plugins-api|Plugin API]] — build custom plugins
|
|
- [[wiki/payloadcms/hooks-collections|Collection Hooks]] — `beforeChange`/`afterDelete` hooks used internally
|
|
- [[wiki/payloadcms/queries|Queries]] — querying the `search` collection with `?sort=priority`
|
|
- [[wiki/payloadcms/localization|Localization]] — `localize` option and `skipSync` locale parameter
|
|
|
|
## Sources
|
|
|
|
- `raw/plugins__search.md` — https://payloadcms.com/docs/plugins/search
|