3030import org .elasticsearch .search .aggregations .InternalAggregation ;
3131import org .elasticsearch .search .aggregations .NonCollectingAggregator ;
3232import org .elasticsearch .search .aggregations .pipeline .PipelineAggregator ;
33+ import org .elasticsearch .search .aggregations .support .AggregatorSupplier ;
34+ import org .elasticsearch .search .aggregations .support .CoreValuesSourceType ;
3335import org .elasticsearch .search .aggregations .support .ValuesSource ;
3436import org .elasticsearch .search .aggregations .support .ValuesSourceAggregatorFactory ;
3537import org .elasticsearch .search .aggregations .support .ValuesSourceConfig ;
38+ import org .elasticsearch .search .aggregations .support .ValuesSourceRegistry ;
3639import org .elasticsearch .search .internal .SearchContext ;
3740
3841import java .io .IOException ;
@@ -44,6 +47,88 @@ public class RareTermsAggregatorFactory extends ValuesSourceAggregatorFactory {
4447 private final int maxDocCount ;
4548 private final double precision ;
4649
50+ static void registerAggregators (ValuesSourceRegistry valuesSourceRegistry ) {
51+ valuesSourceRegistry .register (RareTermsAggregationBuilder .NAME ,
52+ List .of (CoreValuesSourceType .BYTES , CoreValuesSourceType .IP ),
53+ RareTermsAggregatorFactory .bytesSupplier ());
54+
55+ valuesSourceRegistry .register (RareTermsAggregationBuilder .NAME ,
56+ List .of (CoreValuesSourceType .DATE , CoreValuesSourceType .BOOLEAN , CoreValuesSourceType .NUMERIC ),
57+ RareTermsAggregatorFactory .numericSupplier ());
58+ }
59+
60+ /**
61+ * This supplier is used for all the field types that should be aggregated as bytes/strings,
62+ * including those that need global ordinals
63+ */
64+ private static RareTermsAggregatorSupplier bytesSupplier () {
65+ return new RareTermsAggregatorSupplier () {
66+ @ Override
67+ public Aggregator build (String name ,
68+ AggregatorFactories factories ,
69+ ValuesSource valuesSource ,
70+ DocValueFormat format ,
71+ int maxDocCount ,
72+ double precision ,
73+ IncludeExclude includeExclude ,
74+ SearchContext context ,
75+ Aggregator parent ,
76+ List <PipelineAggregator > pipelineAggregators ,
77+ Map <String , Object > metaData ) throws IOException {
78+
79+ ExecutionMode execution = ExecutionMode .MAP ; //TODO global ords not implemented yet, only supports "map"
80+
81+ if ((includeExclude != null ) && (includeExclude .isRegexBased ()) && format != DocValueFormat .RAW ) {
82+ throw new IllegalArgumentException ("Aggregation [" + name + "] cannot support " +
83+ "regular expression style include/exclude settings as they can only be applied to string fields. " +
84+ "Use an array of values for include/exclude clauses" );
85+ }
86+
87+ return execution .create (name , factories , valuesSource , format ,
88+ includeExclude , context , parent , pipelineAggregators , metaData , maxDocCount , precision );
89+
90+ }
91+ };
92+ }
93+
94+ /**
95+ * This supplier is used for all fields that expect to be aggregated as a numeric value.
96+ * This includes floating points, and formatted types that use numerics internally for storage (date, boolean, etc)
97+ */
98+ private static RareTermsAggregatorSupplier numericSupplier () {
99+ return new RareTermsAggregatorSupplier () {
100+ @ Override
101+ public Aggregator build (String name ,
102+ AggregatorFactories factories ,
103+ ValuesSource valuesSource ,
104+ DocValueFormat format ,
105+ int maxDocCount ,
106+ double precision ,
107+ IncludeExclude includeExclude ,
108+ SearchContext context ,
109+ Aggregator parent ,
110+ List <PipelineAggregator > pipelineAggregators ,
111+ Map <String , Object > metaData ) throws IOException {
112+
113+ if ((includeExclude != null ) && (includeExclude .isRegexBased ())) {
114+ throw new IllegalArgumentException ("Aggregation [" + name + "] cannot support regular expression " +
115+ "style include/exclude settings as they can only be applied to string fields. Use an array of numeric " +
116+ "values for include/exclude clauses used to filter numeric fields" );
117+ }
118+
119+ IncludeExclude .LongFilter longFilter = null ;
120+ if (((ValuesSource .Numeric ) valuesSource ).isFloatingPoint ()) {
121+ throw new IllegalArgumentException ("RareTerms aggregation does not support floating point fields." );
122+ }
123+ if (includeExclude != null ) {
124+ longFilter = includeExclude .convertToLongFilter (format );
125+ }
126+ return new LongRareTermsAggregator (name , factories , (ValuesSource .Numeric ) valuesSource , format ,
127+ context , parent , longFilter , maxDocCount , precision , pipelineAggregators , metaData );
128+ }
129+ };
130+ }
131+
47132 RareTermsAggregatorFactory (String name , ValuesSourceConfig config ,
48133 IncludeExclude includeExclude ,
49134 QueryShardContext queryShardContext ,
@@ -79,40 +164,16 @@ protected Aggregator doCreateInternal(ValuesSource valuesSource,
79164 if (collectsFromSingleBucket == false ) {
80165 return asMultiBucketAggregator (this , searchContext , parent );
81166 }
82- if (valuesSource instanceof ValuesSource .Bytes ) {
83- ExecutionMode execution = ExecutionMode .MAP ; //TODO global ords not implemented yet, only supports "map"
84-
85- DocValueFormat format = config .format ();
86- if ((includeExclude != null ) && (includeExclude .isRegexBased ()) && format != DocValueFormat .RAW ) {
87- throw new AggregationExecutionException ("Aggregation [" + name + "] cannot support " +
88- "regular expression style include/exclude settings as they can only be applied to string fields. " +
89- "Use an array of values for include/exclude clauses" );
90- }
91-
92- return execution .create (name , factories , valuesSource , format ,
93- includeExclude , searchContext , parent , pipelineAggregators , metaData , maxDocCount , precision );
94- }
95-
96- if ((includeExclude != null ) && (includeExclude .isRegexBased ())) {
97- throw new AggregationExecutionException ("Aggregation [" + name + "] cannot support regular expression style include/exclude "
98- + "settings as they can only be applied to string fields. Use an array of numeric values for include/exclude clauses " +
99- "used to filter numeric fields" );
100- }
101167
102- if (valuesSource instanceof ValuesSource .Numeric ) {
103- IncludeExclude .LongFilter longFilter = null ;
104- if (((ValuesSource .Numeric ) valuesSource ).isFloatingPoint ()) {
105- throw new AggregationExecutionException ("RareTerms aggregation does not support floating point fields." );
106- }
107- if (includeExclude != null ) {
108- longFilter = includeExclude .convertToLongFilter (config .format ());
109- }
110- return new LongRareTermsAggregator (name , factories , (ValuesSource .Numeric ) valuesSource , config .format (),
111- searchContext , parent , longFilter , maxDocCount , precision , pipelineAggregators , metaData );
168+ AggregatorSupplier aggregatorSupplier = queryShardContext .getValuesSourceRegistry ().getAggregator (config .valueSourceType (),
169+ RareTermsAggregationBuilder .NAME );
170+ if (aggregatorSupplier instanceof RareTermsAggregatorSupplier == false ) {
171+ throw new AggregationExecutionException ("Registry miss-match - expected RareTermsAggregatorSupplier, found [" +
172+ aggregatorSupplier .getClass ().toString () + "]" );
112173 }
113174
114- throw new AggregationExecutionException ( "RareTerms aggregation cannot be applied to field [" + config .fieldContext (). field ()
115- + "]. It can only be applied to numeric or string fields." );
175+ return (( RareTermsAggregatorSupplier ) aggregatorSupplier ). build ( name , factories , valuesSource , config .format (),
176+ maxDocCount , precision , includeExclude , searchContext , parent , pipelineAggregators , metaData );
116177 }
117178
118179 public enum ExecutionMode {
0 commit comments