feat(drizzle): add support for in and not_in operators on json field (#8148)
Closes https://github.com/payloadcms/payload/issues/7952 Adds support for `in` and `not_in` operator against JSON field filters. The following queries are now valid in postgres as well, previously it only worked in mongo ```ts await payload.find({ collection: 'posts', where: { 'data.value': { in: ['12', '13', '14'], }, }, context: { disable: true, }, }) await payload.find({ collection: 'posts', where: { 'data.value': { not_in: ['12', '13', '14'], }, }, context: { disable: true, }, }) ```
This commit is contained in:
@@ -87,6 +87,7 @@
|
||||
"test:e2e:prod:ci": "rm -rf test/node_modules && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd .. && pnpm runts ./test/runE2E.ts --prod",
|
||||
"test:int": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
|
||||
"test:int:postgres": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=postgres DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
|
||||
"test:int:sqlite": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=sqlite DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
|
||||
"test:unit": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=jest.config.js --runInBand",
|
||||
"translateNewKeys": "pnpm --filter payload run translateNewKeys"
|
||||
},
|
||||
|
||||
@@ -125,17 +125,25 @@ export async function parseParams({
|
||||
}
|
||||
|
||||
const jsonQuery = adapter.convertPathToJSONTraversal(pathSegments)
|
||||
const operatorKeys = {
|
||||
const operatorKeys: Record<string, { operator: string; wildcard: string }> = {
|
||||
contains: { operator: 'like', wildcard: '%' },
|
||||
equals: { operator: '=', wildcard: '' },
|
||||
exists: { operator: val === true ? 'is not null' : 'is null' },
|
||||
exists: { operator: val === true ? 'is not null' : 'is null', wildcard: '' },
|
||||
in: { operator: 'in', wildcard: '' },
|
||||
like: { operator: 'like', wildcard: '%' },
|
||||
not_equals: { operator: '<>', wildcard: '' },
|
||||
not_in: { operator: 'not in', wildcard: '' },
|
||||
}
|
||||
|
||||
let formattedValue = val
|
||||
if (adapter.name === 'sqlite' && operator === 'equals' && !isNaN(val)) {
|
||||
formattedValue = val
|
||||
} else if (['in', 'not_in'].includes(operator) && Array.isArray(val)) {
|
||||
if (adapter.name === 'sqlite') {
|
||||
formattedValue = `(${val.map((v) => `${v}`).join(',')})`
|
||||
} else {
|
||||
formattedValue = `(${val.map((v) => `'${v}'`).join(', ')})`
|
||||
}
|
||||
} else {
|
||||
formattedValue = `'${operatorKeys[operator].wildcard}${val}${operatorKeys[operator].wildcard}'`
|
||||
}
|
||||
|
||||
@@ -1744,6 +1744,16 @@ describe('Fields', () => {
|
||||
json: { baz: 'bar', number: 10 },
|
||||
},
|
||||
})
|
||||
|
||||
// Create content for array 'in' and 'not_in' queries
|
||||
for (let i = 1; i < 6; i++) {
|
||||
await payload.create({
|
||||
collection: 'json-fields',
|
||||
data: {
|
||||
json: { value: i },
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
it('should query nested properties - like', async () => {
|
||||
@@ -1901,6 +1911,36 @@ describe('Fields', () => {
|
||||
|
||||
expect(result.docs).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should query nested numbers - in', async () => {
|
||||
const { docs } = await payload.find({
|
||||
collection: 'json-fields',
|
||||
where: {
|
||||
'json.value': { in: [1, 3] },
|
||||
},
|
||||
})
|
||||
|
||||
const docIDs = docs.map(({ json }) => json.value)
|
||||
|
||||
expect(docIDs).toContain(1)
|
||||
expect(docIDs).toContain(3)
|
||||
expect(docIDs).not.toContain(2)
|
||||
})
|
||||
|
||||
it('should query nested numbers - not_in', async () => {
|
||||
const { docs } = await payload.find({
|
||||
collection: 'json-fields',
|
||||
where: {
|
||||
'json.value': { not_in: [1, 3] },
|
||||
},
|
||||
})
|
||||
|
||||
const docIDs = docs.map(({ json }) => json.value)
|
||||
|
||||
expect(docIDs).not.toContain(1)
|
||||
expect(docIDs).not.toContain(3)
|
||||
expect(docIDs).toContain(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user