feat(db-*): add updateMany method to database adapter (#11441)
This PR adds a new `payload.db.updateMany` method, which is a more performant way to update multiple documents compared to using `payload.update`.
This commit is contained in:
@@ -16,6 +16,7 @@ import type {
|
|||||||
TypeWithVersion,
|
TypeWithVersion,
|
||||||
UpdateGlobalArgs,
|
UpdateGlobalArgs,
|
||||||
UpdateGlobalVersionArgs,
|
UpdateGlobalVersionArgs,
|
||||||
|
UpdateManyArgs,
|
||||||
UpdateOneArgs,
|
UpdateOneArgs,
|
||||||
UpdateVersionArgs,
|
UpdateVersionArgs,
|
||||||
} from 'payload'
|
} from 'payload'
|
||||||
@@ -53,6 +54,7 @@ import { commitTransaction } from './transactions/commitTransaction.js'
|
|||||||
import { rollbackTransaction } from './transactions/rollbackTransaction.js'
|
import { rollbackTransaction } from './transactions/rollbackTransaction.js'
|
||||||
import { updateGlobal } from './updateGlobal.js'
|
import { updateGlobal } from './updateGlobal.js'
|
||||||
import { updateGlobalVersion } from './updateGlobalVersion.js'
|
import { updateGlobalVersion } from './updateGlobalVersion.js'
|
||||||
|
import { updateMany } from './updateMany.js'
|
||||||
import { updateOne } from './updateOne.js'
|
import { updateOne } from './updateOne.js'
|
||||||
import { updateVersion } from './updateVersion.js'
|
import { updateVersion } from './updateVersion.js'
|
||||||
import { upsert } from './upsert.js'
|
import { upsert } from './upsert.js'
|
||||||
@@ -160,6 +162,7 @@ declare module 'payload' {
|
|||||||
updateGlobalVersion: <T extends TypeWithID = TypeWithID>(
|
updateGlobalVersion: <T extends TypeWithID = TypeWithID>(
|
||||||
args: { options?: QueryOptions } & UpdateGlobalVersionArgs<T>,
|
args: { options?: QueryOptions } & UpdateGlobalVersionArgs<T>,
|
||||||
) => Promise<TypeWithVersion<T>>
|
) => Promise<TypeWithVersion<T>>
|
||||||
|
|
||||||
updateOne: (args: { options?: QueryOptions } & UpdateOneArgs) => Promise<Document>
|
updateOne: (args: { options?: QueryOptions } & UpdateOneArgs) => Promise<Document>
|
||||||
updateVersion: <T extends TypeWithID = TypeWithID>(
|
updateVersion: <T extends TypeWithID = TypeWithID>(
|
||||||
args: { options?: QueryOptions } & UpdateVersionArgs<T>,
|
args: { options?: QueryOptions } & UpdateVersionArgs<T>,
|
||||||
@@ -200,6 +203,7 @@ export function mongooseAdapter({
|
|||||||
mongoMemoryServer,
|
mongoMemoryServer,
|
||||||
sessions: {},
|
sessions: {},
|
||||||
transactionOptions: transactionOptions === false ? undefined : transactionOptions,
|
transactionOptions: transactionOptions === false ? undefined : transactionOptions,
|
||||||
|
updateMany,
|
||||||
url,
|
url,
|
||||||
versions: {},
|
versions: {},
|
||||||
// DatabaseAdapter
|
// DatabaseAdapter
|
||||||
|
|||||||
61
packages/db-mongodb/src/updateMany.ts
Normal file
61
packages/db-mongodb/src/updateMany.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import type { MongooseUpdateQueryOptions } from 'mongoose'
|
||||||
|
import type { UpdateMany } from 'payload'
|
||||||
|
|
||||||
|
import type { MongooseAdapter } from './index.js'
|
||||||
|
|
||||||
|
import { buildQuery } from './queries/buildQuery.js'
|
||||||
|
import { buildProjectionFromSelect } from './utilities/buildProjectionFromSelect.js'
|
||||||
|
import { getSession } from './utilities/getSession.js'
|
||||||
|
import { handleError } from './utilities/handleError.js'
|
||||||
|
import { transform } from './utilities/transform.js'
|
||||||
|
|
||||||
|
export const updateMany: UpdateMany = async function updateMany(
|
||||||
|
this: MongooseAdapter,
|
||||||
|
{ collection, data, locale, options: optionsArgs = {}, req, returning, select, where },
|
||||||
|
) {
|
||||||
|
const Model = this.collections[collection]
|
||||||
|
const fields = this.payload.collections[collection].config.fields
|
||||||
|
|
||||||
|
const options: MongooseUpdateQueryOptions = {
|
||||||
|
...optionsArgs,
|
||||||
|
lean: true,
|
||||||
|
new: true,
|
||||||
|
projection: buildProjectionFromSelect({
|
||||||
|
adapter: this,
|
||||||
|
fields: this.payload.collections[collection].config.flattenedFields,
|
||||||
|
select,
|
||||||
|
}),
|
||||||
|
session: await getSession(this, req),
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = await buildQuery({
|
||||||
|
adapter: this,
|
||||||
|
collectionSlug: collection,
|
||||||
|
fields: this.payload.collections[collection].config.flattenedFields,
|
||||||
|
locale,
|
||||||
|
where,
|
||||||
|
})
|
||||||
|
|
||||||
|
transform({ adapter: this, data, fields, operation: 'write' })
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Model.updateMany(query, data, options)
|
||||||
|
} catch (error) {
|
||||||
|
handleError({ collection, error, req })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returning === false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await Model.find(query, {}, options)
|
||||||
|
|
||||||
|
transform({
|
||||||
|
adapter: this,
|
||||||
|
data: result,
|
||||||
|
fields,
|
||||||
|
operation: 'read',
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
rollbackTransaction,
|
rollbackTransaction,
|
||||||
updateGlobal,
|
updateGlobal,
|
||||||
updateGlobalVersion,
|
updateGlobalVersion,
|
||||||
|
updateMany,
|
||||||
updateOne,
|
updateOne,
|
||||||
updateVersion,
|
updateVersion,
|
||||||
} from '@payloadcms/drizzle'
|
} from '@payloadcms/drizzle'
|
||||||
@@ -185,6 +186,7 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
|
|||||||
rollbackTransaction,
|
rollbackTransaction,
|
||||||
updateGlobal,
|
updateGlobal,
|
||||||
updateGlobalVersion,
|
updateGlobalVersion,
|
||||||
|
updateMany,
|
||||||
updateOne,
|
updateOne,
|
||||||
updateVersion,
|
updateVersion,
|
||||||
upsert: updateOne,
|
upsert: updateOne,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
rollbackTransaction,
|
rollbackTransaction,
|
||||||
updateGlobal,
|
updateGlobal,
|
||||||
updateGlobalVersion,
|
updateGlobalVersion,
|
||||||
|
updateMany,
|
||||||
updateOne,
|
updateOne,
|
||||||
updateVersion,
|
updateVersion,
|
||||||
} from '@payloadcms/drizzle'
|
} from '@payloadcms/drizzle'
|
||||||
@@ -120,6 +121,7 @@ export function sqliteAdapter(args: Args): DatabaseAdapterObj<SQLiteAdapter> {
|
|||||||
tableNameMap: new Map<string, string>(),
|
tableNameMap: new Map<string, string>(),
|
||||||
tables: {},
|
tables: {},
|
||||||
transactionOptions: args.transactionOptions || undefined,
|
transactionOptions: args.transactionOptions || undefined,
|
||||||
|
updateMany,
|
||||||
versionsSuffix: args.versionsSuffix || '_v',
|
versionsSuffix: args.versionsSuffix || '_v',
|
||||||
|
|
||||||
// DatabaseAdapter
|
// DatabaseAdapter
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
rollbackTransaction,
|
rollbackTransaction,
|
||||||
updateGlobal,
|
updateGlobal,
|
||||||
updateGlobalVersion,
|
updateGlobalVersion,
|
||||||
|
updateMany,
|
||||||
updateOne,
|
updateOne,
|
||||||
updateVersion,
|
updateVersion,
|
||||||
} from '@payloadcms/drizzle'
|
} from '@payloadcms/drizzle'
|
||||||
@@ -186,6 +187,7 @@ export function vercelPostgresAdapter(args: Args = {}): DatabaseAdapterObj<Verce
|
|||||||
rollbackTransaction,
|
rollbackTransaction,
|
||||||
updateGlobal,
|
updateGlobal,
|
||||||
updateGlobalVersion,
|
updateGlobalVersion,
|
||||||
|
updateMany,
|
||||||
updateOne,
|
updateOne,
|
||||||
updateVersion,
|
updateVersion,
|
||||||
upsert: updateOne,
|
upsert: updateOne,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export { commitTransaction } from './transactions/commitTransaction.js'
|
|||||||
export { rollbackTransaction } from './transactions/rollbackTransaction.js'
|
export { rollbackTransaction } from './transactions/rollbackTransaction.js'
|
||||||
export { updateGlobal } from './updateGlobal.js'
|
export { updateGlobal } from './updateGlobal.js'
|
||||||
export { updateGlobalVersion } from './updateGlobalVersion.js'
|
export { updateGlobalVersion } from './updateGlobalVersion.js'
|
||||||
|
export { updateMany } from './updateMany.js'
|
||||||
export { updateOne } from './updateOne.js'
|
export { updateOne } from './updateOne.js'
|
||||||
export { updateVersion } from './updateVersion.js'
|
export { updateVersion } from './updateVersion.js'
|
||||||
export { upsertRow } from './upsertRow/index.js'
|
export { upsertRow } from './upsertRow/index.js'
|
||||||
|
|||||||
97
packages/drizzle/src/updateMany.ts
Normal file
97
packages/drizzle/src/updateMany.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import type { LibSQLDatabase } from 'drizzle-orm/libsql'
|
||||||
|
import type { UpdateMany } from 'payload'
|
||||||
|
|
||||||
|
import toSnakeCase from 'to-snake-case'
|
||||||
|
|
||||||
|
import type { DrizzleAdapter } from './types.js'
|
||||||
|
|
||||||
|
import buildQuery from './queries/buildQuery.js'
|
||||||
|
import { selectDistinct } from './queries/selectDistinct.js'
|
||||||
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
import { getTransaction } from './utilities/getTransaction.js'
|
||||||
|
|
||||||
|
export const updateMany: UpdateMany = async function updateMany(
|
||||||
|
this: DrizzleAdapter,
|
||||||
|
{
|
||||||
|
collection: collectionSlug,
|
||||||
|
data,
|
||||||
|
joins: joinQuery,
|
||||||
|
locale,
|
||||||
|
req,
|
||||||
|
returning,
|
||||||
|
select,
|
||||||
|
where: whereToUse,
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const db = await getTransaction(this, req)
|
||||||
|
const collection = this.payload.collections[collectionSlug].config
|
||||||
|
const tableName = this.tableNameMap.get(toSnakeCase(collection.slug))
|
||||||
|
|
||||||
|
const { joins, selectFields, where } = buildQuery({
|
||||||
|
adapter: this,
|
||||||
|
fields: collection.flattenedFields,
|
||||||
|
locale,
|
||||||
|
tableName,
|
||||||
|
where: whereToUse,
|
||||||
|
})
|
||||||
|
|
||||||
|
let idsToUpdate: (number | string)[] = []
|
||||||
|
|
||||||
|
const selectDistinctResult = await selectDistinct({
|
||||||
|
adapter: this,
|
||||||
|
db,
|
||||||
|
joins,
|
||||||
|
selectFields,
|
||||||
|
tableName,
|
||||||
|
where,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (selectDistinctResult?.[0]?.id) {
|
||||||
|
idsToUpdate = selectDistinctResult?.map((doc) => doc.id)
|
||||||
|
|
||||||
|
// If id wasn't passed but `where` without any joins, retrieve it with findFirst
|
||||||
|
} else if (whereToUse && !joins.length) {
|
||||||
|
const _db = db as LibSQLDatabase
|
||||||
|
|
||||||
|
const table = this.tables[tableName]
|
||||||
|
|
||||||
|
const docsToUpdate = await _db
|
||||||
|
.select({
|
||||||
|
id: table.id,
|
||||||
|
})
|
||||||
|
.from(table)
|
||||||
|
.where(where)
|
||||||
|
|
||||||
|
idsToUpdate = docsToUpdate?.map((doc) => doc.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!idsToUpdate.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = []
|
||||||
|
|
||||||
|
// TODO: We need to batch this to reduce the amount of db calls. This can get very slow if we are updating a lot of rows.
|
||||||
|
for (const idToUpdate of idsToUpdate) {
|
||||||
|
const result = await upsertRow({
|
||||||
|
id: idToUpdate,
|
||||||
|
adapter: this,
|
||||||
|
data,
|
||||||
|
db,
|
||||||
|
fields: collection.flattenedFields,
|
||||||
|
ignoreResult: returning === false,
|
||||||
|
joinQuery,
|
||||||
|
operation: 'update',
|
||||||
|
req,
|
||||||
|
select,
|
||||||
|
tableName,
|
||||||
|
})
|
||||||
|
results.push(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returning === false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
@@ -145,6 +145,8 @@ export interface BaseDatabaseAdapter {
|
|||||||
|
|
||||||
updateGlobalVersion: UpdateGlobalVersion
|
updateGlobalVersion: UpdateGlobalVersion
|
||||||
|
|
||||||
|
updateMany: UpdateMany
|
||||||
|
|
||||||
updateOne: UpdateOne
|
updateOne: UpdateOne
|
||||||
|
|
||||||
updateVersion: UpdateVersion
|
updateVersion: UpdateVersion
|
||||||
@@ -510,6 +512,29 @@ export type UpdateOneArgs = {
|
|||||||
*/
|
*/
|
||||||
export type UpdateOne = (args: UpdateOneArgs) => Promise<Document>
|
export type UpdateOne = (args: UpdateOneArgs) => Promise<Document>
|
||||||
|
|
||||||
|
export type UpdateManyArgs = {
|
||||||
|
collection: CollectionSlug
|
||||||
|
data: Record<string, unknown>
|
||||||
|
draft?: boolean
|
||||||
|
joins?: JoinQuery
|
||||||
|
locale?: string
|
||||||
|
/**
|
||||||
|
* Additional database adapter specific options to pass to the query
|
||||||
|
*/
|
||||||
|
options?: Record<string, unknown>
|
||||||
|
req?: Partial<PayloadRequest>
|
||||||
|
/**
|
||||||
|
* If true, returns the updated documents
|
||||||
|
*
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
returning?: boolean
|
||||||
|
select?: SelectType
|
||||||
|
where: Where
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UpdateMany = (args: UpdateManyArgs) => Promise<Document[] | null>
|
||||||
|
|
||||||
export type UpsertArgs = {
|
export type UpsertArgs = {
|
||||||
collection: CollectionSlug
|
collection: CollectionSlug
|
||||||
data: Record<string, unknown>
|
data: Record<string, unknown>
|
||||||
|
|||||||
@@ -1112,6 +1112,7 @@ export type {
|
|||||||
Connect,
|
Connect,
|
||||||
Count,
|
Count,
|
||||||
CountArgs,
|
CountArgs,
|
||||||
|
CountGlobalVersionArgs,
|
||||||
CountGlobalVersions,
|
CountGlobalVersions,
|
||||||
CountVersions,
|
CountVersions,
|
||||||
Create,
|
Create,
|
||||||
@@ -1156,6 +1157,8 @@ export type {
|
|||||||
UpdateGlobalArgs,
|
UpdateGlobalArgs,
|
||||||
UpdateGlobalVersion,
|
UpdateGlobalVersion,
|
||||||
UpdateGlobalVersionArgs,
|
UpdateGlobalVersionArgs,
|
||||||
|
UpdateMany,
|
||||||
|
UpdateManyArgs,
|
||||||
UpdateOne,
|
UpdateOne,
|
||||||
UpdateOneArgs,
|
UpdateOneArgs,
|
||||||
UpdateVersion,
|
UpdateVersion,
|
||||||
|
|||||||
@@ -8,7 +8,21 @@ import { v4 as uuid } from 'uuid'
|
|||||||
|
|
||||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||||
import { devUser } from '../credentials.js'
|
import { devUser } from '../credentials.js'
|
||||||
import { errorOnUnnamedFieldsSlug, postsSlug } from './shared.js'
|
import { seed } from './seed.js'
|
||||||
|
import {
|
||||||
|
customIDsSlug,
|
||||||
|
customSchemaSlug,
|
||||||
|
defaultValuesSlug,
|
||||||
|
errorOnUnnamedFieldsSlug,
|
||||||
|
fakeCustomIDsSlug,
|
||||||
|
fieldsPersistanceSlug,
|
||||||
|
pgMigrationSlug,
|
||||||
|
placesSlug,
|
||||||
|
postsSlug,
|
||||||
|
relationASlug,
|
||||||
|
relationBSlug,
|
||||||
|
relationshipsMigrationSlug,
|
||||||
|
} from './shared.js'
|
||||||
|
|
||||||
const defaultValueField: TextField = {
|
const defaultValueField: TextField = {
|
||||||
name: 'defaultValue',
|
name: 'defaultValue',
|
||||||
@@ -183,7 +197,7 @@ export default buildConfigWithDefaults({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'default-values',
|
slug: defaultValuesSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
@@ -222,7 +236,7 @@ export default buildConfigWithDefaults({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'relation-a',
|
slug: relationASlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
@@ -239,7 +253,7 @@ export default buildConfigWithDefaults({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'relation-b',
|
slug: relationBSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
@@ -261,7 +275,7 @@ export default buildConfigWithDefaults({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'pg-migrations',
|
slug: pgMigrationSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'relation1',
|
name: 'relation1',
|
||||||
@@ -329,7 +343,7 @@ export default buildConfigWithDefaults({
|
|||||||
versions: true,
|
versions: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'custom-schema',
|
slug: customSchemaSlug,
|
||||||
dbName: 'customs',
|
dbName: 'customs',
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
@@ -404,7 +418,7 @@ export default buildConfigWithDefaults({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'places',
|
slug: placesSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'country',
|
name: 'country',
|
||||||
@@ -417,7 +431,7 @@ export default buildConfigWithDefaults({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'fields-persistance',
|
slug: fieldsPersistanceSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'text',
|
name: 'text',
|
||||||
@@ -475,7 +489,7 @@ export default buildConfigWithDefaults({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'custom-ids',
|
slug: customIDsSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'id',
|
name: 'id',
|
||||||
@@ -502,7 +516,7 @@ export default buildConfigWithDefaults({
|
|||||||
versions: { drafts: true },
|
versions: { drafts: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'fake-custom-ids',
|
slug: fakeCustomIDsSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
@@ -535,7 +549,7 @@ export default buildConfigWithDefaults({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'relationships-migration',
|
slug: relationshipsMigrationSlug,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
type: 'relationship',
|
type: 'relationship',
|
||||||
@@ -587,13 +601,9 @@ export default buildConfigWithDefaults({
|
|||||||
locales: ['en', 'es'],
|
locales: ['en', 'es'],
|
||||||
},
|
},
|
||||||
onInit: async (payload) => {
|
onInit: async (payload) => {
|
||||||
await payload.create({
|
if (process.env.SEED_IN_CONFIG_ONINIT !== 'false') {
|
||||||
collection: 'users',
|
await seed(payload)
|
||||||
data: {
|
}
|
||||||
email: devUser.email,
|
|
||||||
password: devUser.password,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
typescript: {
|
typescript: {
|
||||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { devUser } from '../credentials.js'
|
|||||||
import { initPayloadInt } from '../helpers/initPayloadInt.js'
|
import { initPayloadInt } from '../helpers/initPayloadInt.js'
|
||||||
import { isMongoose } from '../helpers/isMongoose.js'
|
import { isMongoose } from '../helpers/isMongoose.js'
|
||||||
import removeFiles from '../helpers/removeFiles.js'
|
import removeFiles from '../helpers/removeFiles.js'
|
||||||
|
import { seed } from './seed.js'
|
||||||
import { errorOnUnnamedFieldsSlug, postsSlug } from './shared.js'
|
import { errorOnUnnamedFieldsSlug, postsSlug } from './shared.js'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
@@ -43,9 +44,17 @@ process.env.PAYLOAD_CONFIG_PATH = path.join(dirname, 'config.ts')
|
|||||||
|
|
||||||
describe('database', () => {
|
describe('database', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||||
;({ payload, restClient } = await initPayloadInt(dirname))
|
;({ payload, restClient } = await initPayloadInt(dirname))
|
||||||
payload.db.migrationDir = path.join(dirname, './migrations')
|
payload.db.migrationDir = path.join(dirname, './migrations')
|
||||||
|
|
||||||
|
await seed(payload)
|
||||||
|
|
||||||
|
await restClient.login({
|
||||||
|
slug: 'users',
|
||||||
|
credentials: devUser,
|
||||||
|
})
|
||||||
|
|
||||||
const loginResult = await payload.login({
|
const loginResult = await payload.login({
|
||||||
collection: 'users',
|
collection: 'users',
|
||||||
data: {
|
data: {
|
||||||
@@ -794,6 +803,7 @@ describe('database', () => {
|
|||||||
data: {
|
data: {
|
||||||
title,
|
title,
|
||||||
},
|
},
|
||||||
|
depth: 0,
|
||||||
disableTransaction: true,
|
disableTransaction: true,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -876,6 +886,80 @@ describe('database', () => {
|
|||||||
|
|
||||||
expect(result.point).toEqual([5, 10])
|
expect(result.point).toEqual([5, 10])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('ensure updateMany updates all docs and respects where query', async () => {
|
||||||
|
await payload.db.deleteMany({
|
||||||
|
collection: postsSlug,
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
exists: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await payload.create({
|
||||||
|
collection: postsSlug,
|
||||||
|
data: {
|
||||||
|
title: 'notupdated',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create 5 posts
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
await payload.create({
|
||||||
|
collection: postsSlug,
|
||||||
|
data: {
|
||||||
|
title: `v1 ${i}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await payload.db.updateMany({
|
||||||
|
collection: postsSlug,
|
||||||
|
data: {
|
||||||
|
title: 'updated',
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
title: {
|
||||||
|
not_equals: 'notupdated',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result?.length).toBe(5)
|
||||||
|
expect(result?.[0]?.title).toBe('updated')
|
||||||
|
expect(result?.[4]?.title).toBe('updated')
|
||||||
|
|
||||||
|
// Ensure all posts minus the one we don't want updated are updated
|
||||||
|
const { docs } = await payload.find({
|
||||||
|
collection: postsSlug,
|
||||||
|
depth: 0,
|
||||||
|
pagination: false,
|
||||||
|
where: {
|
||||||
|
title: {
|
||||||
|
equals: 'updated',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(docs).toHaveLength(5)
|
||||||
|
expect(docs?.[0]?.title).toBe('updated')
|
||||||
|
expect(docs?.[4]?.title).toBe('updated')
|
||||||
|
|
||||||
|
const { docs: notUpdatedDocs } = await payload.find({
|
||||||
|
collection: postsSlug,
|
||||||
|
depth: 0,
|
||||||
|
pagination: false,
|
||||||
|
where: {
|
||||||
|
title: {
|
||||||
|
not_equals: 'updated',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(notUpdatedDocs).toHaveLength(1)
|
||||||
|
expect(notUpdatedDocs?.[0]?.title).toBe('notupdated')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Error Handler', () => {
|
describe('Error Handler', () => {
|
||||||
|
|||||||
26
test/database/seed.ts
Normal file
26
test/database/seed.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import type { Payload } from 'payload'
|
||||||
|
|
||||||
|
import path from 'path'
|
||||||
|
import { getFileByPath } from 'payload'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
|
import { devUser } from '../credentials.js'
|
||||||
|
import { seedDB } from '../helpers/seed.js'
|
||||||
|
import { collectionSlugs } from './shared.js'
|
||||||
|
|
||||||
|
const filename = fileURLToPath(import.meta.url)
|
||||||
|
const dirname = path.dirname(filename)
|
||||||
|
|
||||||
|
export const _seed = async (_payload: Payload) => {
|
||||||
|
await _payload.create({
|
||||||
|
collection: 'users',
|
||||||
|
data: {
|
||||||
|
email: devUser.email,
|
||||||
|
password: devUser.password,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function seed(_payload: Payload) {
|
||||||
|
return await _seed(_payload)
|
||||||
|
}
|
||||||
@@ -1,2 +1,37 @@
|
|||||||
export const postsSlug = 'posts'
|
export const postsSlug = 'posts'
|
||||||
export const errorOnUnnamedFieldsSlug = 'error-on-unnamed-fields'
|
export const errorOnUnnamedFieldsSlug = 'error-on-unnamed-fields'
|
||||||
|
|
||||||
|
export const defaultValuesSlug = 'default-values'
|
||||||
|
|
||||||
|
export const relationASlug = 'relation-a'
|
||||||
|
|
||||||
|
export const relationBSlug = 'relation-b'
|
||||||
|
|
||||||
|
export const pgMigrationSlug = 'pg-migrations'
|
||||||
|
|
||||||
|
export const customSchemaSlug = 'custom-schema'
|
||||||
|
|
||||||
|
export const placesSlug = 'places'
|
||||||
|
|
||||||
|
export const fieldsPersistanceSlug = 'fields-persistance'
|
||||||
|
|
||||||
|
export const customIDsSlug = 'custom-ids'
|
||||||
|
|
||||||
|
export const fakeCustomIDsSlug = 'fake-custom-ids'
|
||||||
|
|
||||||
|
export const relationshipsMigrationSlug = 'relationships-migration'
|
||||||
|
|
||||||
|
export const collectionSlugs = [
|
||||||
|
postsSlug,
|
||||||
|
errorOnUnnamedFieldsSlug,
|
||||||
|
defaultValuesSlug,
|
||||||
|
relationASlug,
|
||||||
|
relationBSlug,
|
||||||
|
pgMigrationSlug,
|
||||||
|
customSchemaSlug,
|
||||||
|
placesSlug,
|
||||||
|
fieldsPersistanceSlug,
|
||||||
|
customIDsSlug,
|
||||||
|
fakeCustomIDsSlug,
|
||||||
|
relationshipsMigrationSlug,
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user