--- 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` | — | Fallback `priority` on create; fn receives `doc` | | `searchOverrides` | `Partial` | — | 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