Skip to content

Commit 19dea5b

Browse files
authored
Fix aggregate geoNear with date query (#6540)
* added failing test case * add date conversion for geoNear query - geoNear stages were not parsed for date fields, but mongodb nodejs adapter requires date object * reverted unnecessary code auto-formatting * limited parsing to query property of geoNear stage - the geoNear object contains parameter keys which could be identical to field names in the collection, which should not be parsed and changed, therefore restricting parsing only to query parameter key * reverted unnecessary code auto-formatting * added index type parameter to ensureIndex - required to create geo index for geoNear test * added geo index creation to test case * fixed dates in test case - test case likey failed due to date rounding * added error output to console - temporary, to find out why test fails on mongodb 3.6.9 * create seperate class to avoid multiple geo indices on TestObject class - mongodb <4.0 does not allow nultiple geo indices on a class when using geoNear - see https://docs.mongodb.com/v3.6/reference/operator/aggregation/geoNear/#behavior * fixed incorrect result validation - results were not ordered properly, so test validation failed sometimes * removed error output to console This reverts commit da81c51.
1 parent 13bda61 commit 19dea5b

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

spec/ParseQuery.Aggregate.spec.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
const Parse = require('parse/node');
33
const request = require('../lib/request');
4+
const Config = require('../lib/Config');
45

56
const masterKeyHeaders = {
67
'X-Parse-Application-Id': 'test',
@@ -1428,4 +1429,49 @@ describe('Parse.Query Aggregate testing', () => {
14281429
});
14291430
}
14301431
);
1432+
1433+
it_only_db('mongo')('geoNear with location query', async () => {
1434+
// Create geo index which is required for `geoNear` query
1435+
const database = Config.get(Parse.applicationId).database;
1436+
const schema = await new Parse.Schema('GeoObject').save();
1437+
await database.adapter.ensureIndex(
1438+
'GeoObject',
1439+
schema,
1440+
['location'],
1441+
'geoIndex',
1442+
false,
1443+
'2dsphere'
1444+
);
1445+
// Create objects
1446+
const GeoObject = Parse.Object.extend('GeoObject');
1447+
const obj1 = new GeoObject({ value: 1, location: new Parse.GeoPoint(1, 1), date: new Date(1) });
1448+
const obj2 = new GeoObject({ value: 2, location: new Parse.GeoPoint(2, 1), date: new Date(2) });
1449+
const obj3 = new GeoObject({ value: 3, location: new Parse.GeoPoint(3, 1), date: new Date(3) });
1450+
await Parse.Object.saveAll([obj1, obj2, obj3]);
1451+
// Create query
1452+
const pipeline = [
1453+
{
1454+
geoNear: {
1455+
near: {
1456+
type: 'Point',
1457+
coordinates: [1, 1]
1458+
},
1459+
key: 'location',
1460+
spherical: true,
1461+
distanceField: 'dist',
1462+
query: {
1463+
date: {
1464+
$gte: new Date(2)
1465+
}
1466+
}
1467+
}
1468+
}
1469+
];
1470+
const query = new Parse.Query(GeoObject);
1471+
const results = await query.aggregate(pipeline);
1472+
// Check results
1473+
expect(results.length).toEqual(2);
1474+
expect(results[0].value).toEqual(2);
1475+
expect(results[1].value).toEqual(3);
1476+
});
14311477
});

src/Adapters/Storage/Mongo/MongoStorageAdapter.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,15 +682,16 @@ export class MongoStorageAdapter implements StorageAdapter {
682682
schema: SchemaType,
683683
fieldNames: string[],
684684
indexName: ?string,
685-
caseInsensitive: boolean = false
685+
caseInsensitive: boolean = false,
686+
indexType: any = 1
686687
): Promise<any> {
687688
schema = convertParseSchemaToMongoSchema(schema);
688689
const indexCreationRequest = {};
689690
const mongoFieldNames = fieldNames.map(fieldName =>
690691
transformKey(className, fieldName, schema)
691692
);
692693
mongoFieldNames.forEach(fieldName => {
693-
indexCreationRequest[fieldName] = 1;
694+
indexCreationRequest[fieldName] = indexType;
694695
});
695696

696697
const defaultOptions: Object = { background: true, sparse: true };
@@ -843,6 +844,9 @@ export class MongoStorageAdapter implements StorageAdapter {
843844
stage.$project
844845
);
845846
}
847+
if (stage.$geoNear) {
848+
stage.$geoNear.query = this._parseAggregateArgs(schema, stage.$geoNear.query);
849+
}
846850
return stage;
847851
});
848852
readPreference = this._parseReadPreference(readPreference);

src/Adapters/Storage/StorageAdapter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ export interface StorageAdapter {
9292
schema: SchemaType,
9393
fieldNames: string[],
9494
indexName?: string,
95-
caseSensitive?: boolean
95+
caseSensitive?: boolean,
96+
indexType?: any
9697
): Promise<any>;
9798
ensureUniqueness(
9899
className: string,

0 commit comments

Comments
 (0)