perf: optimize virtual fields that reference ID (#12159)
This PR optimizes the new virtual fields with relationships feature https://github.com/payloadcms/payload/pull/11805 when the path references the ID field, for example: ``` { name: 'postCategoryID', type: 'number', virtual: 'post.category.id', }, ``` Previously, we did additional population of `category`, which is unnecessary as we can always grab the ID from the `category` value itself. One less querying step.
This commit is contained in:
@@ -85,6 +85,11 @@ export const virtualFieldPopulationPromise = async ({
|
|||||||
docID = currentValue
|
docID = currentValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (segments[0] === 'id' && segments.length === 0) {
|
||||||
|
siblingDoc[name] = docID
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof docID !== 'string' && typeof docID !== 'number') {
|
if (typeof docID !== 'string' && typeof docID !== 'number') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -471,6 +471,16 @@ export default buildConfigWithDefaults({
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
virtual: 'post.category.title',
|
virtual: 'post.category.title',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'postCategoryID',
|
||||||
|
type: 'json',
|
||||||
|
virtual: 'post.category.id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'postID',
|
||||||
|
type: 'json',
|
||||||
|
virtual: 'post.id',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'postLocalized',
|
name: 'postLocalized',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@@ -481,6 +491,16 @@ export default buildConfigWithDefaults({
|
|||||||
type: 'relationship',
|
type: 'relationship',
|
||||||
relationTo: 'posts',
|
relationTo: 'posts',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'customID',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'custom-ids',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customIDValue',
|
||||||
|
type: 'text',
|
||||||
|
virtual: 'customID.id',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
versions: { drafts: true },
|
versions: { drafts: true },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1993,11 +1993,63 @@ describe('database', () => {
|
|||||||
collection: 'virtual-relations',
|
collection: 'virtual-relations',
|
||||||
depth: 0,
|
depth: 0,
|
||||||
where: { id: { equals: id } },
|
where: { id: { equals: id } },
|
||||||
draft: true,
|
|
||||||
})
|
})
|
||||||
expect(draft.docs[0]?.postTitle).toBe('my-title')
|
expect(draft.docs[0]?.postTitle).toBe('my-title')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should allow virtual field as reference to ID', async () => {
|
||||||
|
const post = await payload.create({ collection: 'posts', data: { title: 'my-title' } })
|
||||||
|
const { id } = await payload.create({
|
||||||
|
collection: 'virtual-relations',
|
||||||
|
depth: 0,
|
||||||
|
data: { post: post.id },
|
||||||
|
})
|
||||||
|
|
||||||
|
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
|
||||||
|
expect(docDepth2.postID).toBe(post.id)
|
||||||
|
const docDepth0 = await payload.findByID({ collection: 'virtual-relations', id, depth: 0 })
|
||||||
|
expect(docDepth0.postID).toBe(post.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow virtual field as reference to custom ID', async () => {
|
||||||
|
const customID = await payload.create({ collection: 'custom-ids', data: {} })
|
||||||
|
const { id } = await payload.create({
|
||||||
|
collection: 'virtual-relations',
|
||||||
|
depth: 0,
|
||||||
|
data: { customID: customID.id },
|
||||||
|
})
|
||||||
|
|
||||||
|
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
|
||||||
|
expect(docDepth2.customIDValue).toBe(customID.id)
|
||||||
|
const docDepth0 = await payload.findByID({
|
||||||
|
collection: 'virtual-relations',
|
||||||
|
id,
|
||||||
|
depth: 0,
|
||||||
|
})
|
||||||
|
expect(docDepth0.customIDValue).toBe(customID.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow deep virtual field as reference to ID', async () => {
|
||||||
|
const category = await payload.create({
|
||||||
|
collection: 'categories',
|
||||||
|
data: { title: 'category-3' },
|
||||||
|
})
|
||||||
|
const post = await payload.create({
|
||||||
|
collection: 'posts',
|
||||||
|
data: { category: category.id, title: 'my-title-3' },
|
||||||
|
})
|
||||||
|
const { id } = await payload.create({
|
||||||
|
collection: 'virtual-relations',
|
||||||
|
depth: 0,
|
||||||
|
data: { post: post.id },
|
||||||
|
})
|
||||||
|
|
||||||
|
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
|
||||||
|
expect(docDepth2.postCategoryID).toBe(category.id)
|
||||||
|
const docDepth0 = await payload.findByID({ collection: 'virtual-relations', id, depth: 0 })
|
||||||
|
expect(docDepth0.postCategoryID).toBe(category.id)
|
||||||
|
})
|
||||||
|
|
||||||
it('should allow virtual field with reference localized', async () => {
|
it('should allow virtual field with reference localized', async () => {
|
||||||
const post = await payload.create({
|
const post = await payload.create({
|
||||||
collection: 'posts',
|
collection: 'posts',
|
||||||
|
|||||||
@@ -373,8 +373,39 @@ export interface VirtualRelation {
|
|||||||
id: string;
|
id: string;
|
||||||
postTitle?: string | null;
|
postTitle?: string | null;
|
||||||
postCategoryTitle?: string | null;
|
postCategoryTitle?: string | null;
|
||||||
|
postCategoryID?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
postID?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
postLocalized?: string | null;
|
postLocalized?: string | null;
|
||||||
post?: (string | null) | Post;
|
post?: (string | null) | Post;
|
||||||
|
customID?: (string | null) | CustomId;
|
||||||
|
customIDValue?: string | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
_status?: ('draft' | 'published') | null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "custom-ids".
|
||||||
|
*/
|
||||||
|
export interface CustomId {
|
||||||
|
id: string;
|
||||||
|
title?: string | null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
@@ -398,17 +429,6 @@ export interface FieldsPersistance {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
|
||||||
* via the `definition` "custom-ids".
|
|
||||||
*/
|
|
||||||
export interface CustomId {
|
|
||||||
id: string;
|
|
||||||
title?: string | null;
|
|
||||||
updatedAt: string;
|
|
||||||
createdAt: string;
|
|
||||||
_status?: ('draft' | 'published') | null;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "fake-custom-ids".
|
* via the `definition` "fake-custom-ids".
|
||||||
@@ -807,8 +827,12 @@ export interface PlacesSelect<T extends boolean = true> {
|
|||||||
export interface VirtualRelationsSelect<T extends boolean = true> {
|
export interface VirtualRelationsSelect<T extends boolean = true> {
|
||||||
postTitle?: T;
|
postTitle?: T;
|
||||||
postCategoryTitle?: T;
|
postCategoryTitle?: T;
|
||||||
|
postCategoryID?: T;
|
||||||
|
postID?: T;
|
||||||
postLocalized?: T;
|
postLocalized?: T;
|
||||||
post?: T;
|
post?: T;
|
||||||
|
customID?: T;
|
||||||
|
customIDValue?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
_status?: T;
|
_status?: T;
|
||||||
|
|||||||
Reference in New Issue
Block a user