fix(db-mongodb): joins with singular collection name (#8933)
### What? Properly specifies `$lookup.from` when the collection name is singular. ### Why? MongoDB can pluralize the collection name and so can be different for singular ones. ### How? Uses the collection name from the driver directly `adapter.collections[slug].collection.name` instead of just `slug`.
This commit is contained in:
@@ -106,7 +106,7 @@ export const buildJoinAggregation = async ({
|
||||
$lookup: {
|
||||
as: `${as}.docs`,
|
||||
foreignField: `${join.field.on}${code}`,
|
||||
from: slug,
|
||||
from: adapter.collections[slug].collection.name,
|
||||
localField: versions ? 'parent' : '_id',
|
||||
pipeline,
|
||||
},
|
||||
@@ -147,7 +147,7 @@ export const buildJoinAggregation = async ({
|
||||
$lookup: {
|
||||
as: `${as}.docs`,
|
||||
foreignField: `${join.field.on}${localeSuffix}`,
|
||||
from: slug,
|
||||
from: adapter.collections[slug].collection.name,
|
||||
localField: versions ? 'parent' : '_id',
|
||||
pipeline,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
import { categoriesSlug, postsSlug } from '../shared.js'
|
||||
import { singularSlug } from './Singular.js'
|
||||
|
||||
export const Categories: CollectionConfig = {
|
||||
slug: categoriesSlug,
|
||||
@@ -83,5 +84,11 @@ export const Categories: CollectionConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'singulars',
|
||||
type: 'join',
|
||||
collection: singularSlug,
|
||||
on: 'category',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
14
test/joins/collections/Singular.ts
Normal file
14
test/joins/collections/Singular.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const singularSlug = 'singular'
|
||||
|
||||
export const Singular: CollectionConfig = {
|
||||
slug: singularSlug,
|
||||
fields: [
|
||||
{
|
||||
type: 'relationship',
|
||||
relationTo: 'categories',
|
||||
name: 'category',
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||
import { Categories } from './collections/Categories.js'
|
||||
import { CategoriesVersions } from './collections/CategoriesVersions.js'
|
||||
import { Posts } from './collections/Posts.js'
|
||||
import { Singular } from './collections/Singular.js'
|
||||
import { Uploads } from './collections/Uploads.js'
|
||||
import { Versions } from './collections/Versions.js'
|
||||
import { seed } from './seed.js'
|
||||
@@ -20,6 +21,7 @@ export default buildConfigWithDefaults({
|
||||
Uploads,
|
||||
Versions,
|
||||
CategoriesVersions,
|
||||
Singular,
|
||||
{
|
||||
slug: localizedPostsSlug,
|
||||
admin: {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getFileByPath } from 'payload'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import type { NextRESTClient } from '../helpers/NextRESTClient.js'
|
||||
import type { Category, Config, Post } from './payload-types.js'
|
||||
import type { Category, Config, Post, Singular } from './payload-types.js'
|
||||
|
||||
import { devUser } from '../credentials.js'
|
||||
import { idToString } from '../helpers/idToString.js'
|
||||
@@ -642,6 +642,8 @@ describe('Joins Field', () => {
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
expect(true).toBeTruthy()
|
||||
const response = await restClient
|
||||
.GRAPHQL_POST({ body: JSON.stringify({ query }) })
|
||||
.then((res) => res.json())
|
||||
@@ -666,6 +668,21 @@ describe('Joins Field', () => {
|
||||
|
||||
expect(allCategories.totalDocs).toBe(allCategoriesByIds.totalDocs)
|
||||
})
|
||||
|
||||
it('should join with singular collection name', async () => {
|
||||
const {
|
||||
docs: [category],
|
||||
} = await payload.find({ collection: 'categories', limit: 1, depth: 0 })
|
||||
|
||||
const singular = await payload.create({
|
||||
collection: 'singular',
|
||||
data: { category: category.id },
|
||||
})
|
||||
|
||||
const categoryWithJoins = await payload.findByID({ collection: 'categories', id: category.id })
|
||||
|
||||
expect((categoryWithJoins.singulars.docs[0] as Singular).id).toBe(singular.id)
|
||||
})
|
||||
})
|
||||
|
||||
async function createPost(overrides?: Partial<Post>, locale?: Config['locale']) {
|
||||
|
||||
@@ -16,6 +16,7 @@ export interface Config {
|
||||
uploads: Upload;
|
||||
versions: Version;
|
||||
'categories-versions': CategoriesVersion;
|
||||
singular: Singular;
|
||||
'localized-posts': LocalizedPost;
|
||||
'localized-categories': LocalizedCategory;
|
||||
users: User;
|
||||
@@ -133,6 +134,20 @@ export interface Category {
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
};
|
||||
singulars?: {
|
||||
docs?: (string | Singular)[] | null;
|
||||
hasNextPage?: boolean | null;
|
||||
} | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "singular".
|
||||
*/
|
||||
export interface Singular {
|
||||
id: string;
|
||||
category?: (string | null) | Category;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -231,6 +246,10 @@ export interface PayloadLockedDocument {
|
||||
relationTo: 'categories-versions';
|
||||
value: string | CategoriesVersion;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'singular';
|
||||
value: string | Singular;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'localized-posts';
|
||||
value: string | LocalizedPost;
|
||||
|
||||
Reference in New Issue
Block a user