@@ -431,11 +431,55 @@ function defineScope(cls, targetClass, name, params, methods, options) {
431
431
options = { } ;
432
432
}
433
433
options = options || { } ;
434
-
435
434
const targetModel = definition . targetModel ( this . _receiver ) ;
435
+ // If there is a through model
436
+ // run another query to apply filter on relatedModel(targetModel)
437
+ // see github.com/strongloop/loopback-datasource-juggler/issues/1795
438
+ let scopeOnRelatedModel = false ;
439
+ let queryRelated ;
440
+ let keyFrom ;
441
+ let relatedModel ;
442
+ let IdKey ;
443
+ let fieldsRelated ;
444
+ if ( this . _scope && this . _scope . collect &&
445
+ where !== null && typeof where === 'object' ) {
446
+ queryRelated = {
447
+ relation : this . _scope . collect ,
448
+ scope : {
449
+ where : where ,
450
+ } ,
451
+ } ;
452
+ where = { } ;
453
+ scopeOnRelatedModel = true ;
454
+ relatedModel = targetModel . relations [ queryRelated . relation ] . modelTo ;
455
+ IdKey = idName ( relatedModel ) ;
456
+ keyFrom = targetModel . relations [ queryRelated . relation ] . keyFrom || IdKey ;
457
+ fieldsRelated = [ keyFrom ] ;
458
+ }
436
459
const scoped = ( this . _scope && this . _scope . where ) || { } ;
437
- const filter = mergeQuery ( { where : scoped } , { where : where || { } } ) ;
438
- return targetModel . destroyAll ( filter . where , options , cb ) ;
460
+ const filter = mergeQuery ( { where : scoped } , { where : where || { } , fields : fieldsRelated } ) ;
461
+ if ( ! scopeOnRelatedModel ) {
462
+ return targetModel . destroyAll ( filter . where , options , cb ) ;
463
+ }
464
+ return targetModel . find ( filter , options , function ( err , findData ) {
465
+ // Merge queryRelated filter and targetId filter
466
+ const buildWhere = function ( ) {
467
+ return {
468
+ and : [
469
+ {
470
+ [ IdKey ] : collectTargetIds ( findData , keyFrom ) ,
471
+ } ,
472
+ queryRelated . scope . where ] ,
473
+ } ;
474
+ } ;
475
+ if ( queryRelated . scope . where !== undefined ) {
476
+ queryRelated . scope . where = buildWhere ( ) ;
477
+ } else {
478
+ queryRelated . scope . where = { } ;
479
+ queryRelated . scope . where [ IdKey ] = collectTargetIds ( findData , keyFrom ) ;
480
+ }
481
+ return relatedModel . destroyAll ( queryRelated . scope . where , options , cb ) ;
482
+ } ) ;
439
483
}
440
484
441
485
function updateAll ( where , data , options , cb ) {
@@ -453,9 +497,54 @@ function defineScope(cls, targetClass, name, params, methods, options) {
453
497
}
454
498
options = options || { } ;
455
499
const targetModel = definition . targetModel ( this . _receiver ) ;
500
+ // If there is a through model
501
+ // run another query to apply filter on relatedModel(targetModel)
502
+ // see github.com/strongloop/loopback-datasource-juggler/issues/1795
503
+ let scopeOnRelatedModel = false ;
504
+ let queryRelated ;
505
+ let keyFrom ;
506
+ let relatedModel ;
507
+ let IdKey ;
508
+ let fieldsRelated ;
509
+ if ( this . _scope && this . _scope . collect &&
510
+ where !== null && typeof where === 'object' ) {
511
+ queryRelated = {
512
+ relation : this . _scope . collect ,
513
+ scope : {
514
+ where : where ,
515
+ } ,
516
+ } ;
517
+ where = { } ;
518
+ scopeOnRelatedModel = true ;
519
+ relatedModel = targetModel . relations [ queryRelated . relation ] . modelTo ;
520
+ IdKey = idName ( relatedModel ) ;
521
+ keyFrom = targetModel . relations [ queryRelated . relation ] . keyFrom || IdKey ;
522
+ fieldsRelated = [ keyFrom ] ;
523
+ }
456
524
const scoped = ( this . _scope && this . _scope . where ) || { } ;
457
- const filter = mergeQuery ( { where : scoped } , { where : where || { } } ) ;
458
- return targetModel . updateAll ( filter . where , data , options , cb ) ;
525
+ const filter = mergeQuery ( { where : scoped } , { where : where || { } , fields : fieldsRelated } ) ;
526
+ if ( ! scopeOnRelatedModel ) {
527
+ return targetModel . updateAll ( filter . where , data , options , cb ) ;
528
+ }
529
+ return targetModel . find ( filter , options , function ( err , findData ) {
530
+ // Merge queryRelated filter and targetId filter
531
+ const buildWhere = function ( ) {
532
+ return {
533
+ and : [
534
+ {
535
+ [ IdKey ] : collectTargetIds ( findData , keyFrom ) ,
536
+ } ,
537
+ queryRelated . scope . where ] ,
538
+ } ;
539
+ } ;
540
+ if ( queryRelated . scope . where !== undefined ) {
541
+ queryRelated . scope . where = buildWhere ( ) ;
542
+ } else {
543
+ queryRelated . scope . where = { } ;
544
+ queryRelated . scope . where [ IdKey ] = collectTargetIds ( findData , keyFrom ) ;
545
+ }
546
+ return relatedModel . updateAll ( queryRelated . scope . where , data , options , cb ) ;
547
+ } ) ;
459
548
}
460
549
461
550
function findById ( id , filter , options , cb ) {
@@ -501,9 +590,52 @@ function defineScope(cls, targetClass, name, params, methods, options) {
501
590
}
502
591
options = options || { } ;
503
592
const targetModel = definition . targetModel ( this . _receiver ) ;
593
+ // If there is a through model
594
+ // run another query to apply filter on relatedModel(targetModel)
595
+ // see github.com/strongloop/loopback-datasource-juggler/issues/1795
596
+ let scopeOnRelatedModel = false ;
597
+ let queryRelated ;
598
+ let keyFrom ;
599
+ let relatedModel ;
600
+ let IdKey ;
601
+ if ( this . _scope && this . _scope . collect &&
602
+ filter && filter . where !== null && typeof filter . where === 'object' ) {
603
+ queryRelated = {
604
+ relation : this . _scope . collect ,
605
+ scope : filter ,
606
+ } ;
607
+ scopeOnRelatedModel = true ;
608
+ relatedModel = targetModel . relations [ queryRelated . relation ] . modelTo ;
609
+ IdKey = idName ( relatedModel ) ;
610
+ keyFrom = targetModel . relations [ queryRelated . relation ] . keyFrom || IdKey ;
611
+ filter = {
612
+ fields : [ keyFrom ] ,
613
+ } ;
614
+ }
504
615
const scoped = ( this . _scope && this . _scope . where ) || { } ;
505
616
filter = mergeQuery ( { where : scoped } , filter || { } ) ;
506
- return targetModel . findOne ( filter , options , cb ) ;
617
+ if ( ! scopeOnRelatedModel ) {
618
+ return targetModel . findOne ( filter , options , cb ) ;
619
+ }
620
+ return targetModel . find ( filter , options , function ( err , data ) {
621
+ // Merge queryRelated filter and targetId filter
622
+ const buildWhere = function ( ) {
623
+ return {
624
+ and : [
625
+ {
626
+ [ IdKey ] : collectTargetIds ( data , keyFrom ) ,
627
+ } ,
628
+ queryRelated . scope . where ] ,
629
+ } ;
630
+ } ;
631
+ if ( queryRelated . scope . where !== undefined ) {
632
+ queryRelated . scope . where = buildWhere ( ) ;
633
+ } else {
634
+ queryRelated . scope . where = { } ;
635
+ queryRelated . scope . where [ IdKey ] = collectTargetIds ( data , keyFrom ) ;
636
+ }
637
+ return relatedModel . findOne ( queryRelated . scope , options , cb ) ;
638
+ } ) ;
507
639
}
508
640
509
641
function count ( where , options , cb ) {
@@ -517,11 +649,55 @@ function defineScope(cls, targetClass, name, params, methods, options) {
517
649
options = { } ;
518
650
}
519
651
options = options || { } ;
520
-
521
652
const targetModel = definition . targetModel ( this . _receiver ) ;
653
+ // If there is a through model
654
+ // run another query to apply filter on relatedModel(targetModel)
655
+ // see github.com/strongloop/loopback-datasource-juggler/issues/1795
656
+ let scopeOnRelatedModel = false ;
657
+ let queryRelated ;
658
+ let keyFrom ;
659
+ let relatedModel ;
660
+ let IdKey ;
661
+ let fieldsRelated ;
662
+ if ( this . _scope && this . _scope . collect &&
663
+ where !== null && typeof where === 'object' ) {
664
+ queryRelated = {
665
+ relation : this . _scope . collect ,
666
+ scope : {
667
+ where : where ,
668
+ } ,
669
+ } ;
670
+ where = { } ;
671
+ scopeOnRelatedModel = true ;
672
+ relatedModel = targetModel . relations [ queryRelated . relation ] . modelTo ;
673
+ IdKey = idName ( relatedModel ) ;
674
+ keyFrom = targetModel . relations [ queryRelated . relation ] . keyFrom || IdKey ;
675
+ fieldsRelated = [ keyFrom ] ;
676
+ }
522
677
const scoped = ( this . _scope && this . _scope . where ) || { } ;
523
- const filter = mergeQuery ( { where : scoped } , { where : where || { } } ) ;
524
- return targetModel . count ( filter . where , options , cb ) ;
678
+ const filter = mergeQuery ( { where : scoped } , { where : where || { } , fields : fieldsRelated } ) ;
679
+ if ( ! scopeOnRelatedModel ) {
680
+ return targetModel . count ( filter . where , options , cb ) ;
681
+ }
682
+ return targetModel . find ( filter , options , function ( err , data ) {
683
+ // Merge queryRelated filter and targetId filter
684
+ const buildWhere = function ( ) {
685
+ return {
686
+ and : [
687
+ {
688
+ [ IdKey ] : collectTargetIds ( data , keyFrom ) ,
689
+ } ,
690
+ queryRelated . scope . where ] ,
691
+ } ;
692
+ } ;
693
+ if ( queryRelated . scope . where !== undefined ) {
694
+ queryRelated . scope . where = buildWhere ( ) ;
695
+ } else {
696
+ queryRelated . scope . where = { } ;
697
+ queryRelated . scope . where [ IdKey ] = collectTargetIds ( data , keyFrom ) ;
698
+ }
699
+ return relatedModel . count ( queryRelated . scope . where , options , cb ) ;
700
+ } ) ;
525
701
}
526
702
527
703
return definition ;
0 commit comments