fix: properly handle nullable minDistance and maxDistance in near query (#10622)
Fixes https://github.com/payloadcms/payload/issues/10521
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,12 +319,22 @@ export function parseParams({
|
||||
|
||||
case 'near': {
|
||||
const [lng, lat, maxDistance, minDistance] = queryValue as number[]
|
||||
const geoConstraints: SQL[] = []
|
||||
|
||||
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}`
|
||||
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})`,
|
||||
)
|
||||
}
|
||||
|
||||
if (typeof minDistance === 'number' && !Number.isNaN(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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user