diff --git a/packages/db-mongodb/src/queries/sanitizeQueryValue.ts b/packages/db-mongodb/src/queries/sanitizeQueryValue.ts index ce8df399902..872d35b5f88 100644 --- a/packages/db-mongodb/src/queries/sanitizeQueryValue.ts +++ b/packages/db-mongodb/src/queries/sanitizeQueryValue.ts @@ -349,10 +349,11 @@ export const sanitizeQueryValue = ({ $geometry: { type: 'Point', coordinates: [parseFloat(lng), parseFloat(lat)] }, } - if (maxDistance) { + if (maxDistance && !Number.isNaN(Number(maxDistance))) { formattedValue.$maxDistance = parseFloat(maxDistance) } - if (minDistance) { + + if (minDistance && !Number.isNaN(Number(minDistance))) { formattedValue.$minDistance = parseFloat(minDistance) } } diff --git a/packages/drizzle/src/queries/parseParams.ts b/packages/drizzle/src/queries/parseParams.ts index 2acf79a50ef..705ff2acde1 100644 --- a/packages/drizzle/src/queries/parseParams.ts +++ b/packages/drizzle/src/queries/parseParams.ts @@ -319,12 +319,22 @@ export function parseParams({ case 'near': { const [lng, lat, maxDistance, minDistance] = queryValue as number[] + const geoConstraints: SQL[] = [] + + if (typeof maxDistance === 'number' && !Number.isNaN(maxDistance)) { + geoConstraints.push( + sql`ST_DWithin(ST_Transform(${table[columnName]}, 3857), ST_Transform(ST_SetSRID(ST_MakePoint(${lng}, ${lat}), 4326), 3857), ${maxDistance})`, + ) + } - let constraint = sql`ST_DWithin(ST_Transform(${table[columnName]}, 3857), ST_Transform(ST_SetSRID(ST_MakePoint(${lng}, ${lat}), 4326), 3857), ${maxDistance})` if (typeof minDistance === 'number' && !Number.isNaN(minDistance)) { - constraint = sql`${constraint} AND ST_Distance(ST_Transform(${table[columnName]}, 3857), ST_Transform(ST_SetSRID(ST_MakePoint(${lng}, ${lat}), 4326), 3857)) >= ${minDistance}` + geoConstraints.push( + sql`ST_Distance(ST_Transform(${table[columnName]}, 3857), ST_Transform(ST_SetSRID(ST_MakePoint(${lng}, ${lat}), 4326), 3857)) >= ${minDistance}`, + ) + } + if (geoConstraints.length) { + constraints.push(and(...geoConstraints)) } - constraints.push(constraint) break } diff --git a/test/collections-rest/int.spec.ts b/test/collections-rest/int.spec.ts index 74039d2a5b2..8283007d299 100644 --- a/test/collections-rest/int.spec.ts +++ b/test/collections-rest/int.spec.ts @@ -1128,6 +1128,48 @@ describe('collections-rest', () => { expect(resultCount.totalDocs).toBe(1) }) + it('should omit maxDistance and return a document from minDistance', async () => { + if (payload.db.name === 'sqlite') { + return + } + + const near = `${lat + 0.01}, ${lng + 0.01}, null, 1500` + const response = await restClient.GET(`/${pointSlug}`, { + query: { + where: { + point: { + near, + }, + }, + }, + }) + const result = await response.json() + + expect(response.status).toEqual(200) + expect(result.docs).toHaveLength(1) + }) + + it('should omit maxDistance and not return a document because exceeds minDistance', async () => { + if (payload.db.name === 'sqlite') { + return + } + + const near = `${lat + 0.01}, ${lng + 0.01}, null, 1700` + const response = await restClient.GET(`/${pointSlug}`, { + query: { + where: { + point: { + near, + }, + }, + }, + }) + const result = await response.json() + + expect(response.status).toEqual(200) + expect(result.docs).toHaveLength(0) + }) + it('should not return a point far away', async () => { if (payload.db.name === 'sqlite') { return