Commit Graph

550 Commits

Author SHA1 Message Date
Elliot DeNolf
272914c818 chore(release): v3.34.0 [skip ci] 2025-04-10 15:38:35 -04:00
Sasha
466dcd7189 feat: support where querying by join fields (#12075)
### What?
This PR adds support for `where` querying by the join field (don't
confuse with `where` querying of related docs via `joins.where`)

Previously, this didn't work:
```
const categories = await payload.find({
  collection: 'categories',
  where: { 'relatedPosts.title': { equals: 'my-title' } },
})
```

### Why?
This is crucial for bi-directional relationships, can be used for access
control.

### How?
Implements `where` handling for join fields the same as we do for
relationships. In MongoDB it's not as efficient as it can be, the old PR
that improves it and can be updated later is here
https://github.com/payloadcms/payload/pull/8858

Fixes https://github.com/payloadcms/payload/discussions/9683
2025-04-10 15:30:40 -04:00
Elliot DeNolf
36e7c59b4e chore(release): v3.33.0 [skip ci] 2025-04-04 14:52:55 -04:00
Sasha
857e984fbb fix(db-mongodb): querying relationships with where clause as an object with several conditions (#11953)
Fixes https://github.com/payloadcms/payload/issues/11927

When trying to use the following notation:
```ts
const { docs } = await payload.find({
  collection: 'movies',
  depth: 0,
  where: {
    'director.name': { equals: 'Director1' },
    'director.localized': { equals: 'Director1_Localized' },
  },
})
```
Currently, it respects only the latest condition and the first is
ignored.

However, this works fine:
```ts
const { docs } = await payload.find({
  collection: 'movies',
  depth: 0,
  where: {
    and: [
      {
        'director.name': { equals: 'Director1' },
      },
      {
        'director.localized': { equals: 'Director1_Localized' },
      },
    ],
  },
})
```

But this should be an equivalent to
```
 where: {
    'director.name': { equals: 'Director1' },
    'director.localized': { equals: 'Director1_Localized' },
  },
```
2025-04-03 09:07:10 -04:00
Elliot DeNolf
4ac6d21ef6 chore(release): v3.32.0 [skip ci] 2025-04-01 14:27:01 -04:00
Alessio Gravili
c844b4c848 feat: configurable job queue processing order (LIFO/FIFO), allow sequential execution of jobs (#11897)
Previously, jobs were executed in FIFO order on MongoDB, and LIFO on
Postgres, with no way to configure this behavior.

This PR makes FIFO the default on both MongoDB and Postgres and
introduces the following new options to configure the processing order
globally or on a queue-by-queue basis:
- a `processingOrder` property to the jobs config
- a `processingOrder` argument to `payload.jobs.run()` to override
what's set in the jobs config

It also adds a new `sequential` option to `payload.jobs.run()`, which
can be useful for debugging.
2025-03-31 15:00:36 -06:00
Alessio Gravili
9a1c3cf4cc fix: support parallel job queue tasks (#11917)
This adds support for running multiple job queue tasks in parallel
within the same workflow while preventing conflicts. Previously, this
would have caused the following issues:
- Job log entries get lost - the final job log is incomplete, despite
all tasks having been executed
- Write conflicts in postgres, leading to unique constraint violation
errors

The solution involves handling job log data updates in a way that avoids
overwriting, and ensuring the final update reflects the latest job log
data. Each job log entry now initializes its own ID, so a given job log
entry’s ID remains the same across multiple, parallel task executions.

## Postgres

In Postgres, we need to enable transactions for the
`payload.db.updateJobs` operation; otherwise, two tasks updating the
same job in parallel can conflict. This happens because Postgres handles
array rows by deleting them all, then re-inserting (rather than
upserting). The rows are stored in a separate table, and the following
scenario can occur:

Op 1: deletes all job log rows
Op 2: deletes all job log rows
Op 1: inserts 200 job log rows
Op 2: insert the same 200 job log rows again => `error: “duplicate key
value violates unique constraint "payload_jobs_log_pkey”`

Because transactions were not used, the rows inserted by Op 1
immediately became visible to Op 2, causing the conflict. Enabling
transactions fixes this. In theory, it can still happen if Op 1 commits
before Op 2 starts inserting (due to the read committed isolation
level), but it should occur far less frequently.

Alongside this change, we should consider inserting the rows using an
upsert (update on conflict), which will get rid of this error
completely. That way, if the insertion of Op 1 is visible to Op 2, Op 2
will simply overwrite it, rather than erroring. Individual job entries
are immutable and job entries cannot be deleted, thus this shouldn't
corrupt any data.

## Mongo

In Mongo, the issue is addressed by ensuring that log row deletions
caused due to different log states in concurrent operations are not
merged back to the client job log, and by making sure the final update
includes all job logs.

There is no duplicate key error in Mongo because the array log resides
in the same document and duplicates are simply upserted. We cannot use
transactions in Mongo, as it appears to lock the document in a way that
prevents reliable parallel updates, leading to:

`MongoServerError: WriteConflict error: this operation conflicted with
another operation. Please retry your operation or multi-document
transaction`
2025-03-31 13:06:05 -06:00
Alessio Gravili
a083d47368 feat(db-*): return database name to unsanitized config (#11913)
You can access the database name from `sanitizedConfig.db.name`. But
currently, it' not possible to access the db name from the unsanitized
config.

Plugins only have access to the unsanitized config. This change allows
db adapters to return the db name early, which will allow plugins to
conditionally initialize db-specific functionality
2025-03-31 12:57:17 -06:00
Elliot DeNolf
35e6cfbdfc chore(release): v3.31.0 [skip ci] 2025-03-25 14:28:01 -04:00
Alessio Gravili
a5c3aa0e4f perf: reduce job queue db calls (#11846)
Continuation of #11489. This adds a new, optional `updateJobs` db
adapter method that reduces the amount of database calls for the jobs
queue.

## MongoDB

### Previous: running a set of 50 queued jobs
- 1x db.find (= 1x `Model.paginate`)
- 50x db.updateOne (= 50x `Model.findOneAndUpdate`)

### Now: running a set of 50 queued jobs
- 1x db.updateJobs (= 1x `Model.find` and 1x `Model.updateMany`)

**=> 51 db round trips before, 2 db round trips after**


### Previous: upon task completion
- 1x db.find (= 1x `Model.paginate`)
- 1x db.updateOne (= 1x `Model.findOneAndUpdate`)

### Now: upon task completion
- 1x db.updateJobs (= 1x `Model.findOneAndUpdate`)


**=> 2 db round trips before, 1 db round trip after**


## Drizzle (e.g. Postgres)

### running a set of 50 queued jobs
 - 1x db.query[tablename].findMany
 - 50x db.select 
 - 50x upsertRow
 
This is unaffected by this PR and will be addressed in a future PR
2025-03-25 18:09:52 +00:00
Elliot DeNolf
bb14cc9b41 chore(release): v3.30.0 [skip ci] 2025-03-24 09:59:42 -04:00
Sasha
1b2b6a1b15 fix: respect draft: true when querying docs for the join field (#11763)
Previously, if you were querying a collection that has a join field with
`draft: true`, and the join field's collection also has
`versions.drafts: true` our db adapter would still query the original
SQL table / mongodb collection instead of the versions one which isn't
quite right since we respect `draft: true` when populating relationships
2025-03-24 09:49:30 -04:00
Sasha
4081953c18 feat(db-mongodb): support sorting by fields in other collections through a relationship field (#11803)
This is already supported in Postgres / SQLite.
For example:
```
const result = await payload.find({
  collection: 'directors',
  depth: 0,
  sort: '-movies.name', // movies is a relationship field here
})
```

Removes the condition in tests:
```
 // no support for sort by relation in mongodb
 if (isMongoose(payload)) {
  return
}
```
2025-03-20 20:49:21 +00:00
Elliot DeNolf
339226e62a chore(release): v3.29.0 [skip ci] 2025-03-20 13:59:33 -04:00
Jarrod Flesch
1d25b16a4a fix(db-mongodb): spread version schema options correctly (#11793) 2025-03-20 10:22:51 -04:00
Alessio Gravili
e96d3c87e2 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,
    },
  },
})
```
2025-03-19 10:47:58 -06:00
Sasha
f442d22237 feat(db-*): allow to thread id to create operation data without custom IDs (#11709)
Fixes https://github.com/payloadcms/payload/issues/6884

Adds a new flag `acceptIDOnCreate` that allows you to thread your own
`id` to `payload.create` `data`, for example:

```ts
// doc created with id 1
const doc = await payload.create({ collection: 'posts', data: {id: 1, title: "my title"}})
```

```ts
import { Types } from 'mongoose'
const id = new Types.ObjectId().toHexString()
const doc = await payload.create({ collection: 'posts', data: {id, title: "my title"}})
```
2025-03-17 23:48:35 -04:00
Elliot DeNolf
e8064a3a0c chore(release): v3.28.1 [skip ci] 2025-03-12 17:27:26 -04:00
Elliot DeNolf
d959d843a2 chore(release): v3.28.0 [skip ci] 2025-03-11 17:10:15 -04:00
Sasha
e9afb367b5 fix(db-mongodb): properly sanitize updateVersion read result (#11589)
Previously, `db.updateVersion` had a mistake with using `transform({
operation: 'write' })` instead of `transform({ operation: 'read' })`
which led to improper DB data sanitization (like ObjectID -> string,
Date -> string) when calling `payload.update` with `autosave: true` when
some other autosave draft already exists. This fixes
https://github.com/payloadcms/payload/issues/11542 additionally for this
case.
2025-03-07 19:14:02 +02:00
Sasha
2ad035fb7b feat(db-mongodb): strip keys from the data that don't exist in the schema from read results (#11558)
This change makes so that data that exists in MongoDB but isn't defined
in the Payload config won't be included to `payload.find` /
`payload.db.find` calls. Now we strip all the additional keys.

Consider you have a field named `secretField` that's also `hidden: true`
(or `read: () => false`) that contains some sensitive data. Then you
removed this field from the database and as for now with the MongoDB
adapter this field will be included to the Local API / REST API results
without any consideration, as Payload doesn't know about it anymore.

This also fixes https://github.com/payloadcms/payload/issues/11542 if
you removed / renamed a relationship field from the schema, Payload
won't sanitize ObjectIDs back to strings anymore.

Ideally you should create a migration script that completely removes the
deleted field from the database with `$unset`, but people rarely do
this.

If you still need to keep those fields to the result, this PR allows you
to do this with the new `allowAdditionalKeys: true` flag.
2025-03-06 14:31:38 +00:00
Elliot DeNolf
54acdad190 chore(release): v3.27.0 [skip ci] 2025-03-05 16:44:09 -05:00
Sasha
bacc0f002a feat: compound indexes (#11512)
### What?
This PR adds ability to define indexes on several fields for collections
(compound indexes).

Example:
```ts
{
  indexes: [{ unique: true, fields: ['title', 'group.name'] }]
}
```

### Why?
This can be used to either speed up querying/sorting by 2 or more fields
at the same time or to ensure uniqueness between several fields.

### How?
Implements this logic in database adapters. Additionally, adds a utility
`getFieldByPath`.
2025-03-05 03:09:24 +02:00
Elliot DeNolf
1d168318d0 chore(release): v3.26.0 [skip ci] 2025-03-04 10:01:54 -05:00
Alessio Gravili
6a3d58bb32 feat(db-*): support limit in db.updateMany (#11488)
This PR adds a new `limit` property to `payload.db.updateMany`. This functionality is required for [migrating our job system to use faster, direct db adapter calls](https://github.com/payloadcms/payload/pull/11489)
2025-03-03 05:32:57 +00:00
Sasha
79a7b4ad02 chore(db-mongodb): tsconfig uses strict: true and noUncheckedIndexedAccess: true (#11444)
Migrates the `db-mongodb` package to use `strict: true` and
`noUncheckedIndexedAccess: true` TSConfig properties.
This greatly improves code quality and prevents some runtime errors or
gives better error messages.
2025-03-01 00:17:24 +02:00
Sasha
d4d2bf4617 perf(db-mongodb): faster join field aggregation by replacing mongoose-aggregate-paginate-v2 with a custom implementation (#10936)
Fixes
https://github.com/payloadcms/payload/discussions/10165#discussioncomment-12034047

As described in the discussion, we have an incorrect order of
aggregation pipeline when using aggregations with the join field. We
must use `$sort`, `$skip`, `$limit` before the `$lookup` or otherwise
mongodb scans all the docs, applies `$lookup` for them and only after
applies `$limit`, `$skip`.
Replaces `mongoose-aggregate-paginate-v2` with a custom
`aggregatePaginate` because we need a custom solution here. This was
considered in https://github.com/payloadcms/payload/pull/9594 but it was
reverted as for now.

Fixes https://github.com/payloadcms/payload/issues/11187
2025-02-28 21:30:00 +02:00
Alessio Gravili
41c7413f59 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`.
2025-02-27 20:30:17 -07:00
Alessio Gravili
c21dac1b53 perf(db-*): add option to disable returning modified documents in db methods (#11393)
This PR adds a new `returning` option to various db adapter methods. Setting it to `false` where the return value is not used will lead to performance gains, as we don't have to do additional db calls to fetch the updated document and then sanitize it.
2025-02-27 17:40:22 -05:00
Elliot DeNolf
bdf0113b2f chore(release): v3.25.0 [skip ci] 2025-02-27 12:06:03 -05:00
Sasha
3436fb16ea feat: allow to count related docs for join fields (#11395)
### What?
For the join field query adds ability to specify `count: true`, example:
```ts
const result = await payload.find({
  joins: {
    'group.relatedPosts': {
      sort: '-title',
      count: true,
    },
  },
  collection: "categories",
})

result.group?.relatedPosts?.totalDocs // available
```

### Why?
Can be useful to implement full pagination / show total related
documents count in the UI.

### How?
Implements the logic in database adapters. In MongoDB it's additional
`$lookup` that has `$count` in the pipeline. In SQL, it's additional
subquery with `COUNT(*)`. Preserves the current behavior by default,
since counting introduces overhead.


Additionally, fixes a typescript generation error for join fields.
Before, `docs` and `hasNextPage` were marked as nullable, which is not
true, these fields cannot be `null`.
Additionally, fixes threading of `joinQuery` in
`transform/read/traverseFields` for group / tab fields recursive calls.
2025-02-27 16:05:48 +00:00
Sasha
6b6c289d79 fix(db-mongodb): hasNextPage with polymorphic joins (#11394)
Previously, `hasNextPage` was working incorrectly with polymorphic joins
(that have an array of `collection`) in MongoDB.

This PR fixes it and adds extra assertions to the polymorphic joins
test.

---------

Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
2025-02-25 21:22:47 +00:00
Paul
b014416584 feat: add support for not_like operation (#11326)
This PR adds support for `not_like` as a query operation. Functions just
as a negative to `like`, uses `ilike` in postgres and `like` in sqlite
2025-02-22 00:32:37 +00:00
Sasha
1dc748d341 perf(db-mongodb): remove JSON.parse(JSON.stringify) copying of results (#11293)
Improves performance and optimizes memory usage for mongodb adapter by
cutting down copying of results via `JSON.parse(JSON.stringify())`.
Instead, `transform` does necessary transformations (`ObjectID` ->
`string,` `Date` -> `string`) without any copying
2025-02-21 17:31:24 +02:00
Elliot DeNolf
f3161f9405 chore(release): v3.24.0 [skip ci] 2025-02-19 13:37:26 -05:00
Alessio Gravili
7922d66181 fix(db-mongodb): properly handle document notfound cases for update and delete operations (#11267)
In the `findOne` db operation, we return `null` if the document was not
found.

For single-document delete and update operations, if the document you
wanted to update is not found, the following runtime error is thrown
instead: `Cannot read properties of null (reading '_id')`.

This PR correctly handles these cases and returns `null` from the db
method, just like the `findOne` operation.
2025-02-19 01:19:59 +00:00
Sasha
6d36a28cdc feat: join field across many collections (#10919)
This feature allows you to specify `collection` for the join field as
array.
This can be useful for example to describe relationship linking like
this:
```ts
{
  slug: 'folders',
  fields: [
    {
      type: 'join',
      on: 'folder',
      collection: ['files', 'documents', 'folders'],
      name: 'children',
    },
    {
      type: 'relationship',
      relationTo: 'folders',
      name: 'folder',
    },
  ],
},
{
  slug: 'files',
  upload: true,
  fields: [
    {
      type: 'relationship',
      relationTo: 'folders',
      name: 'folder',
    },
  ],
},
{
  slug: 'documents',
  fields: [
    {
      type: 'relationship',
      relationTo: 'folders',
      name: 'folder',
    },
  ],
},
```

Documents and files can be placed to folders and folders themselves can
be nested to other folders (root folders just have `folder` as `null`).

Output type of `Folder`:
```ts
export interface Folder {
  id: string;
  children?: {
    docs?:
      | (
          | {
              relationTo?: 'files';
              value: string | File;
            }
          | {
              relationTo?: 'documents';
              value: string | Document;
            }
          | {
              relationTo?: 'folders';
              value: string | Folder;
            }
        )[]
      | null;
    hasNextPage?: boolean | null;
  } | null;
  folder?: (string | null) | Folder;
  updatedAt: string;
  createdAt: string;
}
```

While you could instead have many join fields (for example
`childrenFolders`, `childrenFiles`) etc - this doesn't allow you to
sort/filter and paginate things across many collections, which isn't
trivial. With SQL we use `UNION ALL` query to achieve that.

---------

Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
2025-02-18 21:53:45 +02:00
Sasha
847d8d824f feat: add page query parameter for joins (#10998)
Currently, the join field outputs to its result `hasNextPage: boolean`
and have the `limit` query parameter but lacks `page` which can be
useful. This PR adds it.
2025-02-18 16:47:09 +02:00
Alessio Gravili
e6fea1d132 fix: localized fields within block references were not handled properly if any parent is localized (#11207)
The `localized` properly was not stripped out of referenced block fields, if any parent was localized. For normal fields, this is done in sanitizeConfig. As the same referenced block config can be used in both a localized and non-localized config, we are not able to strip it out inside sanitizeConfig by modifying the block config.

Instead, this PR had to bring back tedious logic to handle it everywhere the `field.localized` property is accessed. For backwards-compatibility, we need to keep the existing sanitizeConfig logic. In 4.0, we should remove it to benefit from better test coverage of runtime field.localized handling - for now, this is done for our test suite using the `PAYLOAD_DO_NOT_SANITIZE_LOCALIZED_PROPERTY` flag.
2025-02-17 19:50:32 +00:00
Sasha
2ae670e0e4 test(db-mongodb): unit test assertion for relationship sanitization inside blockReferences (#11195)
This PR adds a new unit test assertion to existing
https://github.com/payloadcms/payload/blob/main/packages/db-mongodb/src/utilities/sanitizeRelationshipIDs.spec.ts
that ensures relationships are sanitized to `ObjectID`s correctly when
saved to the database for relationships inside the new `blockReferences`
https://github.com/payloadcms/payload/pull/10905
2025-02-16 14:07:58 +02:00
Said Akhrarov
12f51bad5f fix(db-mongodb): remove duplicative indexing of timestamps (#11028)
### What?
This PR removes a pair unnecessary calls to `schema.index` against the
timestamp fields. The issue is when a user sets `indexSortableFields` as
this is what will ultimately pass the predicate which then creates
duplicate indexes.

### Why?
These calls are redundant as `index` is [already
passed](https://github.com/payloadcms/payload/blob/main/packages/db-mongodb/src/models/buildSchema.ts#L69)
to the underlying fields base schema options in the process of
formatting and will already be indexed.

These warnings were surfaced after the bump to mongoose to version 8.9.5
as [in 8.9.3 mongoose began throwing these warnings to indicate
duplicative
indexes](https://github.com/Automattic/mongoose/releases/tag/8.9.3).

### How?
By removing these calls and, as a result, silencing the warnings thrown
by mongoose.
2025-02-13 23:07:24 -05:00
Alessio Gravili
4c8cafd6a6 perf: deduplicate blocks used in multiple places using new config.blocks property (#10905)
If you have multiple blocks that are used in multiple places, this can quickly blow up the size of your Payload Config. This will incur a performance hit, as more data is
1.  sent to the client (=> bloated `ClientConfig` and large initial html) and
2. processed on the server (permissions are calculated every single time you navigate to a page - this iterates through all blocks you have defined, even if they're duplicative)

This can be optimized by defining your block **once** in your Payload Config, and just referencing the block slug whenever it's used, instead of passing the entire block config. To do this, the block can be defined in the `blocks` array of the Payload Config. The slug can then be passed to the `blockReferences` array in the Blocks Field - the `blocks` array has to be empty for compatibility reasons.

```ts
import { buildConfig } from 'payload'
import { lexicalEditor, BlocksFeature } from '@payloadcms/richtext-lexical'

// Payload Config
const config = buildConfig({
  // Define the block once
  blocks: [
    {
      slug: 'TextBlock',
      fields: [
        {
          name: 'text',
          type: 'text',
        },
      ],
    },
  ],
  collections: [
    {
      slug: 'collection1',
      fields: [
        {
          name: 'content',
          type: 'blocks',
          // Reference the block by slug
          blockReferences: ['TextBlock'],
          blocks: [], // Required to be empty, for compatibility reasons
        },
      ],
    },
     {
      slug: 'collection2',
      fields: [
        {
          name: 'editor',
          type: 'richText',
          editor: lexicalEditor({
            BlocksFeature({
              // Same reference can be reused anywhere, even in the lexical editor, without incurred performance hit
              blocks: ['TextBlock'],
            })
          })
        },
      ],
    },
  ],
})
```

## v4.0 Plans

In 4.0, we will remove the `blockReferences` property, and allow string block references to be passed directly to the blocks `property`. Essentially, we'd remove the `blocks` property and rename `blockReferences` to `blocks`.

The reason we opted to a new property in this PR is to avoid breaking changes. Allowing strings to be passed to the `blocks` property will prevent plugins that iterate through fields / blocks from compiling.

## PR Changes

- Testing: This PR introduces a plugin that automatically converts blocks to block references. This is done in the fields__blocks test suite, to run our existing test suite using block references.

- Block References support: Most changes are similar. Everywhere we iterate through blocks, we have to now do the following:
1. Check if `field.blockReferences` is provided. If so, only iterate through that.
2. Check if the block is an object (= actual block), or string
3. If it's a string, pull the actual block from the Payload Config or from `payload.blocks`.

The exception is config sanitization and block type generations. This PR optimizes them so that each block is only handled once, instead of every time the block is referenced.

## Benchmarks

60 Block fields, each block field having the same 600 Blocks.

### Before:
**Initial HTML:** 195 kB
**Generated types:** takes 11 minutes, 461,209 lines

https://github.com/user-attachments/assets/11d49a4e-5414-4579-8050-e6346e552f56

### After:
**Initial HTML:** 73.6 kB
**Generated types:** takes 2 seconds, 35,810 lines

https://github.com/user-attachments/assets/3eab1a99-6c29-489d-add5-698df67780a3

### After Permissions Optimization (follow-up PR)
Initial HTML: 73.6 kB

https://github.com/user-attachments/assets/a909202e-45a8-4bf6-9a38-8c85813f1312


## Future Plans

1. This PR does not yet deduplicate block references during permissions calculation. We'll optimize that in a separate PR, as this one is already large enough
2. The same optimization can be done to deduplicate fields. One common use-case would be link field groups that may be referenced in multiple entities, outside of blocks. We might explore adding a new `fieldReferences` property, that allows you to reference those same `config.blocks`.
2025-02-14 00:08:20 +00:00
Elliot DeNolf
480c6e7c09 chore(release): v3.23.0 [skip ci] 2025-02-11 12:53:51 -05:00
Jarrod Flesch
d2fe9b0807 fix(db-mongodb): ensures same level operators are respected (#11087)
### What?
If you had multiple operator constraints on a single field, the last one
defined would be the only one used.

Example:
```ts
where: {
  id: {
    in: [doc2.id],
    not_in: [], // <-- only respected this operator constraint
  },
}
```

and
```ts
where: {
  id: {
    not_in: [],
    in: [doc2.id], // <-- only respected this operator constraint
  },
}
```

They would yield different results.

### Why?
The results were not merged into an `$and` query inside parseParams.

### How?
Merges the results within an `$and` constraint.

Fixes https://github.com/payloadcms/payload/issues/10944

Supersedes https://github.com/payloadcms/payload/pull/11011
2025-02-10 16:29:08 -05:00
Elliot DeNolf
a80c6b5212 chore(release): v3.22.0 [skip ci] 2025-02-07 09:22:48 -05:00
Elliot DeNolf
834fdde088 chore(release): v3.21.0 [skip ci] 2025-02-05 14:15:51 -05:00
Elliot DeNolf
5bd17cc111 chore(release): v3.20.0 [skip ci] 2025-01-29 10:41:55 -05:00
Elliot DeNolf
b2ebf85082 chore(release): v3.19.0 [skip ci] 2025-01-23 13:38:39 -05:00
Sasha
2d8ff7218a fix(db-mongodb): v2-v3 migration versions docs of collections and globals without relationship fields (#10755)
Fixes https://github.com/payloadcms/payload/issues/10753
2025-01-23 12:33:43 -05:00
Sasha
d601300034 fix(db-mongodb): querying polymorphic relationships with the all operator (#10704)
Fixes https://github.com/payloadcms/payload/issues/10678
2025-01-23 18:23:50 +02:00