Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/db-mongodb/src/queries/sanitizeQueryValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export const sanitizeQueryValue = ({
}

if (['relationship', 'upload'].includes(field.type)) {
if (val === 'null') {
if (val === 'null' || (Array.isArray(val) && val.length === 1 && val[0] === 'null')) {
formattedValue = null
}

Expand Down
2 changes: 1 addition & 1 deletion packages/drizzle/src/queries/sanitizeQueryValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const sanitizeQueryValue = ({
}

if (field.type === 'relationship' || field.type === 'upload') {
if (val === 'null') {
if (val === 'null' || (Array.isArray(val) && val.length === 1 && val[0] === 'null')) {
formattedValue = null
} else if (!(formattedValue === null || typeof formattedValue === 'boolean')) {
// convert the value to the idType of the relationship
Expand Down
52 changes: 52 additions & 0 deletions test/relationships/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,58 @@ describe('Relationships', () => {
expect(query.docs[0].text).toEqual('Tree 3')
expect(query.docs[1].text).toEqual('Tree 4')
})

it('should query using "equals: null" on a hasMany relationship field', async () => {
await payload.delete({ collection: 'directors', where: {} })
await payload.delete({ collection: 'movies', where: {} })

const movie = await payload.create({
collection: 'movies',
data: { name: 'Some Movie' },
})

await payload.create({
collection: 'directors',
data: {
name: 'Director With Movies',
movies: [movie.id],
},
})

const directorWithoutMovies = await payload.create({
collection: 'directors',
data: {
name: 'Director Without Movies',
},
})

// Test programmatic API with null
const programmaticResult = await payload.find({
collection: 'directors',
depth: 0,
where: {
movies: { equals: null },
},
})

expect(programmaticResult.totalDocs).toBe(1)
expect(programmaticResult.docs[0]?.id).toBe(directorWithoutMovies.id)

// Test REST API with ['null'] — the form the admin UI sends for "None"
const restResult = await restClient
.GET(`/directors`, {
query: {
where: {
movies: { equals: ['null'] },
},
depth: 0,
},
})
.then((res) => res.json() as Promise<{ docs: Director[]; totalDocs: number }>)

expect(restResult.totalDocs).toBe(1)
expect(restResult.docs[0]?.id).toBe(directorWithoutMovies.id)
})
})

describe('sorting by relationships', () => {
Expand Down
Loading