diff --git a/spec/ParseQuery.Aggregate.spec.js b/spec/ParseQuery.Aggregate.spec.js index 5987399a42..f29bad996c 100644 --- a/spec/ParseQuery.Aggregate.spec.js +++ b/spec/ParseQuery.Aggregate.spec.js @@ -96,6 +96,27 @@ describe('Parse.Query Aggregate testing', () => { }).catch(done.fail); }); + it('group by pointer', (done) => { + const pointer1 = new TestObject(); + const pointer2 = new TestObject(); + const obj1 = new TestObject({ pointer: pointer1 }); + const obj2 = new TestObject({ pointer: pointer2 }); + const obj3 = new TestObject({ pointer: pointer1 }); + const pipeline = [ + { group: { objectId: '$pointer' } } + ]; + Parse.Object.saveAll([pointer1, pointer2, obj1, obj2, obj3]).then(() => { + const query = new Parse.Query(TestObject); + return query.aggregate(pipeline); + }).then((results) => { + expect(results.length).toEqual(3); + expect(results.some(result => result.objectId === pointer1.id)).toEqual(true); + expect(results.some(result => result.objectId === pointer2.id)).toEqual(true); + expect(results.some(result => result.objectId === null)).toEqual(true); + done(); + }); + }); + it('group sum 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 43a994daa9..b5d97c2de9 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -515,12 +515,26 @@ export class MongoStorageAdapter implements StorageAdapter { } aggregate(className: string, schema: any, pipeline: any, readPreference: ?string) { + let isPointerField = false; + pipeline = pipeline.map((stage) => { + if (stage.$group && stage.$group._id) { + const field = stage.$group._id.substring(1); + if (schema.fields[field] && schema.fields[field].type === 'Pointer') { + isPointerField = true; + stage.$group._id = `$_p_${field}`; + } + } + return stage; + }); readPreference = this._parseReadPreference(readPreference); return this._adaptiveCollection(className) .then(collection => collection.aggregate(pipeline, { readPreference, maxTimeMS: this._maxTimeMS })) .then(results => { results.forEach(result => { if (result.hasOwnProperty('_id')) { + if (isPointerField && result._id) { + result._id = result._id.split('$')[1]; + } result.objectId = result._id; delete result._id; } diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index e46fcec73b..601ac64505 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -754,13 +754,13 @@ export class PostgresStorageAdapter implements StorageAdapter { debug('schemaUpgrade', { className, schema }); conn = conn || this._client; const self = this; - + return conn.tx('schema-upgrade', function * (t) { const columns = yield t.map('SELECT column_name FROM information_schema.columns WHERE table_name = $', { className }, a => a.column_name); const newColumns = Object.keys(schema.fields) .filter(item => columns.indexOf(item) === -1) .map(fieldName => self.addFieldIfNotExists(className, fieldName, schema.fields[fieldName], t)); - + yield t.batch(newColumns); }); } @@ -896,7 +896,7 @@ export class PostgresStorageAdapter implements StorageAdapter { return this._client.any('SELECT * FROM "_SCHEMA" WHERE "className"=$', { className }) .then(result => { if (result.length !== 1) { - throw undefined; + throw undefined; } return result[0].schema; }) @@ -1267,12 +1267,12 @@ export class PostgresStorageAdapter implements StorageAdapter { const createValue = Object.assign({}, query, update); return this.createObject(className, schema, createValue) .catch(error => { - // ignore duplicate value errors as it's upsert - if (error.code !== Parse.Error.DUPLICATE_VALUE) { - throw error; - } - return this.findOneAndUpdate(className, schema, query, update); - }); + // ignore duplicate value errors as it's upsert + if (error.code !== Parse.Error.DUPLICATE_VALUE) { + throw error; + } + return this.findOneAndUpdate(className, schema, query, update); + }); } find(className: string, schema: SchemaType, query: QueryType, { skip, limit, sort, keys }: QueryOptions) { @@ -1452,7 +1452,7 @@ export class PostgresStorageAdapter implements StorageAdapter { throw error; } return 0; - }); + }); } distinct(className: string, schema: SchemaType, query: QueryType, fieldName: string) {