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
}
```
This commit is contained in:
Sasha
2025-03-20 22:49:21 +02:00
committed by GitHub
parent f9f53a65cb
commit 4081953c18
12 changed files with 277 additions and 30 deletions

View File

@@ -223,6 +223,7 @@ export default buildConfigWithDefaults({
},
{
slug: 'movies',
versions: { drafts: true },
fields: [
{
name: 'name',
@@ -242,6 +243,11 @@ export default buildConfigWithDefaults({
name: 'name',
type: 'text',
},
{
name: 'localized',
type: 'text',
localized: true,
},
{
name: 'movies',
type: 'relationship',

View File

@@ -593,11 +593,6 @@ describe('Relationships', () => {
})
it('should sort by a property of a hasMany relationship', async () => {
// no support for sort by relation in mongodb
if (isMongoose(payload)) {
return
}
const movie1 = await payload.create({
collection: 'movies',
data: {
@@ -638,6 +633,92 @@ describe('Relationships', () => {
expect(result.docs[0].id).toStrictEqual(director1.id)
})
it('should sort by a property of a relationship', async () => {
await payload.delete({ collection: 'directors', where: {} })
await payload.delete({ collection: 'movies', where: {} })
const director_1 = await payload.create({
collection: 'directors',
data: { name: 'Dan', localized: 'Dan' },
})
await payload.update({
collection: 'directors',
id: director_1.id,
locale: 'de',
data: { localized: 'Mr. Dan' },
})
const director_2 = await payload.create({
collection: 'directors',
data: { name: 'Mr. Dan', localized: 'Mr. Dan' },
})
await payload.update({
collection: 'directors',
id: director_2.id,
locale: 'de',
data: { localized: 'Dan' },
})
const movie_1 = await payload.create({
collection: 'movies',
depth: 0,
data: { director: director_1.id, name: 'Some Movie 1' },
})
const movie_2 = await payload.create({
collection: 'movies',
depth: 0,
data: { director: director_2.id, name: 'Some Movie 2' },
})
const res_1 = await payload.find({
collection: 'movies',
sort: '-director.name',
depth: 0,
})
const res_2 = await payload.find({
collection: 'movies',
sort: 'director.name',
depth: 0,
})
expect(res_1.docs).toStrictEqual([movie_2, movie_1])
expect(res_2.docs).toStrictEqual([movie_1, movie_2])
const draft_res_1 = await payload.find({
collection: 'movies',
sort: '-director.name',
depth: 0,
draft: true,
})
const draft_res_2 = await payload.find({
collection: 'movies',
sort: 'director.name',
depth: 0,
draft: true,
})
expect(draft_res_1.docs).toStrictEqual([movie_2, movie_1])
expect(draft_res_2.docs).toStrictEqual([movie_1, movie_2])
const localized_res_1 = await payload.find({
collection: 'movies',
sort: 'director.localized',
depth: 0,
locale: 'de',
})
const localized_res_2 = await payload.find({
collection: 'movies',
sort: 'director.localized',
depth: 0,
})
expect(localized_res_1.docs).toStrictEqual([movie_2, movie_1])
expect(localized_res_2.docs).toStrictEqual([movie_1, movie_2])
})
it('should query using "in" by hasMany relationship field', async () => {
const tree1 = await payload.create({
collection: treeSlug,

View File

@@ -54,6 +54,7 @@ export type SupportedTimezones =
| 'Asia/Singapore'
| 'Asia/Tokyo'
| 'Asia/Seoul'
| 'Australia/Brisbane'
| 'Australia/Sydney'
| 'Pacific/Guam'
| 'Pacific/Noumea'
@@ -268,6 +269,7 @@ export interface Movie {
director?: (string | null) | Director;
updatedAt: string;
createdAt: string;
_status?: ('draft' | 'published') | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
@@ -276,6 +278,7 @@ export interface Movie {
export interface Director {
id: string;
name?: string | null;
localized?: string | null;
movies?: (string | Movie)[] | null;
directors?: (string | Director)[] | null;
updatedAt: string;
@@ -460,9 +463,10 @@ export interface Item {
id: string;
status?: ('completed' | 'failed' | 'pending') | null;
relation?: {
docs?: (string | Relation1)[] | null;
hasNextPage?: boolean | null;
} | null;
docs?: (string | Relation1)[];
hasNextPage?: boolean;
totalDocs?: number;
};
updatedAt: string;
createdAt: string;
}
@@ -728,6 +732,7 @@ export interface MoviesSelect<T extends boolean = true> {
director?: T;
updatedAt?: T;
createdAt?: T;
_status?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
@@ -735,6 +740,7 @@ export interface MoviesSelect<T extends boolean = true> {
*/
export interface DirectorsSelect<T extends boolean = true> {
name?: T;
localized?: T;
movies?: T;
directors?: T;
updatedAt?: T;