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?: {
|
defaultPriorities?: {
|
||||||
[collection: string]: ((doc: any) => number | Promise<number>) | number
|
[collection: string]: ((doc: any) => number | Promise<number>) | number
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Controls whether drafts are deleted from the search index
|
||||||
|
*
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
deleteDrafts?: boolean
|
deleteDrafts?: boolean
|
||||||
localize?: 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
|
reindexBatchSize?: number
|
||||||
searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>
|
searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>
|
||||||
|
/**
|
||||||
|
* Controls whether drafts are synced to the search index
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
syncDrafts?: boolean
|
syncDrafts?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,15 +142,42 @@ export const syncDocAsSearchIndex = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deleteDrafts && status === 'draft') {
|
if (deleteDrafts && status === 'draft') {
|
||||||
// do not include draft docs in search results, so delete the record
|
// Check to see if there's a published version of the doc
|
||||||
try {
|
// We don't want to remove the search doc if there is a published version but a new draft has been created
|
||||||
await payload.delete({
|
const {
|
||||||
id: searchDocID,
|
docs: [docWithPublish],
|
||||||
collection: searchSlug,
|
} = await payload.find({
|
||||||
req,
|
collection,
|
||||||
})
|
draft: false,
|
||||||
} catch (err: unknown) {
|
locale: syncLocale,
|
||||||
payload.logger.error({ err, msg: `Error deleting ${searchSlug} document.` })
|
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) {
|
} else if (doSync) {
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default buildConfigWithDefaults({
|
|||||||
searchOverrides: {
|
searchOverrides: {
|
||||||
access: {
|
access: {
|
||||||
// Used for int test
|
// Used for int test
|
||||||
delete: ({ req: { user } }) => user.email === devUser.email,
|
delete: ({ req: { user } }) => user?.email === devUser.email,
|
||||||
},
|
},
|
||||||
fields: ({ defaultFields }) => [
|
fields: ({ defaultFields }) => [
|
||||||
...defaultFields,
|
...defaultFields,
|
||||||
|
|||||||
@@ -133,6 +133,78 @@ describe('@payloadcms/plugin-search', () => {
|
|||||||
expect(results).toHaveLength(0)
|
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 () => {
|
it('should sync changes made to an existing search document', async () => {
|
||||||
const pageToReceiveUpdates = await payload.create({
|
const pageToReceiveUpdates = await payload.create({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
|
|||||||
Reference in New Issue
Block a user