2017-11-12 13:00:22 -06:00
'use strict' ;
const Parse = require ( 'parse/node' ) ;
2018-09-24 17:07:51 -04:00
const request = require ( '../lib/request' ) ;
2020-03-29 22:15:40 +02:00
const Config = require ( '../lib/Config' ) ;
2017-11-12 13:00:22 -06:00
const masterKeyHeaders = {
'X-Parse-Application-Id' : 'test' ,
'X-Parse-Rest-API-Key' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Master-Key' : 'test' ,
2018-09-24 17:07:51 -04:00
'Content-Type' : 'application/json' ,
2018-09-01 13:58:06 -04:00
} ;
2017-11-12 13:00:22 -06:00
const masterKeyOptions = {
headers : masterKeyHeaders ,
2018-09-01 13:58:06 -04:00
json : true ,
} ;
2017-11-12 13:00:22 -06:00
2018-03-14 21:57:30 -05:00
const PointerObject = Parse . Object . extend ( {
2018-09-01 13:58:06 -04:00
className : 'PointerObject' ,
2018-03-14 21:57:30 -05:00
} ) ;
2017-11-12 13:00:22 -06:00
const loadTestData = ( ) => {
2018-09-01 13:58:06 -04:00
const data1 = {
score : 10 ,
name : 'foo' ,
2021-08-12 12:14:04 -05:00
sender : { group : 'A' } , // TODO: change to `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
views : 900 ,
size : [ 'S' , 'M' ] ,
} ;
const data2 = {
score : 10 ,
name : 'foo' ,
2021-08-12 12:14:04 -05:00
sender : { group : 'A' } , // TODO: change to `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
views : 800 ,
size : [ 'M' , 'L' ] ,
} ;
const data3 = {
score : 10 ,
name : 'bar' ,
2021-08-12 12:14:04 -05:00
sender : { group : 'B' } , // TODO: change to `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
views : 700 ,
size : [ 'S' ] ,
} ;
const data4 = {
score : 20 ,
name : 'dpl' ,
2021-08-12 12:14:04 -05:00
sender : { group : 'B' } , // TODO: change to `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
views : 700 ,
size : [ 'S' ] ,
} ;
2017-11-12 13:00:22 -06:00
const obj1 = new TestObject ( data1 ) ;
const obj2 = new TestObject ( data2 ) ;
const obj3 = new TestObject ( data3 ) ;
const obj4 = new TestObject ( data4 ) ;
return Parse . Object . saveAll ( [ obj1 , obj2 , obj3 , obj4 ] ) ;
2018-09-01 13:58:06 -04:00
} ;
2017-11-12 13:00:22 -06:00
2020-10-02 00:19:26 +02:00
const get = function ( url , options ) {
2018-09-24 17:07:51 -04:00
options . qs = options . body ;
delete options . body ;
Object . keys ( options . qs ) . forEach ( key => {
options . qs [ key ] = JSON . stringify ( options . qs [ key ] ) ;
} ) ;
return request ( Object . assign ( { } , { url } , options ) )
. then ( response => response . data )
. catch ( response => {
throw { error : response . data } ;
} ) ;
} ;
2017-11-12 13:00:22 -06:00
describe ( 'Parse.Query Aggregate testing' , ( ) => {
2018-09-01 13:58:06 -04:00
beforeEach ( done => {
2017-11-12 13:00:22 -06:00
loadTestData ( ) . then ( done , done ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'should only query aggregate with master key' , done => {
Parse . _request ( 'GET' , ` aggregate/someClass ` , { } ) . then (
( ) => { } ,
error => {
2017-11-12 13:00:22 -06:00
expect ( error . message ) . toEqual ( 'unauthorized: master key is required' ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
}
) ;
2017-11-12 13:00:22 -06:00
} ) ;
2021-08-12 12:14:04 -05:00
it ( 'invalid query group _id required' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
group : { } , // TODO: write as `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
} ,
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options ) . catch ( error => {
2018-09-01 13:58:06 -04:00
expect ( error . error . code ) . toEqual ( Parse . Error . INVALID _QUERY ) ;
done ( ) ;
2017-11-12 13:00:22 -06:00
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group by field' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
group : { objectId : '$name' } , // TODO: write as `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 3 ) ;
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 1 ] , 'objectId' ) ) . toBe ( true ) ;
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 2 ] , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] . objectId ) . not . toBe ( undefined ) ;
expect ( resp . results [ 1 ] . objectId ) . not . toBe ( undefined ) ;
expect ( resp . results [ 2 ] . objectId ) . not . toBe ( undefined ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-08-12 20:05:08 -05:00
it ( 'group by pipeline operator' , async ( ) => {
const options = Object . assign ( { } , masterKeyOptions , {
body : {
pipeline : {
2021-08-12 12:14:04 -05:00
group : { objectId : '$name' } , // TODO: write as `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
} ,
} ,
2018-08-12 20:05:08 -05:00
} ) ;
2018-09-24 17:07:51 -04:00
const resp = await get ( Parse . serverURL + '/aggregate/TestObject' , options ) ;
2018-08-12 20:05:08 -05:00
expect ( resp . results . length ) . toBe ( 3 ) ;
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 1 ] , 'objectId' ) ) . toBe ( true ) ;
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 2 ] , 'objectId' ) ) . toBe ( true ) ;
2018-08-12 20:05:08 -05:00
expect ( resp . results [ 0 ] . objectId ) . not . toBe ( undefined ) ;
expect ( resp . results [ 1 ] . objectId ) . not . toBe ( undefined ) ;
expect ( resp . results [ 2 ] . objectId ) . not . toBe ( undefined ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group by empty object' , done => {
2018-02-16 12:41:02 -06:00
const obj = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-08-12 12:14:04 -05:00
group : { objectId : { } } , // TODO: write as `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
} ,
] ;
obj
. save ( )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results [ 0 ] . objectId ) . toEqual ( null ) ;
done ( ) ;
} ) ;
2018-02-16 12:41:02 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group by empty string' , done => {
2018-02-16 12:41:02 -06:00
const obj = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-08-12 12:14:04 -05:00
group : { objectId : '' } , // TODO: write as `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
} ,
] ;
obj
. save ( )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results [ 0 ] . objectId ) . toEqual ( null ) ;
done ( ) ;
} ) ;
2018-02-16 12:41:02 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group by empty array' , done => {
2018-02-16 12:41:02 -06:00
const obj = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-08-12 12:14:04 -05:00
group : { objectId : [ ] } , // TODO: write as `$group`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
} ,
] ;
obj
. save ( )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results [ 0 ] . objectId ) . toEqual ( null ) ;
done ( ) ;
} ) ;
2018-02-16 12:41:02 -06:00
} ) ;
2020-03-09 21:48:39 +05:30
it ( 'group by multiple columns ' , done => {
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
const obj3 = new TestObject ( ) ;
const pipeline = [
{
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2020-03-09 21:48:39 +05:30
group : {
objectId : {
score : '$score' ,
views : '$views' ,
} ,
count : { $sum : 1 } ,
} ,
} ,
] ;
Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 5 ) ;
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group by date object' , done => {
2018-02-16 12:41:02 -06:00
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
const obj3 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-10-31 15:49:03 -04:00
$group : {
_id : {
2018-09-01 13:58:06 -04:00
day : { $dayOfMonth : '$_updated_at' } ,
month : { $month : '$_created_at' } ,
year : { $year : '$_created_at' } ,
} ,
count : { $sum : 1 } ,
} ,
} ,
] ;
Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
const createdAt = new Date ( obj1 . createdAt ) ;
expect ( results [ 0 ] . objectId . day ) . toEqual ( createdAt . getUTCDate ( ) ) ;
2019-07-31 19:55:16 -07:00
expect ( results [ 0 ] . objectId . month ) . toEqual ( createdAt . getUTCMonth ( ) + 1 ) ;
2018-09-01 13:58:06 -04:00
expect ( results [ 0 ] . objectId . year ) . toEqual ( createdAt . getUTCFullYear ( ) ) ;
done ( ) ;
} ) ;
2018-02-16 12:41:02 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group by date object transform' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
const obj3 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-10-31 15:49:03 -04:00
$group : {
_id : {
2018-09-01 13:58:06 -04:00
day : { $dayOfMonth : '$updatedAt' } ,
month : { $month : '$createdAt' } ,
year : { $year : '$createdAt' } ,
} ,
count : { $sum : 1 } ,
} ,
} ,
] ;
Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
const createdAt = new Date ( obj1 . createdAt ) ;
expect ( results [ 0 ] . objectId . day ) . toEqual ( createdAt . getUTCDate ( ) ) ;
2019-07-31 19:55:16 -07:00
expect ( results [ 0 ] . objectId . month ) . toEqual ( createdAt . getUTCMonth ( ) + 1 ) ;
2018-09-01 13:58:06 -04:00
expect ( results [ 0 ] . objectId . year ) . toEqual ( createdAt . getUTCFullYear ( ) ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2019-09-01 22:34:36 -07:00
it ( 'group by number' , done => {
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
group : { objectId : '$score' } , // TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2019-09-01 22:34:36 -07:00
} ,
} ) ;
get ( Parse . serverURL + '/aggregate/TestObject' , options )
. then ( resp => {
expect ( resp . results . length ) . toBe ( 2 ) ;
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 1 ] , 'objectId' ) ) . toBe ( true ) ;
expect ( resp . results . sort ( ( a , b ) => ( a . objectId > b . objectId ? 1 : - 1 ) ) ) . toEqual ( [
{ objectId : 10 } ,
{ objectId : 20 } ,
] ) ;
2019-09-01 22:34:36 -07:00
done ( ) ;
} )
. catch ( done . fail ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'group and multiply transform' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( { name : 'item a' , quantity : 2 , price : 10 } ) ;
const obj2 = new TestObject ( { name : 'item b' , quantity : 5 , price : 5 } ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
group : {
objectId : null ,
total : { $sum : { $multiply : [ '$quantity' , '$price' ] } } ,
} ,
} ,
] ;
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 1 ) ;
expect ( results [ 0 ] . total ) . toEqual ( 45 ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'project and multiply transform' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( { name : 'item a' , quantity : 2 , price : 10 } ) ;
const obj2 = new TestObject ( { name : 'item b' , quantity : 5 , price : 5 } ) ;
const pipeline = [
{
2018-09-01 13:58:06 -04:00
match : { quantity : { $exists : true } } ,
2018-06-26 18:18:04 -04:00
} ,
{
project : {
name : 1 ,
2018-09-01 13:58:06 -04:00
total : { $multiply : [ '$quantity' , '$price' ] } ,
} ,
} ,
2018-06-26 18:18:04 -04:00
] ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 2 ) ;
if ( results [ 0 ] . name === 'item a' ) {
expect ( results [ 0 ] . total ) . toEqual ( 20 ) ;
expect ( results [ 1 ] . total ) . toEqual ( 25 ) ;
} else {
expect ( results [ 0 ] . total ) . toEqual ( 25 ) ;
expect ( results [ 1 ] . total ) . toEqual ( 20 ) ;
}
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'project without objectId transform' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( { name : 'item a' , quantity : 2 , price : 10 } ) ;
const obj2 = new TestObject ( { name : 'item b' , quantity : 5 , price : 5 } ) ;
const pipeline = [
{
2018-09-01 13:58:06 -04:00
match : { quantity : { $exists : true } } ,
2018-06-26 18:18:04 -04:00
} ,
{
project : {
2021-08-12 12:14:04 -05:00
objectId : 0 , // TODO: change to `_id`. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
total : { $multiply : [ '$quantity' , '$price' ] } ,
} ,
2018-06-26 18:18:04 -04:00
} ,
{
2018-09-01 13:58:06 -04:00
sort : { total : 1 } ,
} ,
2018-06-26 18:18:04 -04:00
] ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 2 ) ;
expect ( results [ 0 ] . total ) . toEqual ( 20 ) ;
expect ( results [ 0 ] . objectId ) . toEqual ( undefined ) ;
expect ( results [ 1 ] . total ) . toEqual ( 25 ) ;
expect ( results [ 1 ] . objectId ) . toEqual ( undefined ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'project updatedAt only transform' , done => {
const pipeline = [
{
project : { objectId : 0 , updatedAt : 1 } ,
} ,
] ;
2018-06-26 18:18:04 -04:00
const query = new Parse . Query ( TestObject ) ;
2018-09-01 13:58:06 -04:00
query . aggregate ( pipeline ) . then ( results => {
2018-06-26 18:18:04 -04:00
expect ( results . length ) . toEqual ( 4 ) ;
for ( let i = 0 ; i < results . length ; i ++ ) {
const item = results [ i ] ;
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( item , 'updatedAt' ) ) . toEqual ( true ) ;
expect ( Object . prototype . hasOwnProperty . call ( item , 'objectId' ) ) . toEqual ( false ) ;
2018-06-26 18:18:04 -04:00
}
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) (
2019-04-26 18:33:03 -07:00
'can group by any date field (it does not work if you have dirty data)' , // rows in your collection with non date data in the field that is supposed to be a date
2018-09-01 13:58:06 -04:00
done => {
2019-04-26 18:33:03 -07:00
const obj1 = new TestObject ( { dateField2019 : new Date ( 1990 , 11 , 1 ) } ) ;
const obj2 = new TestObject ( { dateField2019 : new Date ( 1990 , 5 , 1 ) } ) ;
const obj3 = new TestObject ( { dateField2019 : new Date ( 1990 , 11 , 1 ) } ) ;
const pipeline = [
{
match : {
dateField2019 : { $exists : true } ,
} ,
} ,
{
group : {
objectId : {
day : { $dayOfMonth : '$dateField2019' } ,
month : { $month : '$dateField2019' } ,
year : { $year : '$dateField2019' } ,
} ,
count : { $sum : 1 } ,
} ,
} ,
] ;
Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
const counts = results . map ( result => result . count ) ;
expect ( counts . length ) . toBe ( 2 ) ;
expect ( counts . sort ( ) ) . toEqual ( [ 1 , 2 ] ) ;
done ( ) ;
} )
. catch ( done . fail ) ;
}
) ;
it _only _db ( 'postgres' ) (
'can group by any date field (it does not work if you have dirty data)' , // rows in your collection with non date data in the field that is supposed to be a date
done => {
const obj1 = new TestObject ( { dateField2019 : new Date ( 1990 , 11 , 1 ) } ) ;
const obj2 = new TestObject ( { dateField2019 : new Date ( 1990 , 5 , 1 ) } ) ;
const obj3 = new TestObject ( { dateField2019 : new Date ( 1990 , 11 , 1 ) } ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [
{
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2018-09-01 13:58:06 -04:00
group : {
objectId : {
2019-04-26 18:33:03 -07:00
day : { $dayOfMonth : '$dateField2019' } ,
month : { $month : '$dateField2019' } ,
year : { $year : '$dateField2019' } ,
2018-09-01 13:58:06 -04:00
} ,
count : { $sum : 1 } ,
} ,
} ,
] ;
Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
2019-04-26 18:33:03 -07:00
. then ( results => {
const counts = results . map ( result => result . count ) ;
expect ( counts . length ) . toBe ( 3 ) ;
expect ( counts . sort ( ) ) . toEqual ( [ 1 , 2 , 4 ] ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
2019-04-26 18:33:03 -07:00
} )
. catch ( done . fail ) ;
2018-09-01 13:58:06 -04:00
}
) ;
2018-02-16 12:41:02 -06:00
2018-09-01 13:58:06 -04:00
it ( 'group by pointer' , done => {
2018-01-08 20:42:08 -06:00
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 } ) ;
2018-09-01 13:58:06 -04:00
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 ) ;
2020-10-25 15:06:58 -05:00
expect ( results . some ( result => result . objectId === pointer1 . id ) ) . toEqual ( true ) ;
expect ( results . some ( result => result . objectId === pointer2 . id ) ) . toEqual ( true ) ;
2018-09-01 13:58:06 -04:00
expect ( results . some ( result => result . objectId === null ) ) . toEqual ( true ) ;
done ( ) ;
} ) ;
2018-01-08 20:42:08 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group sum query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , total : { $sum : '$score' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] . objectId ) . toBe ( null ) ;
expect ( resp . results [ 0 ] . total ) . toBe ( 50 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group count query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , total : { $sum : 1 } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] . objectId ) . toBe ( null ) ;
expect ( resp . results [ 0 ] . total ) . toBe ( 4 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group min query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , minScore : { $min : '$score' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] . objectId ) . toBe ( null ) ;
expect ( resp . results [ 0 ] . minScore ) . toBe ( 10 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group max query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , maxScore : { $max : '$score' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] . objectId ) . toBe ( null ) ;
expect ( resp . results [ 0 ] . maxScore ) . toBe ( 20 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'group avg query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , avgScore : { $avg : '$score' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( resp . results [ 0 ] , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] . objectId ) . toBe ( null ) ;
expect ( resp . results [ 0 ] . avgScore ) . toBe ( 12.5 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'limit query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
limit : 2 ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 2 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'sort ascending query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
sort : { name : 1 } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 4 ) ;
expect ( resp . results [ 0 ] . name ) . toBe ( 'bar' ) ;
expect ( resp . results [ 1 ] . name ) . toBe ( 'dpl' ) ;
expect ( resp . results [ 2 ] . name ) . toBe ( 'foo' ) ;
expect ( resp . results [ 3 ] . name ) . toBe ( 'foo' ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'sort decending query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
sort : { name : - 1 } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 4 ) ;
expect ( resp . results [ 0 ] . name ) . toBe ( 'foo' ) ;
expect ( resp . results [ 1 ] . name ) . toBe ( 'foo' ) ;
expect ( resp . results [ 2 ] . name ) . toBe ( 'dpl' ) ;
expect ( resp . results [ 3 ] . name ) . toBe ( 'bar' ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'skip query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
skip : 2 ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 2 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match comparison date query' , done => {
2018-06-26 18:18:04 -04:00
const today = new Date ( ) ;
const yesterday = new Date ( ) ;
const tomorrow = new Date ( ) ;
yesterday . setDate ( today . getDate ( ) - 1 ) ;
tomorrow . setDate ( today . getDate ( ) + 1 ) ;
const obj1 = new TestObject ( { dateField : yesterday } ) ;
const obj2 = new TestObject ( { dateField : today } ) ;
const obj3 = new TestObject ( { dateField : tomorrow } ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [ { match : { dateField : { $lt : tomorrow } } } ] ;
Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toBe ( 2 ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match comparison query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2018-09-01 13:58:06 -04:00
match : { score : { $gt : 15 } } ,
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 1 ) ;
expect ( resp . results [ 0 ] . score ) . toBe ( 20 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match multiple comparison query' , done => {
2018-01-20 08:00:36 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2018-09-01 13:58:06 -04:00
match : { score : { $gt : 5 , $lt : 15 } } ,
} ,
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2018-01-20 08:00:36 -06:00
expect ( resp . results . length ) . toBe ( 3 ) ;
expect ( resp . results [ 0 ] . score ) . toBe ( 10 ) ;
expect ( resp . results [ 1 ] . score ) . toBe ( 10 ) ;
expect ( resp . results [ 2 ] . score ) . toBe ( 10 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match complex comparison query' , done => {
2018-01-20 08:00:36 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2018-09-01 13:58:06 -04:00
match : { score : { $gt : 5 , $lt : 15 } , views : { $gt : 850 , $lt : 1000 } } ,
} ,
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2018-01-20 08:00:36 -06:00
expect ( resp . results . length ) . toBe ( 1 ) ;
expect ( resp . results [ 0 ] . score ) . toBe ( 10 ) ;
expect ( resp . results [ 0 ] . views ) . toBe ( 900 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match comparison and equality query' , done => {
2018-01-20 08:00:36 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2018-09-01 13:58:06 -04:00
match : { score : { $gt : 5 , $lt : 15 } , views : 900 } ,
} ,
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2018-01-20 08:00:36 -06:00
expect ( resp . results . length ) . toBe ( 1 ) ;
expect ( resp . results [ 0 ] . score ) . toBe ( 10 ) ;
expect ( resp . results [ 0 ] . views ) . toBe ( 900 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match $or query' , done => {
2018-01-20 08:00:36 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2018-09-01 13:58:06 -04:00
match : {
2020-10-25 15:06:58 -05:00
$or : [ { score : { $gt : 15 , $lt : 25 } } , { views : { $gt : 750 , $lt : 850 } } ] ,
2018-09-01 13:58:06 -04:00
} ,
} ,
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2018-01-20 08:00:36 -06:00
expect ( resp . results . length ) . toBe ( 2 ) ;
// Match score { $gt: 15, $lt: 25 }
expect ( resp . results . some ( result => result . score === 20 ) ) . toEqual ( true ) ;
expect ( resp . results . some ( result => result . views === 700 ) ) . toEqual ( true ) ;
// Match view { $gt: 750, $lt: 850 }
expect ( resp . results . some ( result => result . score === 10 ) ) . toEqual ( true ) ;
expect ( resp . results . some ( result => result . views === 800 ) ) . toEqual ( true ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match objectId query' , done => {
2018-01-20 08:00:36 -06:00
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const pipeline = [ { match : { objectId : obj1 . id } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 1 ) ;
expect ( results [ 0 ] . objectId ) . toEqual ( obj1 . id ) ;
done ( ) ;
} ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match field query' , done => {
const obj1 = new TestObject ( { name : 'TestObject1' } ) ;
const obj2 = new TestObject ( { name : 'TestObject2' } ) ;
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const pipeline = [ { match : { name : 'TestObject1' } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 1 ) ;
expect ( results [ 0 ] . objectId ) . toEqual ( obj1 . id ) ;
done ( ) ;
} ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match pointer query' , done => {
2018-03-14 21:57:30 -05:00
const pointer1 = new PointerObject ( ) ;
const pointer2 = new PointerObject ( ) ;
2018-01-20 08:00:36 -06:00
const obj1 = new TestObject ( { pointer : pointer1 } ) ;
const obj2 = new TestObject ( { pointer : pointer2 } ) ;
const obj3 = new TestObject ( { pointer : pointer1 } ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ pointer1 , pointer2 , obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const pipeline = [ { match : { pointer : pointer1 . id } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 2 ) ;
expect ( results [ 0 ] . pointer . objectId ) . toEqual ( pointer1 . id ) ;
expect ( results [ 1 ] . pointer . objectId ) . toEqual ( pointer1 . id ) ;
2020-10-25 15:06:58 -05:00
expect ( results . some ( result => result . objectId === obj1 . id ) ) . toEqual ( true ) ;
expect ( results . some ( result => result . objectId === obj3 . id ) ) . toEqual ( true ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2018-01-20 08:00:36 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'match exists query' , done => {
const pipeline = [ { match : { score : { $exists : true } } } ] ;
2018-06-26 18:18:04 -04:00
const query = new Parse . Query ( TestObject ) ;
2018-09-01 13:58:06 -04:00
query . aggregate ( pipeline ) . then ( results => {
2018-06-26 18:18:04 -04:00
expect ( results . length ) . toEqual ( 4 ) ;
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match date query - createdAt' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const now = new Date ( ) ;
2020-10-25 15:06:58 -05:00
const today = new Date ( now . getFullYear ( ) , now . getMonth ( ) , now . getDate ( ) ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [ { match : { createdAt : { $gte : today } } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
// Four objects were created initially, we added two more.
expect ( results . length ) . toEqual ( 6 ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match date query - updatedAt' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const now = new Date ( ) ;
2020-10-25 15:06:58 -05:00
const today = new Date ( now . getFullYear ( ) , now . getMonth ( ) , now . getDate ( ) ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [ { match : { updatedAt : { $gte : today } } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
// Four objects were added initially, we added two more.
expect ( results . length ) . toEqual ( 6 ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'match date query - empty' , done => {
2018-06-26 18:18:04 -04:00
const obj1 = new TestObject ( ) ;
const obj2 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
. then ( ( ) => {
const now = new Date ( ) ;
2020-10-25 15:06:58 -05:00
const future = new Date ( now . getFullYear ( ) , now . getMonth ( ) + 1 , now . getDate ( ) ) ;
2018-09-01 13:58:06 -04:00
const pipeline = [ { match : { createdAt : future } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 0 ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'match pointer with operator query' , done => {
2018-06-26 18:18:04 -04:00
const pointer = new PointerObject ( ) ;
const obj1 = new TestObject ( { pointer } ) ;
const obj2 = new TestObject ( { pointer } ) ;
const obj3 = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ pointer , obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const pipeline = [ { match : { pointer : { $exists : true } } } ] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 2 ) ;
expect ( results [ 0 ] . pointer . objectId ) . toEqual ( pointer . id ) ;
expect ( results [ 1 ] . pointer . objectId ) . toEqual ( pointer . id ) ;
2020-10-25 15:06:58 -05:00
expect ( results . some ( result => result . objectId === obj1 . id ) ) . toEqual ( true ) ;
expect ( results . some ( result => result . objectId === obj2 . id ) ) . toEqual ( true ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2019-09-11 07:13:15 -07:00
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 (
2020-03-09 21:48:39 +05:30
(
await new Parse . Query ( 'MyCollection' ) . aggregate ( [
{
match : {
language : { $in : [ null , 'en' ] } ,
} ,
2019-09-11 07:13:15 -07:00
} ,
2020-03-09 21:48:39 +05:30
] )
)
2019-09-11 07:13:15 -07:00
. map ( value => value . otherField )
. sort ( )
) . toEqual ( [ 1 , 2 , 3 , 4 ] ) ;
expect (
2020-03-09 21:48:39 +05:30
(
await new Parse . Query ( 'MyCollection' ) . aggregate ( [
{
match : {
$or : [ { language : 'en' } , { language : null } ] ,
} ,
2019-09-11 07:13:15 -07:00
} ,
2020-03-09 21:48:39 +05:30
] )
)
2019-09-11 07:13:15 -07:00
. map ( value => value . otherField )
. sort ( )
) . toEqual ( [ 1 , 2 , 3 , 4 ] ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'project query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
project : { name : 1 } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
resp . results . forEach ( result => {
2017-12-29 11:39:16 -06:00
expect ( result . objectId ) . not . toBe ( undefined ) ;
expect ( result . name ) . not . toBe ( undefined ) ;
2017-11-12 13:00:22 -06:00
expect ( result . sender ) . toBe ( undefined ) ;
expect ( result . size ) . toBe ( undefined ) ;
expect ( result . score ) . toBe ( undefined ) ;
} ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'multiple project query' , done => {
2017-12-29 11:39:16 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
project : { name : 1 , score : 1 , sender : 1 } ,
2018-09-01 13:58:06 -04:00
} ,
2017-12-29 11:39:16 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
resp . results . forEach ( result => {
2017-12-29 11:39:16 -06:00
expect ( result . objectId ) . not . toBe ( undefined ) ;
expect ( result . name ) . not . toBe ( undefined ) ;
expect ( result . score ) . not . toBe ( undefined ) ;
expect ( result . sender ) . not . toBe ( undefined ) ;
expect ( result . size ) . toBe ( undefined ) ;
} ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-12-29 11:39:16 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'project pointer query' , done => {
2018-06-26 18:18:04 -04:00
const pointer = new PointerObject ( ) ;
const obj = new TestObject ( { pointer , name : 'hello' } ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
const pipeline = [
{ match : { objectId : obj . id } } ,
{ project : { pointer : 1 , name : 1 , createdAt : 1 } } ,
] ;
const query = new Parse . Query ( TestObject ) ;
return query . aggregate ( pipeline ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 1 ) ;
expect ( results [ 0 ] . name ) . toEqual ( 'hello' ) ;
expect ( results [ 0 ] . createdAt ) . not . toBe ( undefined ) ;
expect ( results [ 0 ] . pointer . objectId ) . toEqual ( pointer . id ) ;
done ( ) ;
} ) ;
2018-06-26 18:18:04 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'project with group query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
project : { score : 1 } ,
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : '$score' , score : { $sum : '$score' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 2 ) ;
2018-09-01 13:58:06 -04:00
resp . results . forEach ( result => {
2020-10-25 15:06:58 -05:00
expect ( Object . prototype . hasOwnProperty . call ( result , 'objectId' ) ) . toBe ( true ) ;
2017-11-12 13:00:22 -06:00
expect ( result . name ) . toBe ( undefined ) ;
expect ( result . sender ) . toBe ( undefined ) ;
expect ( result . size ) . toBe ( undefined ) ;
expect ( result . score ) . not . toBe ( undefined ) ;
if ( result . objectId === 10 ) {
expect ( result . score ) . toBe ( 30 ) ;
}
if ( result . objectId === 20 ) {
expect ( result . score ) . toBe ( 20 ) ;
}
} ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'class does not exist return empty' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , total : { $sum : '$score' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/UnknownClass' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 0 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'field does not exist return empty' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
2021-08-12 12:14:04 -05:00
// TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx)
2017-11-12 13:00:22 -06:00
group : { objectId : null , total : { $sum : '$unknownfield' } } ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/UnknownClass' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 0 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct query' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
2018-09-01 13:58:06 -04:00
body : { distinct : 'score' } ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 2 ) ;
expect ( resp . results . includes ( 10 ) ) . toBe ( true ) ;
expect ( resp . results . includes ( 20 ) ) . toBe ( true ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct query with where' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
distinct : 'score' ,
where : {
2018-09-01 13:58:06 -04:00
name : 'bar' ,
} ,
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] ) . toBe ( 10 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct query with where string' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
distinct : 'score' ,
2018-09-01 13:58:06 -04:00
where : JSON . stringify ( { name : 'bar' } ) ,
} ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results [ 0 ] ) . toBe ( 10 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct nested' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
2018-09-01 13:58:06 -04:00
body : { distinct : 'sender.group' } ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 2 ) ;
expect ( resp . results . includes ( 'A' ) ) . toBe ( true ) ;
expect ( resp . results . includes ( 'B' ) ) . toBe ( true ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct pointer' , done => {
2018-03-14 21:57:30 -05:00
const pointer1 = new PointerObject ( ) ;
const pointer2 = new PointerObject ( ) ;
2017-12-29 21:32:40 -06:00
const obj1 = new TestObject ( { pointer : pointer1 } ) ;
const obj2 = new TestObject ( { pointer : pointer2 } ) ;
const obj3 = new TestObject ( { pointer : pointer1 } ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ pointer1 , pointer2 , obj1 , obj2 , obj3 ] )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . distinct ( 'pointer' ) ;
} )
. then ( results => {
expect ( results . length ) . toEqual ( 2 ) ;
2020-10-25 15:06:58 -05:00
expect ( results . some ( result => result . objectId === pointer1 . id ) ) . toEqual ( true ) ;
expect ( results . some ( result => result . objectId === pointer2 . id ) ) . toEqual ( true ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2017-12-29 21:32:40 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct class does not exist return empty' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
2018-09-01 13:58:06 -04:00
body : { distinct : 'unknown' } ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/UnknownClass' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 0 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct field does not exist return empty' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
2018-09-01 13:58:06 -04:00
body : { distinct : 'unknown' } ,
2017-11-12 13:00:22 -06:00
} ) ;
const obj = new TestObject ( ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
return get ( Parse . serverURL + '/aggregate/TestObject' , options ) ;
2018-09-01 13:58:06 -04:00
} )
. then ( resp => {
expect ( resp . results . length ) . toBe ( 0 ) ;
done ( ) ;
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'distinct array' , done => {
2017-11-12 13:00:22 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
2018-09-01 13:58:06 -04:00
body : { distinct : 'size' } ,
2017-11-12 13:00:22 -06:00
} ) ;
2018-09-24 17:07:51 -04:00
get ( Parse . serverURL + '/aggregate/TestObject' , options )
2018-09-01 13:58:06 -04:00
. then ( resp => {
2017-11-12 13:00:22 -06:00
expect ( resp . results . length ) . toBe ( 3 ) ;
expect ( resp . results . includes ( 'S' ) ) . toBe ( true ) ;
expect ( resp . results . includes ( 'M' ) ) . toBe ( true ) ;
expect ( resp . results . includes ( 'L' ) ) . toBe ( true ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( done . fail ) ;
2017-11-12 13:00:22 -06:00
} ) ;
2018-10-26 10:21:42 -05:00
it ( 'distinct objectId' , async ( ) => {
const query = new Parse . Query ( TestObject ) ;
const results = await query . distinct ( 'objectId' ) ;
expect ( results . length ) . toBe ( 4 ) ;
} ) ;
it ( 'distinct createdAt' , async ( ) => {
const object1 = new TestObject ( { createdAt _test : true } ) ;
await object1 . save ( ) ;
const object2 = new TestObject ( { createdAt _test : true } ) ;
await object2 . save ( ) ;
const query = new Parse . Query ( TestObject ) ;
query . equalTo ( 'createdAt_test' , true ) ;
const results = await query . distinct ( 'createdAt' ) ;
expect ( results . length ) . toBe ( 2 ) ;
} ) ;
it ( 'distinct updatedAt' , async ( ) => {
const object1 = new TestObject ( { updatedAt _test : true } ) ;
await object1 . save ( ) ;
const object2 = new TestObject ( ) ;
await object2 . save ( ) ;
object2 . set ( 'updatedAt_test' , true ) ;
await object2 . save ( ) ;
const query = new Parse . Query ( TestObject ) ;
query . equalTo ( 'updatedAt_test' , true ) ;
const results = await query . distinct ( 'updatedAt' ) ;
expect ( results . length ) . toBe ( 2 ) ;
} ) ;
2017-11-22 23:07:45 -08:00
2018-09-01 13:58:06 -04:00
it ( 'distinct null field' , done => {
2018-02-16 09:44:42 -06:00
const options = Object . assign ( { } , masterKeyOptions , {
2018-09-01 13:58:06 -04:00
body : { distinct : 'distinctField' } ,
2018-02-16 09:44:42 -06:00
} ) ;
const user1 = new Parse . User ( ) ;
user1 . setUsername ( 'distinct_1' ) ;
user1 . setPassword ( 'password' ) ;
user1 . set ( 'distinctField' , 'one' ) ;
const user2 = new Parse . User ( ) ;
user2 . setUsername ( 'distinct_2' ) ;
user2 . setPassword ( 'password' ) ;
user2 . set ( 'distinctField' , null ) ;
2018-09-01 13:58:06 -04:00
user1
. signUp ( )
. then ( ( ) => {
return user2 . signUp ( ) ;
} )
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
return get ( Parse . serverURL + '/aggregate/_User' , options ) ;
2018-09-01 13:58:06 -04:00
} )
. then ( resp => {
expect ( resp . results . length ) . toEqual ( 1 ) ;
expect ( resp . results ) . toEqual ( [ 'one' ] ) ;
done ( ) ;
} )
. catch ( done . fail ) ;
2018-02-16 09:44:42 -06:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'does not return sensitive hidden properties' , done => {
2017-11-22 23:07:45 -08:00
const options = Object . assign ( { } , masterKeyOptions , {
body : {
match : {
score : {
2018-09-01 13:58:06 -04:00
$gt : 5 ,
} ,
2017-11-22 23:07:45 -08:00
} ,
2018-09-01 13:58:06 -04:00
} ,
2017-11-22 23:07:45 -08:00
} ) ;
const username = 'leaky_user' ;
const score = 10 ;
const user = new Parse . User ( ) ;
user . setUsername ( username ) ;
user . setPassword ( 'password' ) ;
user . set ( 'score' , score ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
2020-10-02 00:19:26 +02:00
. then ( function ( ) {
2018-09-24 17:07:51 -04:00
return get ( Parse . serverURL + '/aggregate/_User' , options ) ;
2018-09-01 13:58:06 -04:00
} )
2020-10-02 00:19:26 +02:00
. then ( function ( resp ) {
2018-09-01 13:58:06 -04:00
expect ( resp . results . length ) . toBe ( 1 ) ;
const result = resp . results [ 0 ] ;
// verify server-side keys are not present...
expect ( result . _hashed _password ) . toBe ( undefined ) ;
expect ( result . _wperm ) . toBe ( undefined ) ;
expect ( result . _rperm ) . toBe ( undefined ) ;
expect ( result . _acl ) . toBe ( undefined ) ;
expect ( result . _created _at ) . toBe ( undefined ) ;
expect ( result . _updated _at ) . toBe ( undefined ) ;
// verify createdAt, updatedAt and others are present
expect ( result . createdAt ) . not . toBe ( undefined ) ;
expect ( result . updatedAt ) . not . toBe ( undefined ) ;
expect ( result . objectId ) . not . toBe ( undefined ) ;
expect ( result . username ) . toBe ( username ) ;
expect ( result . score ) . toBe ( score ) ;
2017-11-22 23:07:45 -08:00
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
2020-10-02 00:19:26 +02:00
. catch ( function ( err ) {
2018-09-01 13:58:06 -04:00
fail ( err ) ;
} ) ;
2017-11-22 23:07:45 -08:00
} ) ;
2018-06-23 11:28:17 -05:00
2021-03-13 09:05:22 -06:00
it _exclude _dbs ( [ 'postgres' ] ) ( 'aggregate allow multiple of same stage' , async done => {
await reconfigureServer ( ) ;
2020-10-25 15:06:58 -05:00
const pointer1 = new TestObject ( { value : 1 } ) ;
const pointer2 = new TestObject ( { value : 2 } ) ;
const pointer3 = new TestObject ( { value : 3 } ) ;
const obj1 = new TestObject ( { pointer : pointer1 , name : 'Hello' } ) ;
const obj2 = new TestObject ( { pointer : pointer2 , name : 'Hello' } ) ;
const obj3 = new TestObject ( { pointer : pointer3 , name : 'World' } ) ;
const options = Object . assign ( { } , masterKeyOptions , {
body : {
pipeline : [
{
match : { name : 'Hello' } ,
} ,
{
// Transform className$objectId to objectId and store in new field tempPointer
project : {
tempPointer : { $substr : [ '$_p_pointer' , 11 , - 1 ] } , // Remove TestObject$
2018-09-01 13:58:06 -04:00
} ,
2020-10-25 15:06:58 -05:00
} ,
{
// Left Join, replace objectId stored in tempPointer with an actual object
lookup : {
from : 'test_TestObject' ,
localField : 'tempPointer' ,
foreignField : '_id' ,
as : 'tempPointer' ,
2018-09-24 17:07:51 -04:00
} ,
2020-10-25 15:06:58 -05:00
} ,
{
// lookup returns an array, Deconstructs an array field to objects
unwind : {
path : '$tempPointer' ,
2018-09-24 17:07:51 -04:00
} ,
2020-10-25 15:06:58 -05:00
} ,
{
match : { 'tempPointer.value' : 2 } ,
} ,
] ,
} ,
} ) ;
Parse . Object . saveAll ( [ pointer1 , pointer2 , pointer3 , obj1 , obj2 , obj3 ] )
. then ( ( ) => {
return get ( Parse . serverURL + '/aggregate/TestObject' , options ) ;
} )
. then ( resp => {
expect ( resp . results . length ) . toEqual ( 1 ) ;
expect ( resp . results [ 0 ] . tempPointer . value ) . toEqual ( 2 ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2020-10-25 15:06:58 -05:00
} ) ;
2020-03-29 22:15:40 +02:00
2020-09-08 22:16:03 +02:00
it _only _db ( 'mongo' ) ( 'aggregate geoNear with location query' , async ( ) => {
2020-03-29 22:15:40 +02:00
// Create geo index which is required for `geoNear` query
const database = Config . get ( Parse . applicationId ) . database ;
const schema = await new Parse . Schema ( 'GeoObject' ) . save ( ) ;
2020-10-25 15:06:58 -05:00
await database . adapter . ensureIndex ( 'GeoObject' , schema , [ 'location' ] , undefined , false , {
indexType : '2dsphere' ,
} ) ;
2020-03-29 22:15:40 +02:00
// Create objects
const GeoObject = Parse . Object . extend ( 'GeoObject' ) ;
2020-10-02 00:19:26 +02:00
const obj1 = new GeoObject ( {
value : 1 ,
location : new Parse . GeoPoint ( 1 , 1 ) ,
date : new Date ( 1 ) ,
} ) ;
const obj2 = new GeoObject ( {
value : 2 ,
location : new Parse . GeoPoint ( 2 , 1 ) ,
date : new Date ( 2 ) ,
} ) ;
const obj3 = new GeoObject ( {
value : 3 ,
location : new Parse . GeoPoint ( 3 , 1 ) ,
date : new Date ( 3 ) ,
} ) ;
2020-03-29 22:15:40 +02:00
await Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] ) ;
// Create query
const pipeline = [
{
geoNear : {
near : {
type : 'Point' ,
2020-10-02 00:19:26 +02:00
coordinates : [ 1 , 1 ] ,
2020-03-29 22:15:40 +02:00
} ,
key : 'location' ,
spherical : true ,
distanceField : 'dist' ,
query : {
date : {
2020-10-02 00:19:26 +02:00
$gte : new Date ( 2 ) ,
} ,
} ,
} ,
} ,
2020-03-29 22:15:40 +02:00
] ;
const query = new Parse . Query ( GeoObject ) ;
const results = await query . aggregate ( pipeline ) ;
// Check results
expect ( results . length ) . toEqual ( 2 ) ;
expect ( results [ 0 ] . value ) . toEqual ( 2 ) ;
expect ( results [ 1 ] . value ) . toEqual ( 3 ) ;
2021-03-13 09:05:22 -06:00
await database . adapter . deleteAllClasses ( false ) ;
2020-03-29 22:15:40 +02:00
} ) ;
2020-09-08 22:16:03 +02:00
it _only _db ( 'mongo' ) ( 'aggregate geoNear with near GeoJSON point' , async ( ) => {
// Create geo index which is required for `geoNear` query
const database = Config . get ( Parse . applicationId ) . database ;
const schema = await new Parse . Schema ( 'GeoObject' ) . save ( ) ;
2021-03-13 09:05:22 -06:00
await database . adapter . ensureIndex ( 'GeoObject' , schema , [ 'location' ] , undefined , false , {
indexType : '2dsphere' ,
} ) ;
2020-09-08 22:16:03 +02:00
// Create objects
const GeoObject = Parse . Object . extend ( 'GeoObject' ) ;
2020-10-02 00:19:26 +02:00
const obj1 = new GeoObject ( {
value : 1 ,
location : new Parse . GeoPoint ( 1 , 1 ) ,
date : new Date ( 1 ) ,
} ) ;
const obj2 = new GeoObject ( {
value : 2 ,
location : new Parse . GeoPoint ( 2 , 1 ) ,
date : new Date ( 2 ) ,
} ) ;
const obj3 = new GeoObject ( {
value : 3 ,
location : new Parse . GeoPoint ( 3 , 1 ) ,
date : new Date ( 3 ) ,
} ) ;
2020-09-08 22:16:03 +02:00
await Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] ) ;
// Create query
const pipeline = [
{
geoNear : {
near : {
type : 'Point' ,
2020-10-02 00:19:26 +02:00
coordinates : [ 1 , 1 ] ,
2020-09-08 22:16:03 +02:00
} ,
key : 'location' ,
spherical : true ,
2020-10-02 00:19:26 +02:00
distanceField : 'dist' ,
} ,
} ,
2020-09-08 22:16:03 +02:00
] ;
const query = new Parse . Query ( GeoObject ) ;
const results = await query . aggregate ( pipeline ) ;
// Check results
expect ( results . length ) . toEqual ( 3 ) ;
2021-03-13 09:05:22 -06:00
await database . adapter . deleteAllClasses ( false ) ;
2020-09-08 22:16:03 +02:00
} ) ;
2020-10-25 15:06:58 -05:00
it _only _db ( 'mongo' ) ( 'aggregate geoNear with near legacy coordinate pair' , async ( ) => {
// Create geo index which is required for `geoNear` query
const database = Config . get ( Parse . applicationId ) . database ;
const schema = await new Parse . Schema ( 'GeoObject' ) . save ( ) ;
2021-03-13 09:05:22 -06:00
await database . adapter . ensureIndex ( 'GeoObject' , schema , [ 'location' ] , undefined , false , {
indexType : '2dsphere' ,
} ) ;
2020-10-25 15:06:58 -05:00
// Create objects
const GeoObject = Parse . Object . extend ( 'GeoObject' ) ;
const obj1 = new GeoObject ( {
value : 1 ,
location : new Parse . GeoPoint ( 1 , 1 ) ,
date : new Date ( 1 ) ,
} ) ;
const obj2 = new GeoObject ( {
value : 2 ,
location : new Parse . GeoPoint ( 2 , 1 ) ,
date : new Date ( 2 ) ,
} ) ;
const obj3 = new GeoObject ( {
value : 3 ,
location : new Parse . GeoPoint ( 3 , 1 ) ,
date : new Date ( 3 ) ,
} ) ;
await Parse . Object . saveAll ( [ obj1 , obj2 , obj3 ] ) ;
// Create query
const pipeline = [
{
geoNear : {
near : [ 1 , 1 ] ,
key : 'location' ,
spherical : true ,
distanceField : 'dist' ,
2020-10-02 00:19:26 +02:00
} ,
2020-10-25 15:06:58 -05:00
} ,
] ;
const query = new Parse . Query ( GeoObject ) ;
const results = await query . aggregate ( pipeline ) ;
// Check results
expect ( results . length ) . toEqual ( 3 ) ;
2021-03-13 09:05:22 -06:00
await database . adapter . deleteAllClasses ( false ) ;
2020-10-25 15:06:58 -05:00
} ) ;
2017-11-12 13:00:22 -06:00
} ) ;