templates: fix categories search sync (#12359)
Fixes https://github.com/payloadcms/payload/issues/9449 Previously, search sync with categories didn't work and additionally caused problems with Postgres. Additionally, ensures that when doing synchronization, all the categories are populated, since we don't always have populated data inside hooks.
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import { BeforeSync, DocToSync } from '@payloadcms/plugin-search/types'
|
import { BeforeSync, DocToSync } from '@payloadcms/plugin-search/types'
|
||||||
|
|
||||||
export const beforeSyncWithSearch: BeforeSync = async ({ originalDoc, searchDoc, payload }) => {
|
export const beforeSyncWithSearch: BeforeSync = async ({ req, originalDoc, searchDoc }) => {
|
||||||
const {
|
const {
|
||||||
doc: { relationTo: collection },
|
doc: { relationTo: collection },
|
||||||
} = searchDoc
|
} = searchDoc
|
||||||
|
|
||||||
const { slug, id, categories, title, meta, excerpt } = originalDoc
|
const { slug, id, categories, title, meta } = originalDoc
|
||||||
|
|
||||||
const modifiedDoc: DocToSync = {
|
const modifiedDoc: DocToSync = {
|
||||||
...searchDoc,
|
...searchDoc,
|
||||||
@@ -20,24 +20,40 @@ export const beforeSyncWithSearch: BeforeSync = async ({ originalDoc, searchDoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (categories && Array.isArray(categories) && categories.length > 0) {
|
if (categories && Array.isArray(categories) && categories.length > 0) {
|
||||||
// get full categories and keep a flattened copy of their most important properties
|
const populatedCategories: { id: string | number; title: string }[] = []
|
||||||
try {
|
for (const category of categories) {
|
||||||
const mappedCategories = categories.map((category) => {
|
if (!category) {
|
||||||
const { id, title } = category
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
if (typeof category === 'object') {
|
||||||
relationTo: 'categories',
|
populatedCategories.push(category)
|
||||||
id,
|
continue
|
||||||
title,
|
}
|
||||||
}
|
|
||||||
|
const doc = await req.payload.findByID({
|
||||||
|
collection: 'categories',
|
||||||
|
id: category,
|
||||||
|
disableErrors: true,
|
||||||
|
depth: 0,
|
||||||
|
select: { title: true },
|
||||||
|
req,
|
||||||
})
|
})
|
||||||
|
|
||||||
modifiedDoc.categories = mappedCategories
|
if (doc !== null) {
|
||||||
} catch (err) {
|
populatedCategories.push(doc)
|
||||||
console.error(
|
} else {
|
||||||
`Failed. Category not found when syncing collection '${collection}' with id: '${id}' to search.`,
|
console.error(
|
||||||
)
|
`Failed. Category not found when syncing collection '${collection}' with id: '${id}' to search.`,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modifiedDoc.categories = populatedCategories.map((each) => ({
|
||||||
|
relationTo: 'categories',
|
||||||
|
categoryID: String(each.id),
|
||||||
|
title: each.title,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiedDoc
|
return modifiedDoc
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const searchFields: Field[] = [
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'id',
|
name: 'categoryID',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export type SupportedTimezones =
|
|||||||
| 'Asia/Singapore'
|
| 'Asia/Singapore'
|
||||||
| 'Asia/Tokyo'
|
| 'Asia/Tokyo'
|
||||||
| 'Asia/Seoul'
|
| 'Asia/Seoul'
|
||||||
|
| 'Australia/Brisbane'
|
||||||
| 'Australia/Sydney'
|
| 'Australia/Sydney'
|
||||||
| 'Pacific/Guam'
|
| 'Pacific/Guam'
|
||||||
| 'Pacific/Noumea'
|
| 'Pacific/Noumea'
|
||||||
@@ -624,6 +625,7 @@ export interface Form {
|
|||||||
label?: string | null;
|
label?: string | null;
|
||||||
width?: number | null;
|
width?: number | null;
|
||||||
defaultValue?: string | null;
|
defaultValue?: string | null;
|
||||||
|
placeholder?: string | null;
|
||||||
options?:
|
options?:
|
||||||
| {
|
| {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -791,8 +793,9 @@ export interface Search {
|
|||||||
categories?:
|
categories?:
|
||||||
| {
|
| {
|
||||||
relationTo?: string | null;
|
relationTo?: string | null;
|
||||||
id?: string | null;
|
categoryID?: string | null;
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
|
id?: string | null;
|
||||||
}[]
|
}[]
|
||||||
| null;
|
| null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
@@ -1355,6 +1358,7 @@ export interface FormsSelect<T extends boolean = true> {
|
|||||||
label?: T;
|
label?: T;
|
||||||
width?: T;
|
width?: T;
|
||||||
defaultValue?: T;
|
defaultValue?: T;
|
||||||
|
placeholder?: T;
|
||||||
options?:
|
options?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
@@ -1458,8 +1462,9 @@ export interface SearchSelect<T extends boolean = true> {
|
|||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
relationTo?: T;
|
relationTo?: T;
|
||||||
id?: T;
|
categoryID?: T;
|
||||||
title?: T;
|
title?: T;
|
||||||
|
id?: T;
|
||||||
};
|
};
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BeforeSync, DocToSync } from '@payloadcms/plugin-search/types'
|
import { BeforeSync, DocToSync } from '@payloadcms/plugin-search/types'
|
||||||
|
|
||||||
export const beforeSyncWithSearch: BeforeSync = async ({ originalDoc, searchDoc }) => {
|
export const beforeSyncWithSearch: BeforeSync = async ({ req, originalDoc, searchDoc }) => {
|
||||||
const {
|
const {
|
||||||
doc: { relationTo: collection },
|
doc: { relationTo: collection },
|
||||||
} = searchDoc
|
} = searchDoc
|
||||||
@@ -20,24 +20,40 @@ export const beforeSyncWithSearch: BeforeSync = async ({ originalDoc, searchDoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (categories && Array.isArray(categories) && categories.length > 0) {
|
if (categories && Array.isArray(categories) && categories.length > 0) {
|
||||||
// get full categories and keep a flattened copy of their most important properties
|
const populatedCategories: { id: string | number; title: string }[] = []
|
||||||
try {
|
for (const category of categories) {
|
||||||
const mappedCategories = categories.map((category) => {
|
if (!category) {
|
||||||
const { id, title } = category
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
if (typeof category === 'object') {
|
||||||
relationTo: 'categories',
|
populatedCategories.push(category)
|
||||||
id,
|
continue
|
||||||
title,
|
}
|
||||||
}
|
|
||||||
|
const doc = await req.payload.findByID({
|
||||||
|
collection: 'categories',
|
||||||
|
id: category,
|
||||||
|
disableErrors: true,
|
||||||
|
depth: 0,
|
||||||
|
select: { title: true },
|
||||||
|
req,
|
||||||
})
|
})
|
||||||
|
|
||||||
modifiedDoc.categories = mappedCategories
|
if (doc !== null) {
|
||||||
} catch (_err) {
|
populatedCategories.push(doc)
|
||||||
console.error(
|
} else {
|
||||||
`Failed. Category not found when syncing collection '${collection}' with id: '${id}' to search.`,
|
console.error(
|
||||||
)
|
`Failed. Category not found when syncing collection '${collection}' with id: '${id}' to search.`,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modifiedDoc.categories = populatedCategories.map((each) => ({
|
||||||
|
relationTo: 'categories',
|
||||||
|
categoryID: String(each.id),
|
||||||
|
title: each.title,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiedDoc
|
return modifiedDoc
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const searchFields: Field[] = [
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'id',
|
name: 'categoryID',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -793,8 +793,9 @@ export interface Search {
|
|||||||
categories?:
|
categories?:
|
||||||
| {
|
| {
|
||||||
relationTo?: string | null;
|
relationTo?: string | null;
|
||||||
id?: string | null;
|
categoryID?: string | null;
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
|
id?: string | null;
|
||||||
}[]
|
}[]
|
||||||
| null;
|
| null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
@@ -1461,8 +1462,9 @@ export interface SearchSelect<T extends boolean = true> {
|
|||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
relationTo?: T;
|
relationTo?: T;
|
||||||
id?: T;
|
categoryID?: T;
|
||||||
title?: T;
|
title?: T;
|
||||||
|
id?: T;
|
||||||
};
|
};
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BeforeSync, DocToSync } from '@payloadcms/plugin-search/types'
|
import { BeforeSync, DocToSync } from '@payloadcms/plugin-search/types'
|
||||||
|
|
||||||
export const beforeSyncWithSearch: BeforeSync = async ({ originalDoc, searchDoc }) => {
|
export const beforeSyncWithSearch: BeforeSync = async ({ req, originalDoc, searchDoc }) => {
|
||||||
const {
|
const {
|
||||||
doc: { relationTo: collection },
|
doc: { relationTo: collection },
|
||||||
} = searchDoc
|
} = searchDoc
|
||||||
@@ -20,24 +20,40 @@ export const beforeSyncWithSearch: BeforeSync = async ({ originalDoc, searchDoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (categories && Array.isArray(categories) && categories.length > 0) {
|
if (categories && Array.isArray(categories) && categories.length > 0) {
|
||||||
// get full categories and keep a flattened copy of their most important properties
|
const populatedCategories: { id: string | number; title: string }[] = []
|
||||||
try {
|
for (const category of categories) {
|
||||||
const mappedCategories = categories.map((category) => {
|
if (!category) {
|
||||||
const { id, title } = category
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
if (typeof category === 'object') {
|
||||||
relationTo: 'categories',
|
populatedCategories.push(category)
|
||||||
id,
|
continue
|
||||||
title,
|
}
|
||||||
}
|
|
||||||
|
const doc = await req.payload.findByID({
|
||||||
|
collection: 'categories',
|
||||||
|
id: category,
|
||||||
|
disableErrors: true,
|
||||||
|
depth: 0,
|
||||||
|
select: { title: true },
|
||||||
|
req,
|
||||||
})
|
})
|
||||||
|
|
||||||
modifiedDoc.categories = mappedCategories
|
if (doc !== null) {
|
||||||
} catch (_err) {
|
populatedCategories.push(doc)
|
||||||
console.error(
|
} else {
|
||||||
`Failed. Category not found when syncing collection '${collection}' with id: '${id}' to search.`,
|
console.error(
|
||||||
)
|
`Failed. Category not found when syncing collection '${collection}' with id: '${id}' to search.`,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modifiedDoc.categories = populatedCategories.map((each) => ({
|
||||||
|
relationTo: 'categories',
|
||||||
|
categoryID: String(each.id),
|
||||||
|
title: each.title,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiedDoc
|
return modifiedDoc
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const searchFields: Field[] = [
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'id',
|
name: 'categoryID',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user