1
1
// A database adapter that works with data exported from the hosted
2
2
// Parse database.
3
3
4
+ import intersect from 'intersect' ;
5
+
4
6
var mongodb = require ( 'mongodb' ) ;
5
7
var Parse = require ( 'parse/node' ) . Parse ;
6
8
@@ -492,18 +494,28 @@ DatabaseController.prototype.reduceRelationKeys = function(className, query) {
492
494
}
493
495
} ;
494
496
495
- DatabaseController . prototype . addInObjectIdsIds = function ( ids , query ) {
496
- if ( typeof query . objectId == 'string' ) {
497
- // Add equality op as we are sure
498
- // we had a constraint on that one
499
- query . objectId = { '$eq' : query . objectId } ;
497
+ DatabaseController . prototype . addInObjectIdsIds = function ( ids = null , query ) {
498
+ let idsFromString = typeof query . objectId === 'string' ? [ query . objectId ] : null ;
499
+ let idsFromEq = query . objectId && query . objectId [ '$eq' ] ? [ query . objectId [ '$eq' ] ] : null ;
500
+ let idsFromIn = query . objectId && query . objectId [ '$in' ] ? query . objectId [ '$in' ] : null ;
501
+
502
+ let allIds = [ idsFromString , idsFromEq , idsFromIn , ids ] . filter ( list => list !== null ) ;
503
+ let totalLength = allIds . reduce ( ( memo , list ) => memo + list . length , 0 ) ;
504
+
505
+ let idsIntersection = [ ] ;
506
+ if ( totalLength > 125 ) {
507
+ idsIntersection = intersect . big ( allIds ) ;
508
+ } else {
509
+ idsIntersection = intersect ( allIds ) ;
500
510
}
501
- query . objectId = query . objectId || { } ;
502
- let queryIn = [ ] . concat ( query . objectId [ '$in' ] || [ ] , ids || [ ] ) ;
503
- // make a set and spread to remove duplicates
504
- // replace the $in operator as other constraints
505
- // may be set
506
- query . objectId [ '$in' ] = [ ...new Set ( queryIn ) ] ;
511
+
512
+ // Need to make sure we don't clobber existing $lt or other constraints on objectId.
513
+ // Clobbering $eq, $in and shorthand $eq (query.objectId === 'string') constraints
514
+ // is expected though.
515
+ if ( ! ( 'objectId' in query ) || typeof query . objectId === 'string' ) {
516
+ query . objectId = { } ;
517
+ }
518
+ query . objectId [ '$in' ] = idsIntersection ;
507
519
508
520
return query ;
509
521
}
@@ -523,53 +535,47 @@ DatabaseController.prototype.addInObjectIdsIds = function(ids, query) {
523
535
// anything about users, ideally. Then, improve the format of the ACL
524
536
// arg to work like the others.
525
537
DatabaseController . prototype . find = function ( className , query , options = { } ) {
526
- var mongoOptions = { } ;
538
+ let mongoOptions = { } ;
527
539
if ( options . skip ) {
528
540
mongoOptions . skip = options . skip ;
529
541
}
530
542
if ( options . limit ) {
531
543
mongoOptions . limit = options . limit ;
532
544
}
533
545
534
- var isMaster = ! ( 'acl' in options ) ;
535
- var aclGroup = options . acl || [ ] ;
536
- var acceptor = function ( schema ) {
537
- return schema . hasKeys ( className , keysForQuery ( query ) ) ;
538
- } ;
539
- var schema ;
540
- return this . loadSchema ( acceptor ) . then ( ( s ) => {
546
+ let isMaster = ! ( 'acl' in options ) ;
547
+ let aclGroup = options . acl || [ ] ;
548
+ let acceptor = schema => schema . hasKeys ( className , keysForQuery ( query ) )
549
+ let schema = null ;
550
+ return this . loadSchema ( acceptor ) . then ( s => {
541
551
schema = s ;
542
552
if ( options . sort ) {
543
553
mongoOptions . sort = { } ;
544
- for ( var key in options . sort ) {
545
- var mongoKey = transform . transformKey ( schema , className , key ) ;
554
+ for ( let key in options . sort ) {
555
+ let mongoKey = transform . transformKey ( schema , className , key ) ;
546
556
mongoOptions . sort [ mongoKey ] = options . sort [ key ] ;
547
557
}
548
558
}
549
559
550
560
if ( ! isMaster ) {
551
- var op = 'find' ;
552
- var k = Object . keys ( query ) ;
553
- if ( k . length == 1 && typeof query . objectId == 'string' ) {
554
- op = 'get' ;
555
- }
561
+ let op = typeof query . objectId == 'string' && Object . keys ( query ) . length === 1 ?
562
+ 'get' :
563
+ 'find' ;
556
564
return schema . validatePermission ( className , aclGroup , op ) ;
557
565
}
558
566
return Promise . resolve ( ) ;
559
- } ) . then ( ( ) => {
560
- return this . reduceRelationKeys ( className , query ) ;
561
- } ) . then ( ( ) => {
562
- return this . reduceInRelation ( className , query , schema ) ;
563
- } ) . then ( ( ) => {
564
- return this . adaptiveCollection ( className ) ;
565
- } ) . then ( collection => {
566
- var mongoWhere = transform . transformWhere ( schema , className , query ) ;
567
+ } )
568
+ . then ( ( ) => this . reduceRelationKeys ( className , query ) )
569
+ . then ( ( ) => this . reduceInRelation ( className , query , schema ) )
570
+ . then ( ( ) => this . adaptiveCollection ( className ) )
571
+ . then ( collection => {
572
+ let mongoWhere = transform . transformWhere ( schema , className , query ) ;
567
573
if ( ! isMaster ) {
568
- var orParts = [
574
+ let orParts = [
569
575
{ "_rperm" : { "$exists" : false } } ,
570
576
{ "_rperm" : { "$in" : [ "*" ] } }
571
577
] ;
572
- for ( var acl of aclGroup ) {
578
+ for ( let acl of aclGroup ) {
573
579
orParts . push ( { "_rperm" : { "$in" : [ acl ] } } ) ;
574
580
}
575
581
mongoWhere = { '$and' : [ mongoWhere , { '$or' : orParts } ] } ;
0 commit comments