Skip to content

Commit cae300e

Browse files
authored
perf: flattenedFields collection/global property, remove deep copying in validateQueryPaths (#9299)
### What? Improves querying performance of the Local API, reduces copying overhead ### How? Adds `flattenedFields` property for sanitized collection/global config which contains fields in database schema structure. For example, It removes rows / collapsible / unnamed tabs and merges them to the parent `fields`, ignores UI fields, named tabs are added as `type: 'tab'`. This simplifies code in places like Drizzle `transform/traverseFields`. Also, now we can avoid calling `flattenTopLevelFields` which adds some overhead and use `collection.flattenedFields` / `field.flattenedFields`. By refactoring `configToJSONSchema.ts` with `flattenedFields` it also 1. Fixes #9467 2. Fixes types for UI fields were generated for `select` Removes this deep copying for each `where` query constraint https://github.com/payloadcms/payload/blob/58ac784425b411fc28c91dbb3e7df06cc26b6320/packages/payload/src/database/queryValidation/validateQueryPaths.ts#L69-L73 which potentially can add overhead if you have a large collection/global config UPD: The overhead is even much more than in the benchmark below if you have Lexical with blocks. Benchmark in `relationships/int.spec.ts`: ```ts const now = Date.now() for (let i = 0; i < 10; i++) { const now = Date.now() for (let i = 0; i < 300; i++) { const query = await payload.find({ collection: 'chained', where: { 'relation.relation.name': { equals: 'third', }, and: [ { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, { 'relation.relation.name': { equals: 'third', }, }, ], }, }) } payload.logger.info(`#${i + 1} ${Date.now() - now}`) } payload.logger.info(`Total ${Date.now() - now}`) ``` Before: ``` [02:11:48] INFO: #1 3682 [02:11:50] INFO: #2 2199 [02:11:54] INFO: #3 3483 [02:11:56] INFO: #4 2516 [02:11:59] INFO: #5 2467 [02:12:01] INFO: #6 1987 [02:12:03] INFO: #7 1986 [02:12:05] INFO: #8 2375 [02:12:07] INFO: #9 2040 [02:12:09] INFO: #10 1920 [PASS] Relationships > Querying > Nested Querying > should allow querying two levels deep (24667ms) [02:12:09] INFO: Total 24657 ``` After: ``` [02:12:36] INFO: #1 2113 [02:12:38] INFO: #2 1854 [02:12:40] INFO: #3 1700 [02:12:42] INFO: #4 1797 [02:12:44] INFO: #5 2121 [02:12:46] INFO: #6 1774 [02:12:47] INFO: #7 1670 [02:12:49] INFO: #8 1610 [02:12:50] INFO: #9 1596 [02:12:52] INFO: #10 1576 [PASS] Relationships > Querying > Nested Querying > should allow querying two levels deep (17828ms) [02:12:52] INFO: Total 17818 ```
1 parent 8658945 commit cae300e

File tree

106 files changed

+1542
-2230
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+1542
-2230
lines changed

packages/db-mongodb/src/deleteOne.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const deleteOne: DeleteOne = async function deleteOne(
2222
...options,
2323
projection: buildProjectionFromSelect({
2424
adapter: this,
25-
fields: this.payload.collections[collection].config.fields,
25+
fields: this.payload.collections[collection].config.flattenedFields,
2626
select,
2727
}),
2828
}).lean()

