fix: findDistinct with polymorphic relationships (#13875)
Fixes `findDistinct` with polymorphic relationships and also fixes a bug from https://github.com/payloadcms/payload/pull/13840 when `findDistinct` didn't work properly for `hasMany` relationships in mongodb if `sort` is the same as `field` --------- Co-authored-by: Patrik Kozak <35232443+PatrikKozak@users.noreply.github.com>
This commit is contained in:
@@ -132,6 +132,17 @@ export const getConfig: () => Partial<Config> = () => ({
|
||||
hasMany: true,
|
||||
name: 'categories',
|
||||
},
|
||||
{
|
||||
type: 'relationship',
|
||||
relationTo: ['categories'],
|
||||
name: 'categoryPoly',
|
||||
},
|
||||
{
|
||||
type: 'relationship',
|
||||
relationTo: ['categories'],
|
||||
hasMany: true,
|
||||
name: 'categoryPolyMany',
|
||||
},
|
||||
{
|
||||
type: 'relationship',
|
||||
relationTo: 'categories-custom-id',
|
||||
|
||||
@@ -923,6 +923,183 @@ describe('database', () => {
|
||||
expect(fromRes.categories.title).toBe(title)
|
||||
expect(fromRes.categories.id).toBe(id)
|
||||
}
|
||||
|
||||
// Non-consistent sorting by ID
|
||||
// eslint-disable-next-line jest/no-conditional-in-test
|
||||
if (process.env.PAYLOAD_DATABASE?.includes('uuid')) {
|
||||
return
|
||||
}
|
||||
|
||||
const resultDepth1NoSort = await payload.findDistinct({
|
||||
depth: 1,
|
||||
collection: 'posts',
|
||||
field: 'categories',
|
||||
})
|
||||
|
||||
for (let i = 0; i < resultDepth1NoSort.values.length; i++) {
|
||||
const fromRes = resultDepth1NoSort.values[i] as any
|
||||
const id = categoriesIDS[i].categories as any
|
||||
const title = categories[i]?.title
|
||||
expect(fromRes.categories.title).toBe(title)
|
||||
expect(fromRes.categories.id).toBe(id)
|
||||
}
|
||||
})
|
||||
|
||||
it('should populate distinct relationships of polymorphic when depth>0', async () => {
|
||||
await payload.delete({ collection: 'posts', where: {} })
|
||||
await payload.delete({ collection: 'categories', where: {} })
|
||||
|
||||
const category_1 = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category_1' },
|
||||
})
|
||||
const category_2 = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category_2' },
|
||||
})
|
||||
const category_3 = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category_3' },
|
||||
})
|
||||
|
||||
const post_1 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: { title: 'post_1', categoryPoly: { relationTo: 'categories', value: category_1.id } },
|
||||
})
|
||||
const post_2 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: { title: 'post_2', categoryPoly: { relationTo: 'categories', value: category_1.id } },
|
||||
})
|
||||
const post_3 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: { title: 'post_3', categoryPoly: { relationTo: 'categories', value: category_2.id } },
|
||||
})
|
||||
const post_4 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: { title: 'post_4', categoryPoly: { relationTo: 'categories', value: category_3.id } },
|
||||
})
|
||||
const post_5 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: { title: 'post_5', categoryPoly: { relationTo: 'categories', value: category_3.id } },
|
||||
})
|
||||
|
||||
const result = await payload.findDistinct({
|
||||
depth: 0,
|
||||
collection: 'posts',
|
||||
field: 'categoryPoly',
|
||||
})
|
||||
|
||||
expect(result.values).toHaveLength(3)
|
||||
expect(
|
||||
result.values.some(
|
||||
(v) =>
|
||||
v.categoryPoly?.relationTo === 'categories' && v.categoryPoly.value === category_1.id,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
result.values.some(
|
||||
(v) =>
|
||||
v.categoryPoly?.relationTo === 'categories' && v.categoryPoly.value === category_2.id,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
result.values.some(
|
||||
(v) =>
|
||||
v.categoryPoly?.relationTo === 'categories' && v.categoryPoly.value === category_3.id,
|
||||
),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('should populate distinct relationships of hasMany polymorphic when depth>0', async () => {
|
||||
await payload.delete({ collection: 'posts', where: {} })
|
||||
await payload.delete({ collection: 'categories', where: {} })
|
||||
|
||||
const category_1 = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category_1' },
|
||||
})
|
||||
const category_2 = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category_2' },
|
||||
})
|
||||
const category_3 = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category_3' },
|
||||
})
|
||||
|
||||
const post_1 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post_1',
|
||||
categoryPolyMany: [{ relationTo: 'categories', value: category_1.id }],
|
||||
},
|
||||
})
|
||||
const post_2 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post_2',
|
||||
categoryPolyMany: [{ relationTo: 'categories', value: category_1.id }],
|
||||
},
|
||||
})
|
||||
const post_3 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post_3',
|
||||
categoryPolyMany: [{ relationTo: 'categories', value: category_2.id }],
|
||||
},
|
||||
})
|
||||
const post_4 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post_4',
|
||||
categoryPolyMany: [{ relationTo: 'categories', value: category_3.id }],
|
||||
},
|
||||
})
|
||||
const post_5 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post_5',
|
||||
categoryPolyMany: [{ relationTo: 'categories', value: category_3.id }],
|
||||
},
|
||||
})
|
||||
|
||||
const post_6 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post_6',
|
||||
categoryPolyMany: null,
|
||||
},
|
||||
})
|
||||
|
||||
const result = await payload.findDistinct({
|
||||
depth: 0,
|
||||
collection: 'posts',
|
||||
field: 'categoryPolyMany',
|
||||
})
|
||||
|
||||
expect(result.values).toHaveLength(4)
|
||||
expect(
|
||||
result.values.some(
|
||||
(v) =>
|
||||
v.categoryPolyMany?.relationTo === 'categories' &&
|
||||
v.categoryPolyMany.value === category_1.id,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
result.values.some(
|
||||
(v) =>
|
||||
v.categoryPolyMany?.relationTo === 'categories' &&
|
||||
v.categoryPolyMany.value === category_2.id,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
result.values.some(
|
||||
(v) =>
|
||||
v.categoryPolyMany?.relationTo === 'categories' &&
|
||||
v.categoryPolyMany.value === category_3.id,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(result.values.some((v) => v.categoryPolyMany === null)).toBe(true)
|
||||
})
|
||||
|
||||
describe('Compound Indexes', () => {
|
||||
|
||||
@@ -198,6 +198,16 @@ export interface Post {
|
||||
title: string;
|
||||
category?: (string | null) | Category;
|
||||
categories?: (string | Category)[] | null;
|
||||
categoryPoly?: {
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
} | null;
|
||||
categoryPolyMany?:
|
||||
| {
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
}[]
|
||||
| null;
|
||||
categoryCustomID?: (number | null) | CategoriesCustomId;
|
||||
localized?: string | null;
|
||||
text?: string | null;
|
||||
@@ -827,6 +837,8 @@ export interface PostsSelect<T extends boolean = true> {
|
||||
title?: T;
|
||||
category?: T;
|
||||
categories?: T;
|
||||
categoryPoly?: T;
|
||||
categoryPolyMany?: T;
|
||||
categoryCustomID?: T;
|
||||
localized?: T;
|
||||
text?: T;
|
||||
|
||||
Reference in New Issue
Block a user