fix(drizzle): hasMany joins - localized, limit and schema paths (#8633)

Fixes https://github.com/payloadcms/payload/issues/8630

- Fixes `hasMany: true` and `localized: true` on the foreign field
- Adds `limit` to the subquery instead of hardcoded `11`.
- Adds the schema path `field.on` to the subquery, without this having 2
or more relationship fields to the same collection breaks joins
- Properly checks if the field is `hasMany`
This commit is contained in:
Sasha
2024-10-10 19:58:30 +03:00
committed by GitHub
parent 1dcae37e58
commit f6acfdb1f5
8 changed files with 132 additions and 13 deletions

View File

@@ -55,6 +55,12 @@ export const Categories: CollectionConfig = {
collection: postsSlug,
on: 'categories',
},
{
name: 'hasManyPostsLocalized',
type: 'join',
collection: postsSlug,
on: 'categoriesLocalized',
},
{
name: 'group',
type: 'group',

View File

@@ -29,6 +29,13 @@ export const Posts: CollectionConfig = {
relationTo: categoriesSlug,
hasMany: true,
},
{
name: 'categoriesLocalized',
type: 'relationship',
relationTo: categoriesSlug,
hasMany: true,
localized: true,
},
{
name: 'group',
type: 'group',

View File

@@ -5,7 +5,7 @@ import { getFileByPath } from 'payload'
import { fileURLToPath } from 'url'
import type { NextRESTClient } from '../helpers/NextRESTClient.js'
import type { Category, Post } from './payload-types.js'
import type { Category, Config, Post } from './payload-types.js'
import { devUser } from '../credentials.js'
import { idToString } from '../helpers/idToString.js'
@@ -80,6 +80,7 @@ describe('Joins Field', () => {
category: category.id,
upload: uploadedImage,
categories,
categoriesLocalized: categories,
group: {
category: category.id,
camelCaseCategory: category.id,
@@ -212,6 +213,89 @@ describe('Joins Field', () => {
expect(otherCategoryWithPosts.hasManyPosts.docs[0].title).toBe('test 14')
})
it('should populate joins using find with hasMany localized relationships', async () => {
const post_1 = await createPost(
{
title: `test es localized 1`,
categoriesLocalized: [category.id],
group: {
category: category.id,
camelCaseCategory: category.id,
},
},
'es',
)
const post_2 = await createPost(
{
title: `test es localized 2`,
categoriesLocalized: [otherCategory.id],
group: {
category: category.id,
camelCaseCategory: category.id,
},
},
'es',
)
const resultEn = await payload.find({
collection: 'categories',
where: {
id: { equals: category.id },
},
})
const otherResultEn = await payload.find({
collection: 'categories',
where: {
id: { equals: otherCategory.id },
},
})
const [categoryWithPostsEn] = resultEn.docs
const [otherCategoryWithPostsEn] = otherResultEn.docs
expect(categoryWithPostsEn.hasManyPostsLocalized.docs).toHaveLength(10)
expect(categoryWithPostsEn.hasManyPostsLocalized.docs[0]).toHaveProperty('title')
expect(categoryWithPostsEn.hasManyPostsLocalized.docs[0].title).toBe('test 14')
expect(otherCategoryWithPostsEn.hasManyPostsLocalized.docs).toHaveLength(8)
expect(otherCategoryWithPostsEn.hasManyPostsLocalized.docs[0]).toHaveProperty('title')
expect(otherCategoryWithPostsEn.hasManyPostsLocalized.docs[0].title).toBe('test 14')
const resultEs = await payload.find({
collection: 'categories',
locale: 'es',
where: {
id: { equals: category.id },
},
})
const otherResultEs = await payload.find({
collection: 'categories',
locale: 'es',
where: {
id: { equals: otherCategory.id },
},
})
const [categoryWithPostsEs] = resultEs.docs
const [otherCategoryWithPostsEs] = otherResultEs.docs
expect(categoryWithPostsEs.hasManyPostsLocalized.docs).toHaveLength(1)
expect(categoryWithPostsEs.hasManyPostsLocalized.docs[0].title).toBe('test es localized 1')
expect(otherCategoryWithPostsEs.hasManyPostsLocalized.docs).toHaveLength(1)
expect(otherCategoryWithPostsEs.hasManyPostsLocalized.docs[0].title).toBe('test es localized 2')
// clean up
await payload.delete({
collection: 'posts',
where: {
id: {
in: [post_1.id, post_2.id],
},
},
})
})
it('should not error when deleting documents with joins', async () => {
const category = await payload.create({
collection: 'categories',
@@ -499,9 +583,10 @@ describe('Joins Field', () => {
})
})
async function createPost(overrides?: Partial<Post>) {
async function createPost(overrides?: Partial<Post>, locale?: Config['locale']) {
return payload.create({
collection: 'posts',
locale,
data: {
title: 'test',
...overrides,

View File

@@ -58,6 +58,7 @@ export interface Post {
upload?: (string | null) | Upload;
category?: (string | null) | Category;
categories?: (string | Category)[] | null;
categoriesLocalized?: (string | Category)[] | null;
group?: {
category?: (string | null) | Category;
camelCaseCategory?: (string | null) | Category;
@@ -102,6 +103,10 @@ export interface Category {
docs?: (string | Post)[] | null;
hasNextPage?: boolean | null;
} | null;
hasManyPostsLocalized?: {
docs?: (string | Post)[] | null;
hasNextPage?: boolean | null;
} | null;
group?: {
relatedPosts?: {
docs?: (string | Post)[] | null;