fix(plugin-search): deleting docs even when there's a published version (#10993)
Fixes https://github.com/payloadcms/payload/issues/9770 If you had a published document but then created a new draft it would delete the search doc, this PR adds an additional find to check if an existing published doc exists before deleting the search doc. Also adds a few jsdocs to plugin config
This commit is contained in:
@@ -42,10 +42,25 @@ export type SearchPluginConfig = {
|
||||
defaultPriorities?: {
|
||||
[collection: string]: ((doc: any) => number | Promise<number>) | number
|
||||
}
|
||||
/**
|
||||
* Controls whether drafts are deleted from the search index
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
deleteDrafts?: boolean
|
||||
localize?: boolean
|
||||
/**
|
||||
* We use batching when re-indexing large collections. You can control the amount of items per batch, lower numbers should help with memory.
|
||||
*
|
||||
* @default 50
|
||||
*/
|
||||
reindexBatchSize?: number
|
||||
searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>
|
||||
/**
|
||||
* Controls whether drafts are synced to the search index
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
syncDrafts?: boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -142,15 +142,42 @@ export const syncDocAsSearchIndex = async ({
|
||||
}
|
||||
}
|
||||
if (deleteDrafts && status === 'draft') {
|
||||
// do not include draft docs in search results, so delete the record
|
||||
try {
|
||||
await payload.delete({
|
||||
id: searchDocID,
|
||||
collection: searchSlug,
|
||||
req,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
payload.logger.error({ err, msg: `Error deleting ${searchSlug} document.` })
|
||||
// Check to see if there's a published version of the doc
|
||||
// We don't want to remove the search doc if there is a published version but a new draft has been created
|
||||
const {
|
||||
docs: [docWithPublish],
|
||||
} = await payload.find({
|
||||
collection,
|
||||
draft: false,
|
||||
locale: syncLocale,
|
||||
req,
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
_status: {
|
||||
equals: 'published',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: {
|
||||
equals: id,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
if (!docWithPublish) {
|
||||
// do not include draft docs in search results, so delete the record
|
||||
try {
|
||||
await payload.delete({
|
||||
id: searchDocID,
|
||||
collection: searchSlug,
|
||||
req,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
payload.logger.error({ err, msg: `Error deleting ${searchSlug} document.` })
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (doSync) {
|
||||
|
||||
@@ -64,7 +64,7 @@ export default buildConfigWithDefaults({
|
||||
searchOverrides: {
|
||||
access: {
|
||||
// Used for int test
|
||||
delete: ({ req: { user } }) => user.email === devUser.email,
|
||||
delete: ({ req: { user } }) => user?.email === devUser.email,
|
||||
},
|
||||
fields: ({ defaultFields }) => [
|
||||
...defaultFields,
|
||||
|
||||
@@ -133,6 +133,78 @@ describe('@payloadcms/plugin-search', () => {
|
||||
expect(results).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('should not delete a search doc if a published item has a new draft but remains published', async () => {
|
||||
const publishedPage = await payload.create({
|
||||
collection: 'pages',
|
||||
data: {
|
||||
_status: 'published',
|
||||
title: 'Published title!',
|
||||
},
|
||||
})
|
||||
|
||||
// wait for the search document to be potentially created
|
||||
// we do not await this within the `syncToSearch` hook
|
||||
await wait(200)
|
||||
|
||||
const { docs: results } = await payload.find({
|
||||
collection: 'search',
|
||||
depth: 0,
|
||||
where: {
|
||||
'doc.value': {
|
||||
equals: publishedPage.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(results).toHaveLength(1)
|
||||
|
||||
// Create a new draft
|
||||
await payload.update({
|
||||
collection: 'pages',
|
||||
id: publishedPage.id,
|
||||
draft: true,
|
||||
data: {
|
||||
_status: 'draft',
|
||||
title: 'Draft title!',
|
||||
},
|
||||
})
|
||||
|
||||
// This should remain with the published content
|
||||
const { docs: updatedResults } = await payload.find({
|
||||
collection: 'search',
|
||||
depth: 0,
|
||||
where: {
|
||||
'doc.value': {
|
||||
equals: publishedPage.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(updatedResults).toHaveLength(1)
|
||||
|
||||
await payload.update({
|
||||
collection: 'pages',
|
||||
id: publishedPage.id,
|
||||
data: {
|
||||
_status: 'draft',
|
||||
title: 'Drafted again',
|
||||
},
|
||||
})
|
||||
|
||||
// Should now be deleted given we've unpublished the page
|
||||
const { docs: deletedResults } = await payload.find({
|
||||
collection: 'search',
|
||||
depth: 0,
|
||||
where: {
|
||||
'doc.value': {
|
||||
equals: publishedPage.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(deletedResults).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('should sync changes made to an existing search document', async () => {
|
||||
const pageToReceiveUpdates = await payload.create({
|
||||
collection: 'pages',
|
||||
|
||||
Reference in New Issue
Block a user