1
1
//! This will enhance the request tree with access to the fastfield and metadata.
2
2
3
- use columnar:: { Column , ColumnBlockAccessor , ColumnType , StrColumn } ;
3
+ use std:: collections:: HashMap ;
4
+ use std:: io;
5
+
6
+ use columnar:: { Column , ColumnBlockAccessor , ColumnType , DynamicColumn , StrColumn } ;
4
7
5
8
use super :: agg_limits:: ResourceLimitGuard ;
6
9
use super :: agg_req:: { Aggregation , AggregationVariants , Aggregations } ;
@@ -14,7 +17,7 @@ use super::metric::{
14
17
use super :: segment_agg_result:: AggregationLimits ;
15
18
use super :: VecWithNames ;
16
19
use crate :: aggregation:: { f64_to_fastfield_u64, Key } ;
17
- use crate :: SegmentReader ;
20
+ use crate :: { SegmentOrdinal , SegmentReader } ;
18
21
19
22
#[ derive( Default ) ]
20
23
pub ( crate ) struct AggregationsWithAccessor {
@@ -32,6 +35,7 @@ impl AggregationsWithAccessor {
32
35
}
33
36
34
37
pub struct AggregationWithAccessor {
38
+ pub ( crate ) segment_ordinal : SegmentOrdinal ,
35
39
/// In general there can be buckets without fast field access, e.g. buckets that are created
36
40
/// based on search terms. That is not that case currently, but eventually this needs to be
37
41
/// Option or moved.
@@ -44,10 +48,16 @@ pub struct AggregationWithAccessor {
44
48
pub ( crate ) limits : ResourceLimitGuard ,
45
49
pub ( crate ) column_block_accessor : ColumnBlockAccessor < u64 > ,
46
50
/// Used for missing term aggregation, which checks all columns for existence.
51
+ /// And also for `top_hits` aggregation, which may sort on multiple fields.
47
52
/// By convention the missing aggregation is chosen, when this property is set
48
53
/// (instead bein set in `agg`).
49
54
/// If this needs to used by other aggregations, we need to refactor this.
50
- pub ( crate ) accessors : Vec < Column < u64 > > ,
55
+ // NOTE: we can make all other aggregations use this instead of the `accessor` and `field_type`
56
+ // (making them obsolete) But will it have a performance impact?
57
+ pub ( crate ) accessors : Vec < ( Column < u64 > , ColumnType ) > ,
58
+ /// Map field names to all associated column accessors.
59
+ /// This field is used for `docvalue_fields`, which is currently only supported for `top_hits`.
60
+ pub ( crate ) value_accessors : HashMap < String , Vec < DynamicColumn > > ,
51
61
pub ( crate ) agg : Aggregation ,
52
62
}
53
63
@@ -57,19 +67,55 @@ impl AggregationWithAccessor {
57
67
agg : & Aggregation ,
58
68
sub_aggregation : & Aggregations ,
59
69
reader : & SegmentReader ,
70
+ segment_ordinal : SegmentOrdinal ,
60
71
limits : AggregationLimits ,
61
72
) -> crate :: Result < Vec < AggregationWithAccessor > > {
62
- let add_agg_with_accessor = |accessor : Column < u64 > ,
73
+ let mut agg = agg. clone ( ) ;
74
+
75
+ let add_agg_with_accessor = |agg : & Aggregation ,
76
+ accessor : Column < u64 > ,
63
77
column_type : ColumnType ,
64
78
aggs : & mut Vec < AggregationWithAccessor > |
65
79
-> crate :: Result < ( ) > {
66
80
let res = AggregationWithAccessor {
81
+ segment_ordinal,
67
82
accessor,
68
- accessors : Vec :: new ( ) ,
83
+ accessors : Default :: default ( ) ,
84
+ value_accessors : Default :: default ( ) ,
69
85
field_type : column_type,
70
86
sub_aggregation : get_aggs_with_segment_accessor_and_validate (
71
87
sub_aggregation,
72
88
reader,
89
+ segment_ordinal,
90
+ & limits,
91
+ ) ?,
92
+ agg : agg. clone ( ) ,
93
+ limits : limits. new_guard ( ) ,
94
+ missing_value_for_accessor : None ,
95
+ str_dict_column : None ,
96
+ column_block_accessor : Default :: default ( ) ,
97
+ } ;
98
+ aggs. push ( res) ;
99
+ Ok ( ( ) )
100
+ } ;
101
+
102
+ let add_agg_with_accessors = |agg : & Aggregation ,
103
+ accessors : Vec < ( Column < u64 > , ColumnType ) > ,
104
+ aggs : & mut Vec < AggregationWithAccessor > ,
105
+ value_accessors : HashMap < String , Vec < DynamicColumn > > |
106
+ -> crate :: Result < ( ) > {
107
+ let ( accessor, field_type) = accessors. first ( ) . expect ( "at least one accessor" ) ;
108
+ let res = AggregationWithAccessor {
109
+ segment_ordinal,
110
+ // TODO: We should do away with the `accessor` field altogether
111
+ accessor : accessor. clone ( ) ,
112
+ value_accessors,
113
+ field_type : * field_type,
114
+ accessors,
115
+ sub_aggregation : get_aggs_with_segment_accessor_and_validate (
116
+ sub_aggregation,
117
+ reader,
118
+ segment_ordinal,
73
119
& limits,
74
120
) ?,
75
121
agg : agg. clone ( ) ,
@@ -84,32 +130,36 @@ impl AggregationWithAccessor {
84
130
85
131
let mut res: Vec < AggregationWithAccessor > = Vec :: new ( ) ;
86
132
use AggregationVariants :: * ;
87
- match & agg. agg {
133
+
134
+ match agg. agg {
88
135
Range ( RangeAggregation {
89
- field : field_name, ..
136
+ field : ref field_name,
137
+ ..
90
138
} ) => {
91
139
let ( accessor, column_type) =
92
140
get_ff_reader ( reader, field_name, Some ( get_numeric_or_date_column_types ( ) ) ) ?;
93
- add_agg_with_accessor ( accessor, column_type, & mut res) ?;
141
+ add_agg_with_accessor ( & agg , accessor, column_type, & mut res) ?;
94
142
}
95
143
Histogram ( HistogramAggregation {
96
- field : field_name, ..
144
+ field : ref field_name,
145
+ ..
97
146
} ) => {
98
147
let ( accessor, column_type) =
99
148
get_ff_reader ( reader, field_name, Some ( get_numeric_or_date_column_types ( ) ) ) ?;
100
- add_agg_with_accessor ( accessor, column_type, & mut res) ?;
149
+ add_agg_with_accessor ( & agg , accessor, column_type, & mut res) ?;
101
150
}
102
151
DateHistogram ( DateHistogramAggregationReq {
103
- field : field_name, ..
152
+ field : ref field_name,
153
+ ..
104
154
} ) => {
105
155
let ( accessor, column_type) =
106
156
// Only DateTime is supported for DateHistogram
107
157
get_ff_reader ( reader, field_name, Some ( & [ ColumnType :: DateTime ] ) ) ?;
108
- add_agg_with_accessor ( accessor, column_type, & mut res) ?;
158
+ add_agg_with_accessor ( & agg , accessor, column_type, & mut res) ?;
109
159
}
110
160
Terms ( TermsAggregation {
111
- field : field_name,
112
- missing,
161
+ field : ref field_name,
162
+ ref missing,
113
163
..
114
164
} ) => {
115
165
let str_dict_column = reader. fast_fields ( ) . str ( field_name) ?;
@@ -162,24 +212,11 @@ impl AggregationWithAccessor {
162
212
let column_and_types =
163
213
get_all_ff_reader_or_empty ( reader, field_name, None , fallback_type) ?;
164
214
165
- let accessors: Vec < Column > =
166
- column_and_types. iter ( ) . map ( |( a, _) | a. clone ( ) ) . collect ( ) ;
167
- let agg_wit_acc = AggregationWithAccessor {
168
- missing_value_for_accessor : None ,
169
- accessor : accessors[ 0 ] . clone ( ) ,
170
- accessors,
171
- field_type : ColumnType :: U64 ,
172
- sub_aggregation : get_aggs_with_segment_accessor_and_validate (
173
- sub_aggregation,
174
- reader,
175
- & limits,
176
- ) ?,
177
- agg : agg. clone ( ) ,
178
- str_dict_column : str_dict_column. clone ( ) ,
179
- limits : limits. new_guard ( ) ,
180
- column_block_accessor : Default :: default ( ) ,
181
- } ;
182
- res. push ( agg_wit_acc) ;
215
+ let accessors = column_and_types
216
+ . iter ( )
217
+ . map ( |c_t| ( c_t. 0 . clone ( ) , c_t. 1 ) )
218
+ . collect ( ) ;
219
+ add_agg_with_accessors ( & agg, accessors, & mut res, Default :: default ( ) ) ?;
183
220
}
184
221
185
222
for ( accessor, column_type) in column_and_types {
@@ -189,21 +226,25 @@ impl AggregationWithAccessor {
189
226
missing. clone ( )
190
227
} ;
191
228
192
- let missing_value_for_accessor =
193
- if let Some ( missing) = missing_value_term_agg. as_ref ( ) {
194
- get_missing_val ( column_type, missing, agg. agg . get_fast_field_name ( ) ) ?
195
- } else {
196
- None
197
- } ;
229
+ let missing_value_for_accessor = if let Some ( missing) =
230
+ missing_value_term_agg. as_ref ( )
231
+ {
232
+ get_missing_val ( column_type, missing, agg. agg . get_fast_field_names ( ) [ 0 ] ) ?
233
+ } else {
234
+ None
235
+ } ;
198
236
199
237
let agg = AggregationWithAccessor {
238
+ segment_ordinal,
200
239
missing_value_for_accessor,
201
240
accessor,
202
- accessors : Vec :: new ( ) ,
241
+ accessors : Default :: default ( ) ,
242
+ value_accessors : Default :: default ( ) ,
203
243
field_type : column_type,
204
244
sub_aggregation : get_aggs_with_segment_accessor_and_validate (
205
245
sub_aggregation,
206
246
reader,
247
+ segment_ordinal,
207
248
& limits,
208
249
) ?,
209
250
agg : agg. clone ( ) ,
@@ -215,34 +256,63 @@ impl AggregationWithAccessor {
215
256
}
216
257
}
217
258
Average ( AverageAggregation {
218
- field : field_name, ..
259
+ field : ref field_name,
260
+ ..
219
261
} )
220
262
| Count ( CountAggregation {
221
- field : field_name, ..
263
+ field : ref field_name,
264
+ ..
222
265
} )
223
266
| Max ( MaxAggregation {
224
- field : field_name, ..
267
+ field : ref field_name,
268
+ ..
225
269
} )
226
270
| Min ( MinAggregation {
227
- field : field_name, ..
271
+ field : ref field_name,
272
+ ..
228
273
} )
229
274
| Stats ( StatsAggregation {
230
- field : field_name, ..
275
+ field : ref field_name,
276
+ ..
231
277
} )
232
278
| Sum ( SumAggregation {
233
- field : field_name, ..
279
+ field : ref field_name,
280
+ ..
234
281
} ) => {
235
282
let ( accessor, column_type) =
236
283
get_ff_reader ( reader, field_name, Some ( get_numeric_or_date_column_types ( ) ) ) ?;
237
- add_agg_with_accessor ( accessor, column_type, & mut res) ?;
284
+ add_agg_with_accessor ( & agg , accessor, column_type, & mut res) ?;
238
285
}
239
- Percentiles ( percentiles) => {
286
+ Percentiles ( ref percentiles) => {
240
287
let ( accessor, column_type) = get_ff_reader (
241
288
reader,
242
289
percentiles. field_name ( ) ,
243
290
Some ( get_numeric_or_date_column_types ( ) ) ,
244
291
) ?;
245
- add_agg_with_accessor ( accessor, column_type, & mut res) ?;
292
+ add_agg_with_accessor ( & agg, accessor, column_type, & mut res) ?;
293
+ }
294
+ TopHits ( ref mut top_hits) => {
295
+ top_hits. validate_and_resolve ( reader. fast_fields ( ) . columnar ( ) ) ?;
296
+ let accessors: Vec < ( Column < u64 > , ColumnType ) > = top_hits
297
+ . field_names ( )
298
+ . iter ( )
299
+ . map ( |field| {
300
+ get_ff_reader ( reader, field, Some ( get_numeric_or_date_column_types ( ) ) )
301
+ } )
302
+ . collect :: < crate :: Result < _ > > ( ) ?;
303
+
304
+ let value_accessors = top_hits
305
+ . value_field_names ( )
306
+ . iter ( )
307
+ . map ( |field_name| {
308
+ Ok ( (
309
+ field_name. to_string ( ) ,
310
+ get_dynamic_columns ( reader, field_name) ?,
311
+ ) )
312
+ } )
313
+ . collect :: < crate :: Result < _ > > ( ) ?;
314
+
315
+ add_agg_with_accessors ( & agg, accessors, & mut res, value_accessors) ?;
246
316
}
247
317
} ;
248
318
@@ -284,6 +354,7 @@ fn get_numeric_or_date_column_types() -> &'static [ColumnType] {
284
354
pub ( crate ) fn get_aggs_with_segment_accessor_and_validate (
285
355
aggs : & Aggregations ,
286
356
reader : & SegmentReader ,
357
+ segment_ordinal : SegmentOrdinal ,
287
358
limits : & AggregationLimits ,
288
359
) -> crate :: Result < AggregationsWithAccessor > {
289
360
let mut aggss = Vec :: new ( ) ;
@@ -292,6 +363,7 @@ pub(crate) fn get_aggs_with_segment_accessor_and_validate(
292
363
agg,
293
364
agg. sub_aggregation ( ) ,
294
365
reader,
366
+ segment_ordinal,
295
367
limits. clone ( ) ,
296
368
) ?;
297
369
for agg in aggs {
@@ -321,6 +393,19 @@ fn get_ff_reader(
321
393
Ok ( ff_field_with_type)
322
394
}
323
395
396
+ fn get_dynamic_columns (
397
+ reader : & SegmentReader ,
398
+ field_name : & str ,
399
+ ) -> crate :: Result < Vec < columnar:: DynamicColumn > > {
400
+ let ff_fields = reader. fast_fields ( ) . dynamic_column_handles ( field_name) ?;
401
+ let cols = ff_fields
402
+ . iter ( )
403
+ . map ( |h| h. open ( ) )
404
+ . collect :: < io:: Result < _ > > ( ) ?;
405
+ assert ! ( !ff_fields. is_empty( ) , "field {} not found" , field_name) ;
406
+ Ok ( cols)
407
+ }
408
+
324
409
/// Get all fast field reader or empty as default.
325
410
///
326
411
/// Is guaranteed to return at least one column.
0 commit comments