@@ -444,22 +444,33 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem
444444 }
445445
446446 let promises = Object . keys ( query ) . map ( ( key ) => {
447- if ( query [ key ] && ( query [ key ] [ '$in' ] || query [ key ] . __type == 'Pointer' ) ) {
447+ if ( query [ key ] && ( query [ key ] [ '$in' ] || query [ key ] [ '$ne' ] || query [ key ] [ '$nin' ] || query [ key ] . __type == 'Pointer' ) ) {
448448 let t = schema . getExpectedType ( className , key ) ;
449449 let match = t ? t . match ( / ^ r e l a t i o n < ( .* ) > $ / ) : false ;
450450 if ( ! match ) {
451451 return Promise . resolve ( query ) ;
452452 }
453453 let relatedClassName = match [ 1 ] ;
454454 let relatedIds ;
455+ let isNegation = false ;
455456 if ( query [ key ] [ '$in' ] ) {
456457 relatedIds = query [ key ] [ '$in' ] . map ( r => r . objectId ) ;
458+ } else if ( query [ key ] [ '$nin' ] ) {
459+ isNegation = true ;
460+ relatedIds = query [ key ] [ '$nin' ] . map ( r => r . objectId ) ;
461+ } else if ( query [ key ] [ '$ne' ] ) {
462+ isNegation = true ;
463+ relatedIds = [ query [ key ] [ '$ne' ] . objectId ] ;
457464 } else {
458465 relatedIds = [ query [ key ] . objectId ] ;
459466 }
460467 return this . owningIds ( className , key , relatedIds ) . then ( ( ids ) => {
461468 delete query [ key ] ;
462- this . addInObjectIdsIds ( ids , query ) ;
469+ if ( isNegation ) {
470+ this . addNotInObjectIdsIds ( ids , query ) ;
471+ } else {
472+ this . addInObjectIdsIds ( ids , query ) ;
473+ }
463474 return Promise . resolve ( query ) ;
464475 } ) ;
465476 }
@@ -520,6 +531,29 @@ DatabaseController.prototype.addInObjectIdsIds = function(ids = null, query) {
520531 return query ;
521532}
522533
534+ DatabaseController . prototype . addNotInObjectIdsIds = function ( ids = null , query ) {
535+ let idsFromNin = query . objectId && query . objectId [ '$nin' ] ? query . objectId [ '$nin' ] : null ;
536+ let allIds = [ idsFromNin , ids ] . filter ( list => list !== null ) ;
537+ let totalLength = allIds . reduce ( ( memo , list ) => memo + list . length , 0 ) ;
538+
539+ let idsIntersection = [ ] ;
540+ if ( totalLength > 125 ) {
541+ idsIntersection = intersect . big ( allIds ) ;
542+ } else {
543+ idsIntersection = intersect ( allIds ) ;
544+ }
545+
546+ // Need to make sure we don't clobber existing $lt or other constraints on objectId.
547+ // Clobbering $eq, $in and shorthand $eq (query.objectId === 'string') constraints
548+ // is expected though.
549+ if ( ! ( 'objectId' in query ) || typeof query . objectId === 'string' ) {
550+ query . objectId = { } ;
551+ }
552+ query . objectId [ '$nin' ] = idsIntersection ;
553+
554+ return query ;
555+ }
556+
523557// Runs a query on the database.
524558// Returns a promise that resolves to a list of items.
525559// Options:
0 commit comments