fix(db-mongodb): querying polymorphic relationships with the all operator (#10704)

Fixes https://github.com/payloadcms/payload/issues/10678
This commit is contained in:
Sasha
2025-01-23 18:23:50 +02:00
committed by GitHub
parent e5b3da972f
commit d601300034
4 changed files with 106 additions and 17 deletions

View File

@@ -40,7 +40,7 @@ _The exact query syntax will depend on the API you are using, but the concepts a
The following operators are available for use in queries:
| Operator | Description |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `equals` | The value must be exactly equal. |
| `not_equals` | The query will return all documents where the value is not equal. |
| `greater_than` | For numeric or date-based fields. |
@@ -51,7 +51,7 @@ The following operators are available for use in queries:
| `contains` | Must contain the value entered, case-insensitive. |
| `in` | The value must be found within the provided comma-delimited list of values. |
| `not_in` | The value must NOT be within the provided comma-delimited list of values. |
| `all` | The value must contain all values provided in the comma-delimited list. |
| `all` | The value must contain all values provided in the comma-delimited list. Note: currently this operator is supported only with the MongoDB adapter. |
| `exists` | Only return documents where the value either exists (`true`) or does not exist (`false`). |
| `near` | For distance related to a [Point Field](../fields/point) comma separated as `<longitude>, <latitude>, <maxDistance in meters (nullable)>, <minDistance in meters (nullable)>`. |
| `within` | For [Point Fields](../fields/point) to filter documents based on whether points are inside of the given area defined in GeoJSON. [Example](../fields/point#querying-within) |

View File

@@ -324,6 +324,19 @@ export const sanitizeQueryValue = ({
}
}
}
if (
operator === 'all' &&
Array.isArray(relationTo) &&
path.endsWith('.value') &&
Array.isArray(formattedValue)
) {
formattedValue.forEach((v, i) => {
if (Types.ObjectId.isValid(v)) {
formattedValue[i] = new Types.ObjectId(v)
}
})
}
}
// Set up specific formatting necessary by operators

View File

@@ -48,6 +48,7 @@ export const operatorMap: Operators = {
less_than_equal: lte,
like: ilike,
not_equals: ne,
// TODO: support this
// all: all,
not_in: notInArray,
or,

View File

@@ -39,6 +39,8 @@ const dirname = path.dirname(filename)
type EasierChained = { id: string; relation: EasierChained }
const mongoIt = process.env.PAYLOAD_DATABASE === 'mongodb' ? it : it.skip
describe('Relationships', () => {
beforeAll(async () => {
;({ payload, restClient } = await initPayloadInt(dirname))
@@ -459,6 +461,46 @@ describe('Relationships', () => {
expect(query2.totalDocs).toStrictEqual(2)
})
// all operator is not supported in Postgres yet for any fields
mongoIt('should query using "all" by hasMany relationship field', async () => {
const movie1 = await payload.create({
collection: 'movies',
data: {},
})
const movie2 = await payload.create({
collection: 'movies',
data: {},
})
await payload.create({
collection: 'directors',
data: {
name: 'Quentin Tarantino',
movies: [movie2.id, movie1.id],
},
})
await payload.create({
collection: 'directors',
data: {
name: 'Quentin Tarantino',
movies: [movie2.id],
},
})
const query1 = await payload.find({
collection: 'directors',
depth: 0,
where: {
movies: {
all: [movie1.id],
},
},
})
expect(query1.totalDocs).toStrictEqual(1)
})
it('should sort by a property of a hasMany relationship', async () => {
// no support for sort by relation in mongodb
if (isMongoose(payload)) {
@@ -1352,6 +1394,39 @@ describe('Relationships', () => {
expect(queryTwo.docs).toHaveLength(1)
})
// all operator is not supported in Postgres yet for any fields
mongoIt('should allow REST all querying on polymorphic relationships', async () => {
const movie = await payload.create({
collection: 'movies',
data: {
name: 'Pulp Fiction 2',
},
})
await payload.create({
collection: polymorphicRelationshipsSlug,
data: {
polymorphic: {
relationTo: 'movies',
value: movie.id,
},
},
})
const queryOne = await restClient
.GET(`/${polymorphicRelationshipsSlug}`, {
query: {
where: {
'polymorphic.value': {
all: [movie.id],
},
},
},
})
.then((res) => res.json())
expect(queryOne.docs).toHaveLength(1)
})
it('should allow querying on polymorphic relationships with an object syntax', async () => {
const movie = await payload.create({
collection: 'movies',