Skip to content

Commit 2d2bdf6

Browse files
r1tsuukendelljoseph
authored andcommitted
perf: optimize virtual fields that reference ID (#12159)
This PR optimizes the new virtual fields with relationships feature #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.
1 parent 308ad79 commit 2d2bdf6

File tree

4 files changed

+113
-12
lines changed

4 files changed

+113
-12
lines changed

packages/payload/src/fields/hooks/afterRead/virtualFieldPopulationPromise.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ export const virtualFieldPopulationPromise = async ({
8585
docID = currentValue
8686
}
8787

88+
if (segments[0] === 'id' && segments.length === 0) {
89+
siblingDoc[name] = docID
90+
return
91+
}
92+
8893
if (typeof docID !== 'string' && typeof docID !== 'number') {
8994
return
9095
}

test/database/config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,16 @@ export default buildConfigWithDefaults({
471471
type: 'text',
472472
virtual: 'post.category.title',
473473
},
474+
{
475+
name: 'postCategoryID',
476+
type: 'json',
477+
virtual: 'post.category.id',
478+
},
479+
{
480+
name: 'postID',
481+
type: 'json',
482+
virtual: 'post.id',
483+
},
474484
{
475485
name: 'postLocalized',
476486
type: 'text',
@@ -481,6 +491,16 @@ export default buildConfigWithDefaults({
481491
type: 'relationship',
482492
relationTo: 'posts',
483493
},
494+
{
495+
name: 'customID',
496+
type: 'relationship',
497+
relationTo: 'custom-ids',
498+
},
499+
{
500+
name: 'customIDValue',
501+
type: 'text',
502+
virtual: 'customID.id',
503+
},
484504
],
485505
versions: { drafts: true },
486506
},

test/database/int.spec.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1993,11 +1993,63 @@ describe('database', () => {
19931993
collection: 'virtual-relations',
19941994
depth: 0,
19951995
where: { id: { equals: id } },
1996-
draft: true,
19971996
})
19981997
expect(draft.docs[0]?.postTitle).toBe('my-title')
19991998
})
20001999

2000+
it('should allow virtual field as reference to ID', async () => {
2001+
const post = await payload.create({ collection: 'posts', data: { title: 'my-title' } })
2002+
const { id } = await payload.create({
2003+
collection: 'virtual-relations',
2004+
depth: 0,
2005+
data: { post: post.id },
2006+
})
2007+
2008+
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
2009+
expect(docDepth2.postID).toBe(post.id)
2010+
const docDepth0 = await payload.findByID({ collection: 'virtual-relations', id, depth: 0 })
2011+
expect(docDepth0.postID).toBe(post.id)
2012+
})
2013+
2014+
it('should allow virtual field as reference to custom ID', async () => {
2015+
const customID = await payload.create({ collection: 'custom-ids', data: {} })
2016+
const { id } = await payload.create({
2017+
collection: 'virtual-relations',
2018+
depth: 0,
2019+
data: { customID: customID.id },
2020+
})
2021+
2022+
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
2023+
expect(docDepth2.customIDValue).toBe(customID.id)
2024+
const docDepth0 = await payload.findByID({
2025+
collection: 'virtual-relations',
2026+
id,
2027+
depth: 0,
2028+
})
2029+
expect(docDepth0.customIDValue).toBe(customID.id)
2030+
})
2031+
2032+
it('should allow deep virtual field as reference to ID', async () => {
2033+
const category = await payload.create({
2034+
collection: 'categories',
2035+
data: { title: 'category-3' },
2036+
})
2037+
const post = await payload.create({
2038+
collection: 'posts',
2039+
data: { category: category.id, title: 'my-title-3' },
2040+
})
2041+
const { id } = await payload.create({
2042+
collection: 'virtual-relations',
2043+
depth: 0,
2044+
data: { post: post.id },
2045+
})
2046+
2047+
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
2048+
expect(docDepth2.postCategoryID).toBe(category.id)
2049+
const docDepth0 = await payload.findByID({ collection: 'virtual-relations', id, depth: 0 })
2050+
expect(docDepth0.postCategoryID).toBe(category.id)
2051+
})
2052+
20012053
it('should allow virtual field with reference localized', async () => {
20022054
const post = await payload.create({
20032055
collection: 'posts',

test/database/payload-types.ts

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,39 @@ export interface VirtualRelation {
373373
id: string;
374374
postTitle?: string | null;
375375
postCategoryTitle?: string | null;
376+
postCategoryID?:
377+
| {
378+
[k: string]: unknown;
379+
}
380+
| unknown[]
381+
| string
382+
| number
383+
| boolean
384+
| null;
385+
postID?:
386+
| {
387+
[k: string]: unknown;
388+
}
389+
| unknown[]
390+
| string
391+
| number
392+
| boolean
393+
| null;
376394
postLocalized?: string | null;
377395
post?: (string | null) | Post;
396+
customID?: (string | null) | CustomId;
397+
customIDValue?: string | null;
398+
updatedAt: string;
399+
createdAt: string;
400+
_status?: ('draft' | 'published') | null;
401+
}
402+
/**
403+
* This interface was referenced by `Config`'s JSON-Schema
404+
* via the `definition` "custom-ids".
405+
*/
406+
export interface CustomId {
407+
id: string;
408+
title?: string | null;
378409
updatedAt: string;
379410
createdAt: string;
380411
_status?: ('draft' | 'published') | null;
@@ -398,17 +429,6 @@ export interface FieldsPersistance {
398429
updatedAt: string;
399430
createdAt: string;
400431
}
401-
/**
402-
* This interface was referenced by `Config`'s JSON-Schema
403-
* via the `definition` "custom-ids".
404-
*/
405-
export interface CustomId {
406-
id: string;
407-
title?: string | null;
408-
updatedAt: string;
409-
createdAt: string;
410-
_status?: ('draft' | 'published') | null;
411-
}
412432
/**
413433
* This interface was referenced by `Config`'s JSON-Schema
414434
* via the `definition` "fake-custom-ids".
@@ -807,8 +827,12 @@ export interface PlacesSelect<T extends boolean = true> {
807827
export interface VirtualRelationsSelect<T extends boolean = true> {
808828
postTitle?: T;
809829
postCategoryTitle?: T;
830+
postCategoryID?: T;
831+
postID?: T;
810832
postLocalized?: T;
811833
post?: T;
834+
customID?: T;
835+
customIDValue?: T;
812836
updatedAt?: T;
813837
createdAt?: T;
814838
_status?: T;

0 commit comments

Comments
 (0)