feat: polymorphic join querying by fields that don't exist in every collection (#12648)
This PR makes it possible to do polymorphic join querying by fields that
don't exist in all collections specified in `field.collection`, for
example:
```
const result = await payload.find({
collection: 'payload-folders',
joins: {
documentsAndFolders: {
where: {
and: [
{
relationTo: {
in: ['folderPoly1', 'folderPoly2'],
},
},
{
folderPoly2Title: { // this field exists only in the folderPoly2 collection, before it'd throw a query error.
equals: 'Poly 2 Title',
},
},
],
},
},
},
})
```
---------
Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
This commit is contained in:
@@ -59,6 +59,7 @@ export async function validateQueryPaths({
|
||||
errors,
|
||||
overrideAccess,
|
||||
policies,
|
||||
polymorphicJoin,
|
||||
req,
|
||||
versionFields,
|
||||
where: item,
|
||||
@@ -71,6 +72,7 @@ export async function validateQueryPaths({
|
||||
globalConfig,
|
||||
overrideAccess,
|
||||
policies,
|
||||
polymorphicJoin,
|
||||
req,
|
||||
versionFields,
|
||||
where: item,
|
||||
|
||||
@@ -99,7 +99,10 @@ export async function validateSearchParam({
|
||||
promises.push(
|
||||
...paths.map(async ({ collectionSlug, field, invalid, path }, i) => {
|
||||
if (invalid) {
|
||||
errors.push({ path })
|
||||
if (!polymorphicJoin) {
|
||||
errors.push({ path })
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
12
test/joins/collections/FolderPoly1.ts
Normal file
12
test/joins/collections/FolderPoly1.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const FolderPoly1: CollectionConfig = {
|
||||
slug: 'folderPoly1',
|
||||
fields: [
|
||||
{
|
||||
name: 'folderPoly1Title',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
folders: true,
|
||||
}
|
||||
12
test/joins/collections/FolderPoly2.ts
Normal file
12
test/joins/collections/FolderPoly2.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const FolderPoly2: CollectionConfig = {
|
||||
slug: 'folderPoly2',
|
||||
fields: [
|
||||
{
|
||||
name: 'folderPoly2Title',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
folders: true,
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import path from 'path'
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||
import { Categories } from './collections/Categories.js'
|
||||
import { CategoriesVersions } from './collections/CategoriesVersions.js'
|
||||
import { FolderPoly1 } from './collections/FolderPoly1.js'
|
||||
import { FolderPoly2 } from './collections/FolderPoly2.js'
|
||||
import { HiddenPosts } from './collections/HiddenPosts.js'
|
||||
import { Posts } from './collections/Posts.js'
|
||||
import { SelfJoins } from './collections/SelfJoins.js'
|
||||
@@ -337,6 +339,8 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
],
|
||||
},
|
||||
FolderPoly1,
|
||||
FolderPoly2,
|
||||
],
|
||||
localization: {
|
||||
locales: [
|
||||
|
||||
@@ -289,6 +289,64 @@ describe('Joins Field', () => {
|
||||
expect(categoryWithPosts.localizedPolymorphics.docs[0]).toHaveProperty('id')
|
||||
})
|
||||
|
||||
it('should not throw a path validation error when querying joins with polymorphic relationships', async () => {
|
||||
const folderDoc = await payload.create({
|
||||
collection: 'payload-folders',
|
||||
data: {
|
||||
name: 'sharedFolder',
|
||||
},
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'folderPoly1',
|
||||
data: {
|
||||
folderPoly1Title: 'Poly 1 title',
|
||||
folder: folderDoc.id,
|
||||
},
|
||||
depth: 0,
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'folderPoly2',
|
||||
data: {
|
||||
folderPoly2Title: 'Poly 2 Title',
|
||||
folder: folderDoc.id,
|
||||
},
|
||||
depth: 0,
|
||||
})
|
||||
|
||||
const result = await payload.find({
|
||||
collection: 'payload-folders',
|
||||
joins: {
|
||||
documentsAndFolders: {
|
||||
limit: 100_000,
|
||||
sort: 'name',
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
relationTo: {
|
||||
in: ['folderPoly1', 'folderPoly2'],
|
||||
},
|
||||
},
|
||||
{
|
||||
folderPoly2Title: {
|
||||
equals: 'Poly 2 Title',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
id: {
|
||||
equals: folderDoc.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result.docs[0]?.documentsAndFolders.docs).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should filter joins using where query', async () => {
|
||||
const categoryWithPosts = await payload.findByID({
|
||||
id: category.id,
|
||||
|
||||
Reference in New Issue
Block a user