fix(db-mongodb): querying polymorphic relationships with the all operator (#10704)
Fixes https://github.com/payloadcms/payload/issues/10678
This commit is contained in:
@@ -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) |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user