diff --git a/spec/ParseQuery.Aggregate.spec.js b/spec/ParseQuery.Aggregate.spec.js index 10552175a8..56b61035dc 100644 --- a/spec/ParseQuery.Aggregate.spec.js +++ b/spec/ParseQuery.Aggregate.spec.js @@ -941,6 +941,52 @@ describe('Parse.Query Aggregate testing', () => { }); }); + it_exclude_dbs(['postgres'])('match null values', async () => { + const obj1 = new Parse.Object('MyCollection'); + obj1.set('language', 'en'); + obj1.set('otherField', 1); + const obj2 = new Parse.Object('MyCollection'); + obj2.set('language', 'en'); + obj2.set('otherField', 2); + const obj3 = new Parse.Object('MyCollection'); + obj3.set('language', null); + obj3.set('otherField', 3); + const obj4 = new Parse.Object('MyCollection'); + obj4.set('language', null); + obj4.set('otherField', 4); + const obj5 = new Parse.Object('MyCollection'); + obj5.set('language', 'pt'); + obj5.set('otherField', 5); + const obj6 = new Parse.Object('MyCollection'); + obj6.set('language', 'pt'); + obj6.set('otherField', 6); + await Parse.Object.saveAll([obj1, obj2, obj3, obj4, obj5, obj6]); + + expect( + (await new Parse.Query('MyCollection').aggregate([ + { + match: { + language: { $in: [null, 'en'] }, + }, + }, + ])) + .map(value => value.otherField) + .sort() + ).toEqual([1, 2, 3, 4]); + + expect( + (await new Parse.Query('MyCollection').aggregate([ + { + match: { + $or: [{ language: 'en' }, { language: null }], + }, + }, + ])) + .map(value => value.otherField) + .sort() + ).toEqual([1, 2, 3, 4]); + }); + it('project query', done => { const options = Object.assign({}, masterKeyOptions, { body: { diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index e79bec269b..ee3fd5bd81 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -841,7 +841,9 @@ export class MongoStorageAdapter implements StorageAdapter { // As much as I hate recursion...this seemed like a good fit for it. We're essentially traversing // down a tree to find a "leaf node" and checking to see if it needs to be converted. _parseAggregateArgs(schema: any, pipeline: any): any { - if (Array.isArray(pipeline)) { + if (pipeline === null) { + return null; + } else if (Array.isArray(pipeline)) { return pipeline.map(value => this._parseAggregateArgs(schema, value)); } else if (typeof pipeline === 'object') { const returnValue = {};