Skip to content

Commit e96d3c8

Browse files
authored
feat(db-*): support sort in db.updateMany (#11768)
This adds support for `sort` in `payload.db.updateMany`. ## Example ```ts const updatedDocs = await payload.db.updateMany({ collection: 'posts', data: { title: 'updated', }, limit: 5, sort: '-numberField', // <= new where: { id: { exists: true, }, }, }) ```
1 parent 68f2582 commit e96d3c8

File tree

7 files changed

+225
-35
lines changed

7 files changed

+225
-35
lines changed

packages/db-mongodb/src/updateMany.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import type { MongooseUpdateQueryOptions } from 'mongoose'
2-
import type { UpdateMany } from 'payload'
2+
3+
import { flattenWhereToOperators, type UpdateMany } from 'payload'
34

45
import type { MongooseAdapter } from './index.js'
56

67
import { buildQuery } from './queries/buildQuery.js'
8+
import { buildSortParam } from './queries/buildSortParam.js'
79
import { buildProjectionFromSelect } from './utilities/buildProjectionFromSelect.js'
810
import { getCollection } from './utilities/getEntity.js'
911
import { getSession } from './utilities/getSession.js'
@@ -21,11 +23,30 @@ export const updateMany: UpdateMany = async function updateMany(
2123
req,
2224
returning,
2325
select,
26+
sort: sortArg,
2427
where,
2528
},
2629
) {
30+
let hasNearConstraint = false
31+
32+
if (where) {
33+
const constraints = flattenWhereToOperators(where)
34+
hasNearConstraint = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near'))
35+
}
36+
2737
const { collectionConfig, Model } = getCollection({ adapter: this, collectionSlug })
2838

39+
let sort: Record<string, unknown> | undefined
40+
if (!hasNearConstraint) {
41+
sort = buildSortParam({
42+
config: this.payload.config,
43+
fields: collectionConfig.flattenedFields,
44+
locale,
45+
sort: sortArg || collectionConfig.defaultSort,
46+
timestamps: true,
47+
})
48+
}
49+
2950
const options: MongooseUpdateQueryOptions = {
3051
...optionsArgs,
3152
lean: true,
@@ -53,7 +74,7 @@ export const updateMany: UpdateMany = async function updateMany(
5374
const documentsToUpdate = await Model.find(
5475
query,
5576
{},
56-
{ ...options, limit, projection: { _id: 1 } },
77+
{ ...options, limit, projection: { _id: 1 }, sort },
5778
)
5879
if (documentsToUpdate.length === 0) {
5980
return null
@@ -71,7 +92,14 @@ export const updateMany: UpdateMany = async function updateMany(
7192
return null
7293
}
7394

74-
const result = await Model.find(query, {}, options)
95+
const result = await Model.find(
96+
query,
97+
{},
98+
{
99+
...options,
100+
sort,
101+
},
102+
)
75103

76104
transform({
77105
adapter: this,

packages/drizzle/src/updateMany.ts

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type { UpdateMany } from 'payload'
33

44
import toSnakeCase from 'to-snake-case'
55

6-
import type { DrizzleAdapter } from './types.js'
6+
import type { ChainedMethods, DrizzleAdapter } from './types.js'
77

8+
import { chainMethods } from './find/chainMethods.js'
89
import buildQuery from './queries/buildQuery.js'
910
import { selectDistinct } from './queries/selectDistinct.js'
1011
import { upsertRow } from './upsertRow/index.js'
@@ -21,17 +22,21 @@ export const updateMany: UpdateMany = async function updateMany(
2122
req,
2223
returning,
2324
select,
25+
sort: sortArg,
2426
where: whereToUse,
2527
},
2628
) {
2729
const db = await getTransaction(this, req)
2830
const collection = this.payload.collections[collectionSlug].config
2931
const tableName = this.tableNameMap.get(toSnakeCase(collection.slug))
3032

31-
const { joins, selectFields, where } = buildQuery({
33+
const sort = sortArg !== undefined && sortArg !== null ? sortArg : collection.defaultSort
34+
35+
const { joins, orderBy, selectFields, where } = buildQuery({
3236
adapter: this,
3337
fields: collection.flattenedFields,
3438
locale,
39+
sort,
3540
tableName,
3641
where: whereToUse,
3742
})
@@ -40,6 +45,14 @@ export const updateMany: UpdateMany = async function updateMany(
4045

4146
const selectDistinctResult = await selectDistinct({
4247
adapter: this,
48+
chainedMethods: orderBy
49+
? [
50+
{
51+
args: [() => orderBy.map(({ column, order }) => order(column))],
52+
method: 'orderBy',
53+
},
54+
]
55+
: [],
4356
db,
4457
joins,
4558
selectFields,
@@ -49,28 +62,35 @@ export const updateMany: UpdateMany = async function updateMany(
4962

5063
if (selectDistinctResult?.[0]?.id) {
5164
idsToUpdate = selectDistinctResult?.map((doc) => doc.id)
52-
53-
// If id wasn't passed but `where` without any joins, retrieve it with findFirst
5465
} else if (whereToUse && !joins.length) {
66+
// If id wasn't passed but `where` without any joins, retrieve it with findFirst
67+
5568
const _db = db as LibSQLDatabase
5669

5770
const table = this.tables[tableName]
5871

59-
const docsToUpdate =
60-
typeof limit === 'number' && limit > 0
61-
? await _db
62-
.select({
63-
id: table.id,
64-
})
65-
.from(table)
66-
.where(where)
67-
.limit(limit)
68-
: await _db
69-
.select({
70-
id: table.id,
71-
})
72-
.from(table)
73-
.where(where)
72+
const query = _db.select({ id: table.id }).from(table).where(where)
73+
74+
const chainedMethods: ChainedMethods = []
75+
76+
if (typeof limit === 'number' && limit > 0) {
77+
chainedMethods.push({
78+
args: [limit],
79+
method: 'limit',
80+
})
81+
}
82+
83+
if (orderBy) {
84+
chainedMethods.push({
85+
args: [() => orderBy.map(({ column, order }) => order(column))],
86+
method: 'orderBy',
87+
})
88+
}
89+
90+
const docsToUpdate = await chainMethods({
91+
methods: chainedMethods,
92+
query,
93+
})
7494

7595
idsToUpdate = docsToUpdate?.map((doc) => doc.id)
7696
}

packages/payload/src/database/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ export type UpdateManyArgs = {
532532
*/
533533
returning?: boolean
534534
select?: SelectType
535+
sort?: Sort
535536
where: Where
536537
}
537538

test/bulk-edit/payload-types.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export interface Config {
8282
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
8383
};
8484
db: {
85-
defaultIDType: string;
85+
defaultIDType: number;
8686
};
8787
globals: {};
8888
globalsSelect: {};
@@ -118,7 +118,7 @@ export interface UserAuthOperations {
118118
* via the `definition` "posts".
119119
*/
120120
export interface Post {
121-
id: string;
121+
id: number;
122122
title?: string | null;
123123
description?: string | null;
124124
defaultValueField?: string | null;
@@ -155,7 +155,7 @@ export interface Post {
155155
* via the `definition` "users".
156156
*/
157157
export interface User {
158-
id: string;
158+
id: number;
159159
updatedAt: string;
160160
createdAt: string;
161161
email: string;
@@ -172,20 +172,20 @@ export interface User {
172172
* via the `definition` "payload-locked-documents".
173173
*/
174174
export interface PayloadLockedDocument {
175-
id: string;
175+
id: number;
176176
document?:
177177
| ({
178178
relationTo: 'posts';
179-
value: string | Post;
179+
value: number | Post;
180180
} | null)
181181
| ({
182182
relationTo: 'users';
183-
value: string | User;
183+
value: number | User;
184184
} | null);
185185
globalSlug?: string | null;
186186
user: {
187187
relationTo: 'users';
188-
value: string | User;
188+
value: number | User;
189189
};
190190
updatedAt: string;
191191
createdAt: string;
@@ -195,10 +195,10 @@ export interface PayloadLockedDocument {
195195
* via the `definition` "payload-preferences".
196196
*/
197197
export interface PayloadPreference {
198-
id: string;
198+
id: number;
199199
user: {
200200
relationTo: 'users';
201-
value: string | User;
201+
value: number | User;
202202
};
203203
key?: string | null;
204204
value?:
@@ -218,7 +218,7 @@ export interface PayloadPreference {
218218
* via the `definition` "payload-migrations".
219219
*/
220220
export interface PayloadMigration {
221-
id: string;
221+
id: number;
222222
name?: string | null;
223223
batch?: number | null;
224224
updatedAt: string;

test/database/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ export default buildConfigWithDefaults({
4444
type: 'text',
4545
required: true,
4646
},
47+
{
48+
name: 'number',
49+
type: 'number',
50+
},
4751
{
4852
type: 'tabs',
4953
tabs: [

0 commit comments

Comments
 (0)