Skip to content

Commit b896507

Browse files
authored
fix(plugin-search): delete proper search document when doc has the same value but different relationTo (#9616)
Fixes #9612 Previously, the plugin search with different collections but the same IDs could delete a wrong search document on synchronization, because we queried the search document only by `doc.value`. Instead, we should also query by `doc.relationTo`.
1 parent aa5dd8a commit b896507

File tree

5 files changed

+117
-5
lines changed

5 files changed

+117
-5
lines changed

packages/plugin-search/src/Search/hooks/deleteFromSearch.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DeleteFromSearch } from '../../types.js'
22

33
export const deleteFromSearch: DeleteFromSearch = async ({
4+
collection,
45
doc,
56
pluginConfig,
67
req: { payload },
@@ -13,8 +14,11 @@ export const deleteFromSearch: DeleteFromSearch = async ({
1314
depth: 0,
1415
req,
1516
where: {
16-
'doc.value': {
17-
equals: doc.id,
17+
doc: {
18+
equals: {
19+
relationTo: collection.slug,
20+
value: doc.id,
21+
},
1822
},
1923
},
2024
})

packages/plugin-search/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,5 @@ export type SyncWithSearch = (Args: SyncWithSearchArgs) => ReturnType<Collection
7272
export type DeleteFromSearch = (
7373
Args: {
7474
pluginConfig: SearchPluginConfig
75-
} & Omit<Parameters<CollectionAfterDeleteHook>[0], 'collection'>,
75+
} & Parameters<CollectionAfterDeleteHook>[0],
7676
) => ReturnType<CollectionAfterDeleteHook>

test/plugin-search/config.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,19 @@ import { Users } from './collections/Users.js'
1313
import { seed } from './seed/index.js'
1414

1515
export default buildConfigWithDefaults({
16-
collections: [Users, Pages, Posts],
16+
collections: [
17+
Users,
18+
Pages,
19+
Posts,
20+
{
21+
slug: 'custom-ids-1',
22+
fields: [{ type: 'text', name: 'id' }],
23+
},
24+
{
25+
slug: 'custom-ids-2',
26+
fields: [{ type: 'text', name: 'id' }],
27+
},
28+
],
1729
localization: {
1830
defaultLocale: 'en',
1931
fallback: true,
@@ -44,7 +56,7 @@ export default buildConfigWithDefaults({
4456
slug: originalDoc.slug,
4557
}
4658
},
47-
collections: ['pages', 'posts'],
59+
collections: ['pages', 'posts', 'custom-ids-1', 'custom-ids-2'],
4860
defaultPriorities: {
4961
pages: 10,
5062
posts: ({ title }) => (title === 'Hello, world!' ? 30 : 20),

test/plugin-search/int.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,46 @@ describe('@payloadcms/plugin-search', () => {
237237
expect(deletedResults).toHaveLength(0)
238238
})
239239

240+
it('should clear the proper search document when having the same doc.value but different doc.relationTo', async () => {
241+
const custom_id_1 = await payload.create({
242+
collection: 'custom-ids-1',
243+
data: { id: 'custom_id' },
244+
})
245+
246+
await payload.create({
247+
collection: 'custom-ids-2',
248+
data: { id: 'custom_id' },
249+
})
250+
251+
await wait(200)
252+
253+
const {
254+
docs: [docBefore],
255+
} = await payload.find({
256+
collection: 'search',
257+
where: { 'doc.value': { equals: 'custom_id' } },
258+
limit: 1,
259+
sort: 'createdAt',
260+
})
261+
262+
expect(docBefore.doc.relationTo).toBe('custom-ids-1')
263+
264+
await payload.delete({ collection: 'custom-ids-1', id: custom_id_1.id })
265+
266+
await wait(200)
267+
268+
const {
269+
docs: [docAfter],
270+
} = await payload.find({
271+
collection: 'search',
272+
where: { 'doc.value': { equals: 'custom_id' } },
273+
limit: 1,
274+
sort: 'createdAt',
275+
})
276+
277+
expect(docAfter.doc.relationTo).toBe('custom-ids-2')
278+
})
279+
240280
it('should sync localized data', async () => {
241281
const createdDoc = await payload.create({
242282
collection: 'posts',

test/plugin-search/payload-types.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export interface Config {
1414
users: User;
1515
pages: Page;
1616
posts: Post;
17+
'custom-ids-1': CustomIds1;
18+
'custom-ids-2': CustomIds2;
1719
search: Search;
1820
'payload-locked-documents': PayloadLockedDocument;
1921
'payload-preferences': PayloadPreference;
@@ -24,6 +26,8 @@ export interface Config {
2426
users: UsersSelect<false> | UsersSelect<true>;
2527
pages: PagesSelect<false> | PagesSelect<true>;
2628
posts: PostsSelect<false> | PostsSelect<true>;
29+
'custom-ids-1': CustomIds1Select<false> | CustomIds1Select<true>;
30+
'custom-ids-2': CustomIds2Select<false> | CustomIds2Select<true>;
2731
search: SearchSelect<false> | SearchSelect<true>;
2832
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
2933
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
@@ -103,6 +107,24 @@ export interface Post {
103107
createdAt: string;
104108
_status?: ('draft' | 'published') | null;
105109
}
110+
/**
111+
* This interface was referenced by `Config`'s JSON-Schema
112+
* via the `definition` "custom-ids-1".
113+
*/
114+
export interface CustomIds1 {
115+
id: string;
116+
updatedAt: string;
117+
createdAt: string;
118+
}
119+
/**
120+
* This interface was referenced by `Config`'s JSON-Schema
121+
* via the `definition` "custom-ids-2".
122+
*/
123+
export interface CustomIds2 {
124+
id: string;
125+
updatedAt: string;
126+
createdAt: string;
127+
}
106128
/**
107129
* This interface was referenced by `Config`'s JSON-Schema
108130
* via the `definition` "search".
@@ -118,6 +140,14 @@ export interface Search {
118140
| {
119141
relationTo: 'posts';
120142
value: string | Post;
143+
}
144+
| {
145+
relationTo: 'custom-ids-1';
146+
value: string | CustomIds1;
147+
}
148+
| {
149+
relationTo: 'custom-ids-2';
150+
value: string | CustomIds2;
121151
};
122152
id: string;
123153
excerpt?: string | null;
@@ -144,6 +174,14 @@ export interface PayloadLockedDocument {
144174
relationTo: 'posts';
145175
value: string | Post;
146176
} | null)
177+
| ({
178+
relationTo: 'custom-ids-1';
179+
value: string | CustomIds1;
180+
} | null)
181+
| ({
182+
relationTo: 'custom-ids-2';
183+
value: string | CustomIds2;
184+
} | null)
147185
| ({
148186
relationTo: 'search';
149187
value: string | Search;
@@ -228,6 +266,24 @@ export interface PostsSelect<T extends boolean = true> {
228266
createdAt?: T;
229267
_status?: T;
230268
}
269+
/**
270+
* This interface was referenced by `Config`'s JSON-Schema
271+
* via the `definition` "custom-ids-1_select".
272+
*/
273+
export interface CustomIds1Select<T extends boolean = true> {
274+
id?: T;
275+
updatedAt?: T;
276+
createdAt?: T;
277+
}
278+
/**
279+
* This interface was referenced by `Config`'s JSON-Schema
280+
* via the `definition` "custom-ids-2_select".
281+
*/
282+
export interface CustomIds2Select<T extends boolean = true> {
283+
id?: T;
284+
updatedAt?: T;
285+
createdAt?: T;
286+
}
231287
/**
232288
* This interface was referenced by `Config`'s JSON-Schema
233289
* via the `definition` "search_select".

0 commit comments

Comments
 (0)