17
17
use ApiPlatform \Doctrine \Odm \PropertyHelperTrait as MongoDbOdmPropertyHelperTrait ;
18
18
use ApiPlatform \Metadata \Operation ;
19
19
use Doctrine \ODM \MongoDB \Aggregation \Builder ;
20
+ use Doctrine \ODM \MongoDB \Aggregation \Stage \Search ;
20
21
use Doctrine \ODM \MongoDB \Aggregation \Stage \Sort ;
21
22
use Doctrine \Persistence \ManagerRegistry ;
22
23
@@ -66,7 +67,8 @@ public function applyToCollection(Builder $aggregationBuilder, string $resourceC
66
67
if ($ this ->isPropertyNested ($ field , $ resourceClass )) {
67
68
[$ field ] = $ this ->addLookupsForNestedProperty ($ field , $ aggregationBuilder , $ resourceClass , true );
68
69
}
69
- $ aggregationBuilder ->sort (
70
+ $ this ->addSort (
71
+ $ aggregationBuilder ,
70
72
$ context ['mongodb_odm_sort_fields ' ] = ($ context ['mongodb_odm_sort_fields ' ] ?? []) + [$ field => $ order ]
71
73
);
72
74
}
@@ -76,8 +78,9 @@ public function applyToCollection(Builder $aggregationBuilder, string $resourceC
76
78
77
79
if (null !== $ this ->order ) {
78
80
foreach ($ identifiers as $ identifier ) {
79
- $ aggregationBuilder ->sort (
80
- $ context ['mongodb_odm_sort_fields ' ] = ($ context ['mongodb_odm_sort_fields ' ] ?? []) + [$ identifier => $ this ->order ]
81
+ $ this ->addSort (
82
+ $ aggregationBuilder ,
83
+ $ context ['mongodb_odm_sort_fields ' ] = ($ context ['mongodb_odm_sort_fields ' ] ?? []) + [$ identifier => $ this ->order ],
81
84
);
82
85
}
83
86
}
@@ -88,26 +91,30 @@ protected function getManagerRegistry(): ManagerRegistry
88
91
return $ this ->managerRegistry ;
89
92
}
90
93
91
- private function hasSortStage (Builder $ aggregationBuilder ): bool
94
+ private function addSort (Builder $ aggregationBuilder, array $ sortFields ): void
92
95
{
93
- $ shouldStop = false ;
94
- $ index = 0 ;
96
+ $ firstStage = $ aggregationBuilder ->getPipeline (0 );
97
+ if ($ firstStage instanceof Search) {
98
+ // The $search stage supports "sort" for performance, it's always first if present
99
+ $ firstStage ->sort ($ sortFields );
100
+ } else {
101
+ // Append a $sort stage at the end of the pipeline
102
+ $ aggregationBuilder ->sort ($ sortFields );
103
+ }
104
+ }
95
105
96
- do {
97
- try {
106
+ private function hasSortStage (Builder $ aggregationBuilder ): bool
107
+ {
108
+ try {
109
+ for ($ index = 0 ; true ; $ index ++) {
98
110
if ($ aggregationBuilder ->getStage ($ index ) instanceof Sort) {
99
111
// If at least one stage is sort, then it has sorting
100
112
return true ;
101
113
}
102
- } catch (\OutOfRangeException $ outOfRangeException ) {
103
- // There is no more stages on the aggregation builder
104
- $ shouldStop = true ;
105
114
}
106
-
107
- ++$ index ;
108
- } while (!$ shouldStop );
109
-
110
- // No stage was sort, and we iterated through all stages
111
- return false ;
115
+ } catch (\OutOfRangeException ) {
116
+ // There is no more stages on the aggregation builder
117
+ return false ;
118
+ }
112
119
}
113
120
}
0 commit comments