11// A database adapter that works with data exported from the hosted
22// Parse database.
33
4+ import intersect from 'intersect' ;
5+
46var mongodb = require ( 'mongodb' ) ;
57var Parse = require ( 'parse/node' ) . Parse ;
68
@@ -492,18 +494,28 @@ DatabaseController.prototype.reduceRelationKeys = function(className, query) {
492494 }
493495} ;
494496
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 ) ;
500510 }
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 ;
507519
508520 return query ;
509521}
@@ -523,53 +535,47 @@ DatabaseController.prototype.addInObjectIdsIds = function(ids, query) {
523535// anything about users, ideally. Then, improve the format of the ACL
524536// arg to work like the others.
525537DatabaseController . prototype . find = function ( className , query , options = { } ) {
526- var mongoOptions = { } ;
538+ let mongoOptions = { } ;
527539 if ( options . skip ) {
528540 mongoOptions . skip = options . skip ;
529541 }
530542 if ( options . limit ) {
531543 mongoOptions . limit = options . limit ;
532544 }
533545
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 => {
541551 schema = s ;
542552 if ( options . sort ) {
543553 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 ) ;
546556 mongoOptions . sort [ mongoKey ] = options . sort [ key ] ;
547557 }
548558 }
549559
550560 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' ;
556564 return schema . validatePermission ( className , aclGroup , op ) ;
557565 }
558566 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 ) ;
567573 if ( ! isMaster ) {
568- var orParts = [
574+ let orParts = [
569575 { "_rperm" : { "$exists" : false } } ,
570576 { "_rperm" : { "$in" : [ "*" ] } }
571577 ] ;
572- for ( var acl of aclGroup ) {
578+ for ( let acl of aclGroup ) {
573579 orParts . push ( { "_rperm" : { "$in" : [ acl ] } } ) ;
574580 }
575581 mongoWhere = { '$and' : [ mongoWhere , { '$or' : orParts } ] } ;
0 commit comments