diff --git a/wiki/payloadcms/_index.md b/wiki/payloadcms/_index.md index 83d5b1d..0f4df8d 100644 --- a/wiki/payloadcms/_index.md +++ b/wiki/payloadcms/_index.md @@ -120,3 +120,4 @@ | [[wiki/payloadcms/plugin-multi-tenant\|Multi-Tenant Plugin]] | Scaffold multi-tenancy: tenant field on collections, Admin selector, filtered list views + relationship pickers, isGlobal (1 doc/tenant), cascade delete, super-admin bypass, useTenantSelection hook | raw/plugins__multi-tenant.md | 2026-05-15 | | [[wiki/payloadcms/plugin-nested-docs\|Nested Docs Plugin]] | Parent/child hierarchy for collections: auto `parent` + `breadcrumbs` fields, recursive cascade updates, `generateURL`/`generateLabel` options, custom field overrides, localization support | raw/plugins__nested-docs.md | 2026-05-15 | | [[wiki/payloadcms/plugin-redirects\|Redirects Plugin]] | Managed `redirects` collection (from/to + doc reference), redirect types (301/302), overrides pattern, frontend integration (Next.js middleware/redirects()) | raw/plugins__redirects.md | 2026-05-15 | +| [[wiki/payloadcms/plugin-search\|Search Plugin]] | First-party search index: static `search` collection, hook-free queries, priority sorting, `beforeSync`/`skipSync`, on-demand reindex | raw/plugins__search.md | 2026-05-15 | diff --git a/wiki/payloadcms/plugin-search.md b/wiki/payloadcms/plugin-search.md new file mode 100644 index 0000000..d9c7ac1 --- /dev/null +++ b/wiki/payloadcms/plugin-search.md @@ -0,0 +1,139 @@ +--- +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