packages/db-mongodb/src/find.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const find: Find = async function find(
4242
if (!hasNearConstraint) {
4343
sort = buildSortParam({
4444
config: this.payload.config,
45-
fields: collectionConfig.fields,
45+
fields: collectionConfig.flattenedFields,
4646
locale,
4747
sort: sortArg || collectionConfig.defaultSort,
4848
timestamps: true,
@@ -71,7 +71,7 @@ export const find: Find = async function find(
7171
if (select) {
7272
paginationOptions.projection = buildProjectionFromSelect({
7373
adapter: this,
74-
fields: collectionConfig.fields,
74+
fields: collectionConfig.flattenedFields,
7575
select,
7676
})
7777
}

packages/db-mongodb/src/findGlobal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const findGlobal: FindGlobal = async function findGlobal(
1818
lean: true,
1919
select: buildProjectionFromSelect({
2020
adapter: this,
21-
fields: this.payload.globals.config.find((each) => each.slug === slug).fields,
21+
fields: this.payload.globals.config.find((each) => each.slug === slug).flattenedFields,
2222
select,
2323
}),
2424
}

packages/db-mongodb/src/findGlobalVersions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
2929
const versionFields = buildVersionGlobalFields(
3030
this.payload.config,
3131
this.payload.globals.config.find(({ slug }) => slug === global),
32+
true,
3233
)
3334
const options = {
3435
...(await withSession(this, req)),

packages/db-mongodb/src/findOne.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const findOne: FindOne = async function findOne(
2727

2828
const projection = buildProjectionFromSelect({
2929
adapter: this,
30-
fields: collectionConfig.fields,
30+
fields: collectionConfig.flattenedFields,
3131
select,
3232
})
3333

packages/db-mongodb/src/findVersions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const findVersions: FindVersions = async function findVersions(
4444
if (!hasNearConstraint) {
4545
sort = buildSortParam({
4646
config: this.payload.config,
47-
fields: collectionConfig.fields,
47+
fields: collectionConfig.flattenedFields,
4848
locale,
4949
sort: sortArg || '-updatedAt',
5050
timestamps: true,
@@ -68,7 +68,7 @@ export const findVersions: FindVersions = async function findVersions(
6868
pagination,
6969
projection: buildProjectionFromSelect({
7070
adapter: this,
71-
fields: buildVersionCollectionFields(this.payload.config, collectionConfig),
71+
fields: buildVersionCollectionFields(this.payload.config, collectionConfig, true),
7272
select,
7373
}),
7474
sort,

packages/db-mongodb/src/init.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export const init: Init = function init(this: MongooseAdapter) {
3737
versionSchema.plugin<any, PaginateOptions>(paginate, { useEstimatedCount: true }).plugin(
3838
getBuildQueryPlugin({
3939
collectionSlug: collection.slug,
40-
versionsFields: versionCollectionFields,
40+
versionsFields: buildVersionCollectionFields(this.payload.config, collection, true),
4141
}),
4242
)
4343

@@ -84,9 +84,11 @@ export const init: Init = function init(this: MongooseAdapter) {
8484
},
8585
})
8686

87-
versionSchema
88-
.plugin<any, PaginateOptions>(paginate, { useEstimatedCount: true })
89-
.plugin(getBuildQueryPlugin({ versionsFields: versionGlobalFields }))
87+
versionSchema.plugin<any, PaginateOptions>(paginate, { useEstimatedCount: true }).plugin(
88+
getBuildQueryPlugin({
89+
versionsFields: buildVersionGlobalFields(this.payload.config, global, true),
90+
}),
91+
)
9092

9193
this.versions[global.slug] = mongoose.model(
9294
versionModelName,

packages/db-mongodb/src/queries/buildAndOrConditions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Field, Payload, Where } from 'payload'
1+
import type { FlattenedField, Payload, Where } from 'payload'
22

33
import { parseParams } from './parseParams.js'
44

@@ -11,7 +11,7 @@ export async function buildAndOrConditions({
1111
where,
1212
}: {
1313
collectionSlug?: string
14-
fields: Field[]
14+
fields: FlattenedField[]
1515
globalSlug?: string
1616
locale?: string
1717
payload: Payload

packages/db-mongodb/src/queries/buildQuery.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import type { Field, Payload, Where } from 'payload'
1+
import type { FlattenedField, Payload, Where } from 'payload'
22

33
import { QueryError } from 'payload'
44

55
import { parseParams } from './parseParams.js'
66

77
type GetBuildQueryPluginArgs = {
88
collectionSlug?: string
9-
versionsFields?: Field[]
9+
versionsFields?: FlattenedField[]
1010
}
1111

1212
export type BuildQueryArgs = {
@@ -34,11 +34,11 @@ export const getBuildQueryPlugin = ({
3434
if (!fields) {
3535
if (globalSlug) {
3636
const globalConfig = payload.globals.config.find(({ slug }) => slug === globalSlug)
37-
fields = globalConfig.fields
37+
fields = globalConfig.flattenedFields
3838
}
3939
if (collectionSlug) {
4040
const collectionConfig = payload.collections[collectionSlug].config
41-
fields = collectionConfig.fields
41+
fields = collectionConfig.flattenedFields
4242
}
4343
}
4444
const errors = []

packages/db-mongodb/src/queries/buildSearchParams.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Field, Operator, PathToQuery, Payload } from 'payload'
1+
import type { FlattenedField, Operator, PathToQuery, Payload } from 'payload'
22

33
import { Types } from 'mongoose'
44
import { getLocalizedPaths } from 'payload'
@@ -34,7 +34,7 @@ export async function buildSearchParam({
3434
val,
3535
}: {
3636
collectionSlug?: string
37-
fields: Field[]
37+
fields: FlattenedField[]
3838
globalSlug?: string
3939
incomingPath: string
4040
locale?: string
@@ -68,11 +68,11 @@ export async function buildSearchParam({
6868
field: {
6969
name: 'id',
7070
type: idFieldType,
71-
} as Field,
71+
} as FlattenedField,
7272
path: '_id',
7373
})
7474
} else {
75-
paths = await getLocalizedPaths({
75+
paths = getLocalizedPaths({
7676
collectionSlug,
7777
fields,
7878
globalSlug,

0 commit comments

Comments
 (0)