From ea3e75f1bdeb6e8c3b3e46c909f827daef1978f0 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Tue, 11 Oct 2022 17:25:03 -0500 Subject: [PATCH] feat: localDatastore support for unsorted distance queries (#1570) --- integration/test/ParseLocalDatastoreTest.js | 20 +++++++++++++++++++ src/OfflineQuery.js | 22 ++++++++++++++++++--- src/__tests__/OfflineQuery-test.js | 9 +++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/integration/test/ParseLocalDatastoreTest.js b/integration/test/ParseLocalDatastoreTest.js index c532ca0f8..19d224582 100644 --- a/integration/test/ParseLocalDatastoreTest.js +++ b/integration/test/ParseLocalDatastoreTest.js @@ -2735,6 +2735,26 @@ function runTest(controller) { assert.equal(objects.length, 1); }); + it(`${controller.name} supports withinKilometers`, async () => { + const object = new TestObject(); + const firstPoint = new Parse.GeoPoint({ latitude: 40.0, longitude: -30.0 }); + object.set({ location: firstPoint }); + await object.save(); + await object.pin(); + + const sorted = false; + const query = new Parse.Query(TestObject); + query.withinKilometers( + 'location', + new Parse.GeoPoint({ latitude: 40.0, longitude: -30.0 }), + 2, + sorted + ); + query.fromLocalDatastore(); + const results = await query.find(); + assert.equal(results.length, 1); + }); + it(`${controller.name} supports withinPolygon`, async () => { const sacramento = new TestObject(); sacramento.set('location', new Parse.GeoPoint(38.52, -121.5)); diff --git a/src/OfflineQuery.js b/src/OfflineQuery.js index 46167a586..f76cfa061 100644 --- a/src/OfflineQuery.js +++ b/src/OfflineQuery.js @@ -513,9 +513,25 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { return true; } case '$geoWithin': { - const points = compareTo.$polygon.map(geoPoint => [geoPoint.latitude, geoPoint.longitude]); - const polygon = new ParsePolygon(points); - return polygon.containsPoint(object[key]); + if (compareTo.$polygon) { + const points = compareTo.$polygon.map(geoPoint => [ + geoPoint.latitude, + geoPoint.longitude, + ]); + const polygon = new ParsePolygon(points); + return polygon.containsPoint(object[key]); + } + if (compareTo.$centerSphere) { + const [WGS84Point, maxDistance] = compareTo.$centerSphere; + const centerPoint = new ParseGeoPoint({ + latitude: WGS84Point[1], + longitude: WGS84Point[0], + }); + const point = new ParseGeoPoint(object[key]); + const distance = point.radiansTo(centerPoint); + return distance <= maxDistance; + } + break; } case '$geoIntersects': { const polygon = new ParsePolygon(object[key].coordinates); diff --git a/src/__tests__/OfflineQuery-test.js b/src/__tests__/OfflineQuery-test.js index 76e432075..ae67a8494 100644 --- a/src/__tests__/OfflineQuery-test.js +++ b/src/__tests__/OfflineQuery-test.js @@ -471,6 +471,15 @@ describe('OfflineQuery', () => { expect(matchesQuery(q.className, pt, [], q)).toBe(true); }); + it('matches $centerSphere queries', () => { + const pt = new ParseObject('Checkin'); + pt.set('location', new ParseGeoPoint(40, 40)); + + const q = new ParseQuery('Checkin'); + q.withinRadians('location', new ParseGeoPoint(30, 30), 0.3, false); + expect(matchesQuery(q.className, pt, [], q)).toBe(true); + }); + it('matches $within queries', () => { const caltrainStation = new ParseObject('Checkin'); caltrainStation