@@ -110,16 +110,23 @@ impl TopHitsAggregation {
110
110
#[ derive( Clone , Serialize , Deserialize , Debug ) ]
111
111
struct ComparableDocFeature {
112
112
/// Stores any u64-mappable feature.
113
- value : u64 ,
113
+ value : Option < u64 > ,
114
114
/// Sort order for the doc feature
115
115
order : Order ,
116
116
}
117
117
118
118
impl Ord for ComparableDocFeature {
119
119
fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
120
- match self . order {
121
- Order :: Asc => self . value . cmp ( & other. value ) ,
122
- Order :: Desc => other. value . cmp ( & self . value ) ,
120
+ let invert = |cmp : std:: cmp:: Ordering | match self . order {
121
+ Order :: Asc => cmp,
122
+ Order :: Desc => cmp. reverse ( ) ,
123
+ } ;
124
+
125
+ match ( self . value , other. value ) {
126
+ ( Some ( self_value) , Some ( other_value) ) => invert ( self_value. cmp ( & other_value) ) ,
127
+ ( Some ( _) , None ) => std:: cmp:: Ordering :: Greater ,
128
+ ( None , Some ( _) ) => std:: cmp:: Ordering :: Less ,
129
+ ( None , None ) => std:: cmp:: Ordering :: Equal ,
123
130
}
124
131
}
125
132
}
@@ -290,10 +297,9 @@ impl SegmentAggregationCollector for SegmentTopHitsCollector {
290
297
. zip ( self . inner_collector . req . sort . iter ( ) )
291
298
. map ( |( ( c, _) , KeyOrder ( _, order) ) | {
292
299
let order = * order;
293
- match c. values_for_doc ( doc_id) . next ( ) {
294
- Some ( value) => ComparableDocFeature { value, order } ,
295
- // TODO: confirm if this default 0-value is correct
296
- None => ComparableDocFeature { value : 0 , order } ,
300
+ ComparableDocFeature {
301
+ value : c. values_for_doc ( doc_id) . next ( ) ,
302
+ order,
297
303
}
298
304
} )
299
305
. collect ( ) ;
@@ -323,3 +329,54 @@ impl SegmentAggregationCollector for SegmentTopHitsCollector {
323
329
Ok ( ( ) )
324
330
}
325
331
}
332
+
333
+ #[ cfg( test) ]
334
+ mod tests {
335
+ use serde_json:: Value ;
336
+
337
+ use super :: { ComparableDoc , ComparableDocFeature , ComparableDocFeatures , Order } ;
338
+ use crate :: aggregation:: agg_req:: Aggregations ;
339
+ use crate :: aggregation:: agg_result:: AggregationResults ;
340
+ use crate :: aggregation:: bucket:: tests:: get_test_index_from_docs;
341
+ use crate :: aggregation:: tests:: get_test_index_from_values;
342
+ use crate :: aggregation:: AggregationCollector ;
343
+ use crate :: query:: AllQuery ;
344
+
345
+ fn invert_order ( cmp_feature : ComparableDocFeature ) -> ComparableDocFeature {
346
+ let ComparableDocFeature { value, order } = cmp_feature;
347
+ let order = match order {
348
+ Order :: Asc => Order :: Desc ,
349
+ Order :: Desc => Order :: Asc ,
350
+ } ;
351
+ ComparableDocFeature { value, order }
352
+ }
353
+
354
+ #[ test]
355
+ fn test_comparable_doc_feature ( ) -> crate :: Result < ( ) > {
356
+ let small = ComparableDocFeature {
357
+ value : Some ( 1 ) ,
358
+ order : Order :: Asc ,
359
+ } ;
360
+ let big = ComparableDocFeature {
361
+ value : Some ( 2 ) ,
362
+ order : Order :: Asc ,
363
+ } ;
364
+ let none = ComparableDocFeature {
365
+ value : None ,
366
+ order : Order :: Asc ,
367
+ } ;
368
+
369
+ assert ! ( small < big) ;
370
+ assert ! ( none < small) ;
371
+ assert ! ( none < big) ;
372
+
373
+ let small = invert_order ( small) ;
374
+ let big = invert_order ( big) ;
375
+ let none = invert_order ( none) ;
376
+
377
+ assert ! ( small > big) ;
378
+ assert ! ( none < small) ;
379
+ assert ! ( none < big) ;
380
+
381
+ Ok ( ( ) )
382
+ }
0 commit comments