@@ -444,22 +444,33 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem
444
444
}
445
445
446
446
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' ) ) {
448
448
let t = schema . getExpectedType ( className , key ) ;
449
449
let match = t ? t . match ( / ^ r e l a t i o n < ( .* ) > $ / ) : false ;
450
450
if ( ! match ) {
451
451
return Promise . resolve ( query ) ;
452
452
}
453
453
let relatedClassName = match [ 1 ] ;
454
454
let relatedIds ;
455
+ let isNegation = false ;
455
456
if ( query [ key ] [ '$in' ] ) {
456
457
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 ] ;
457
464
} else {
458
465
relatedIds = [ query [ key ] . objectId ] ;
459
466
}
460
467
return this . owningIds ( className , key , relatedIds ) . then ( ( ids ) => {
461
468
delete query [ key ] ;
462
- this . addInObjectIdsIds ( ids , query ) ;
469
+ if ( isNegation ) {
470
+ this . addNotInObjectIdsIds ( ids , query ) ;
471
+ } else {
472
+ this . addInObjectIdsIds ( ids , query ) ;
473
+ }
463
474
return Promise . resolve ( query ) ;
464
475
} ) ;
465
476
}
@@ -520,6 +531,29 @@ DatabaseController.prototype.addInObjectIdsIds = function(ids = null, query) {
520
531
return query ;
521
532
}
522
533
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
+
523
557
// Runs a query on the database.
524
558
// Returns a promise that resolves to a list of items.
525
559
// Options:
0 commit comments