001/*
002 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved.
003 *
004 * Project and contact information: http://www.cascading.org/
005 *
006 * This file is part of the Cascading project.
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *     http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020
021package cascading.pipe.assembly;
022
023import java.beans.ConstructorProperties;
024
025import cascading.flow.FlowProcess;
026import cascading.operation.aggregator.Sum;
027import cascading.pipe.Pipe;
028import cascading.tuple.Fields;
029import cascading.tuple.Tuple;
030import cascading.tuple.TupleEntry;
031import cascading.tuple.Tuples;
032
033/**
034 * Class CountBy is used to count duplicates in a tuple stream, where "duplicates" means all tuples with the same
035 * values for the groupingFields fields. The resulting count is output as a long value in the specified countField.
036 * <p/>
037 * Typically finding the count of a field in a tuple stream relies on a {@link cascading.pipe.GroupBy} and a
038 * {@link cascading.operation.aggregator.Count} {@link cascading.operation.Aggregator} operation.
039 * <p/>
040 * The CountBy SubAssembly is a (typically) more efficient replacement for these two steps, because it does map-side
041 * pre-reduce counting (via {@link CountBy.CountPartials}  {@link AggregateBy.Functor}) before the GroupBy operator;
042 * this reduces network I/O from the map to reduce phases.
043 * <p/>
044 * This strategy is similar to using {@code combiners}, except no sorting or serialization is invoked and results
045 * in a much simpler mechanism.
046 * <p/>
047 * The {@code threshold} value tells the underlying CountPartials functions how many unique key counts to accumulate
048 * in the LRU cache, before emitting the least recently used entry. This accumulation happens map-side, and thus is
049 * bounded by the size of your map task JVM and the typical size of each group key.
050 * <p/>
051 * By default, either the value of {@link cascading.pipe.assembly.AggregateByProps#AGGREGATE_BY_CAPACITY} System property
052 * or {@link cascading.pipe.assembly.AggregateByProps#AGGREGATE_BY_DEFAULT_CAPACITY} will be used.
053 * <p/>
054 * If {@code include} is {@link Include#NO_NULLS}, argument tuples with all null values will be ignored.
055 * <p/>
056 * The values in the argument Tuple are normally all the remaining fields not used for grouping, but this can be
057 * narrowed using the valueFields parameter. When counting the occurrence of a single field (when {@code valueFields}
058 * is set on the constructor), this is the same behavior as {@code select count(foo) ...} in SQL. If {@code include} is
059 * {@link Include#ONLY_NULLS} then only argument tuples with all null values will be counted.
060 *
061 * @see AggregateBy
062 */
063public class CountBy extends AggregateBy
064  {
065  public enum Include
066    {
067      ALL,
068      NO_NULLS,
069      ONLY_NULLS
070    }
071
072  /**
073   * Class CountPartials is a {@link AggregateBy.Functor} that is used to count observed duplicates from the tuple stream.
074   * <p/>
075   * Use this class typically in tandem with a {@link cascading.operation.aggregator.Sum}
076   * {@link cascading.operation.Aggregator} in order to improve counting performance by removing as many values
077   * as possible before the intermediate {@link cascading.pipe.GroupBy} operator.
078   *
079   * @see CountBy
080   */
081  public static class CountPartials implements Functor
082    {
083    private final Fields declaredFields;
084    private final Include include;
085
086    /**
087     * Constructor CountPartials creates a new CountPartials instance.
088     *
089     * @param declaredFields of type Fields
090     */
091    public CountPartials( Fields declaredFields )
092      {
093      this( declaredFields, Include.ALL );
094      }
095
096    public CountPartials( Fields declaredFields, Include include )
097      {
098      this.declaredFields = declaredFields;
099      this.include = include;
100
101      if( !declaredFields.isDeclarator() || declaredFields.size() != 1 )
102        throw new IllegalArgumentException( "declaredFields should declare only one field name" );
103      }
104
105    @Override
106    public Fields getDeclaredFields()
107      {
108      return declaredFields;
109      }
110
111    @Override
112    public Tuple aggregate( FlowProcess flowProcess, TupleEntry args, Tuple context )
113      {
114      if( context == null )
115        context = new Tuple( 0L );
116
117      switch( include )
118        {
119        case ALL:
120          break;
121
122        case NO_NULLS:
123          if( Tuples.frequency( args, null ) == args.size() )
124            return context;
125
126          break;
127
128        case ONLY_NULLS:
129          if( Tuples.frequency( args, null ) != args.size() )
130            return context;
131
132          break;
133        }
134
135      context.set( 0, context.getLong( 0 ) + 1L );
136
137      return context;
138      }
139
140    @Override
141    public Tuple complete( FlowProcess flowProcess, Tuple context )
142      {
143      return context;
144      }
145    }
146
147  //// AggregateBy param constructors
148
149  /**
150   * Constructor CountBy creates a new CountBy instance. Use this constructor when used with a {@link AggregateBy}
151   * instance.
152   *
153   * @param countField of type Fields
154   */
155  @ConstructorProperties({"countField"})
156  public CountBy( Fields countField )
157    {
158    super( Fields.ALL, new CountPartials( countField.applyTypes( Long.TYPE ) ), new Sum( countField.applyTypes( Long.TYPE ) ) );
159    }
160
161  /**
162   * Constructor CountBy creates a new CountBy instance. Use this constructor when used with a {@link AggregateBy}
163   * instance.
164   *
165   * @param countField of type Fields
166   * @param include    of type Include
167   */
168  @ConstructorProperties({"countField", "include"})
169  public CountBy( Fields countField, Include include )
170    {
171    super( Fields.ALL, new CountPartials( countField.applyTypes( Long.TYPE ), include ), new Sum( countField.applyTypes( Long.TYPE ) ) );
172    }
173
174  /**
175   * Constructor CountBy creates a new CountBy instance. Use this constructor when used with a {@link AggregateBy}
176   * instance.
177   *
178   * @param countField of type Fields
179   */
180  @ConstructorProperties({"valueFields", "countField"})
181  public CountBy( Fields valueFields, Fields countField )
182    {
183    super( valueFields, new CountPartials( countField.applyTypes( Long.TYPE ) ), new Sum( countField.applyTypes( Long.TYPE ) ) );
184    }
185
186  /**
187   * Constructor CountBy creates a new CountBy instance. Use this constructor when used with a {@link AggregateBy}
188   * instance.
189   *
190   * @param countField of type Fields
191   */
192  @ConstructorProperties({"valueFields", "countField", "include"})
193  public CountBy( Fields valueFields, Fields countField, Include include )
194    {
195    super( valueFields, new CountPartials( countField.applyTypes( Long.TYPE ), include ), new Sum( countField.applyTypes( Long.TYPE ) ) );
196    }
197
198  ///////
199
200  /**
201   * Constructor CountBy creates a new CountBy instance.
202   *
203   * @param pipe           of type Pipe
204   * @param groupingFields of type Fields
205   * @param countField     of type Fields
206   */
207  @ConstructorProperties({"pipe", "groupingFields", "countField"})
208  public CountBy( Pipe pipe, Fields groupingFields, Fields countField )
209    {
210    this( null, pipe, groupingFields, countField );
211    }
212
213  /**
214   * Constructor CountBy creates a new CountBy instance.
215   *
216   * @param pipe           of type Pipe
217   * @param groupingFields of type Fields
218   * @param countField     fo type Fields
219   * @param threshold      of type int
220   */
221  @ConstructorProperties({"pipe", "groupingFields", "countField", "threshold"})
222  public CountBy( Pipe pipe, Fields groupingFields, Fields countField, int threshold )
223    {
224    this( null, pipe, groupingFields, countField, threshold );
225    }
226
227  /**
228   * Constructor CountBy creates a new CountBy instance.
229   *
230   * @param name           of type String
231   * @param pipe           of type Pipe
232   * @param groupingFields of type Fields
233   * @param countField     of type Fields
234   */
235  @ConstructorProperties({"name", "pipe", "groupingFields", "countField"})
236  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields countField )
237    {
238    this( name, pipe, groupingFields, countField, USE_DEFAULT_THRESHOLD );
239    }
240
241  /**
242   * Constructor CountBy creates a new CountBy instance.
243   *
244   * @param name           of type String
245   * @param pipe           of type Pipe
246   * @param groupingFields of type Fields
247   * @param countField     of type Fields
248   * @param threshold      of type int
249   */
250  @ConstructorProperties({"name", "pipe", "groupingFields", "countField", "threshold"})
251  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields countField, int threshold )
252    {
253    this( name, Pipe.pipes( pipe ), groupingFields, countField, threshold );
254    }
255
256  /**
257   * Constructor CountBy creates a new CountBy instance.
258   *
259   * @param pipes          of type Pipe[]
260   * @param groupingFields of type Fields
261   * @param countField     of type Fields
262   */
263  @ConstructorProperties({"pipes", "groupingFields", "countField"})
264  public CountBy( Pipe[] pipes, Fields groupingFields, Fields countField )
265    {
266    this( null, pipes, groupingFields, countField, USE_DEFAULT_THRESHOLD );
267    }
268
269  /**
270   * Constructor CountBy creates a new CountBy instance.
271   *
272   * @param pipes          of type Pipe[]
273   * @param groupingFields of type Fields
274   * @param countField     of type Fields
275   * @param threshold      of type int
276   */
277  @ConstructorProperties({"pipes", "groupingFields", "countField", "threshold"})
278  public CountBy( Pipe[] pipes, Fields groupingFields, Fields countField, int threshold )
279    {
280    this( null, pipes, groupingFields, countField, threshold );
281    }
282
283  /**
284   * Constructor CountBy creates a new CountBy instance.
285   *
286   * @param name           of type String
287   * @param pipes          of type Pipe[]
288   * @param groupingFields of type Fields
289   * @param countField     of type Fields
290   */
291  @ConstructorProperties({"name", "pipes", "groupingFields", "countField"})
292  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields countField )
293    {
294    this( name, pipes, groupingFields, countField, USE_DEFAULT_THRESHOLD );
295    }
296
297  /**
298   * Constructor CountBy creates a new CountBy instance.
299   *
300   * @param name           of type String
301   * @param pipes          of type Pipe[]
302   * @param groupingFields of type Fields
303   * @param countField     of type Fields
304   * @param threshold      of type int
305   */
306  @ConstructorProperties({"name", "pipes", "groupingFields", "countField", "threshold"})
307  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields countField, int threshold )
308    {
309    super( name, pipes, groupingFields, groupingFields, new CountPartials( countField.applyTypes( Long.TYPE ) ), new Sum( countField.applyTypes( Long.TYPE ) ), threshold );
310    }
311
312  ///////
313
314  /**
315   * Constructor CountBy creates a new CountBy instance.
316   *
317   * @param pipe           of type Pipe
318   * @param groupingFields of type Fields
319   * @param countField     of type Fields
320   * @param include        of type Include
321   */
322  @ConstructorProperties({"pipe", "groupingFields", "countField", "include"})
323  public CountBy( Pipe pipe, Fields groupingFields, Fields countField, Include include )
324    {
325    this( null, pipe, groupingFields, countField, include );
326    }
327
328  /**
329   * Constructor CountBy creates a new CountBy instance.
330   *
331   * @param pipe           of type Pipe
332   * @param groupingFields of type Fields
333   * @param countField     fo type Fields
334   * @param include        of type Include
335   * @param threshold      of type int
336   */
337  @ConstructorProperties({"pipe", "groupingFields", "countField", "include", "threshold"})
338  public CountBy( Pipe pipe, Fields groupingFields, Fields countField, Include include, int threshold )
339    {
340    this( null, pipe, groupingFields, countField, include, threshold );
341    }
342
343  /**
344   * Constructor CountBy creates a new CountBy instance.
345   *
346   * @param name           of type String
347   * @param pipe           of type Pipe
348   * @param groupingFields of type Fields
349   * @param countField     of type Fields
350   * @param include        of type Include
351   */
352  @ConstructorProperties({"name", "pipe", "groupingFields", "countField", "include"})
353  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields countField, Include include )
354    {
355    this( name, pipe, groupingFields, countField, include, USE_DEFAULT_THRESHOLD );
356    }
357
358  /**
359   * Constructor CountBy creates a new CountBy instance.
360   *
361   * @param name           of type String
362   * @param pipe           of type Pipe
363   * @param groupingFields of type Fields
364   * @param countField     of type Fields
365   * @param include        of type Include
366   * @param threshold      of type int
367   */
368  @ConstructorProperties({"name", "pipe", "groupingFields", "countField", "include", "threshold"})
369  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields countField, Include include, int threshold )
370    {
371    this( name, Pipe.pipes( pipe ), groupingFields, countField, include, threshold );
372    }
373
374  /**
375   * Constructor CountBy creates a new CountBy instance.
376   *
377   * @param pipes          of type Pipe[]
378   * @param groupingFields of type Fields
379   * @param countField     of type Fields
380   * @param include        of type Include
381   */
382  @ConstructorProperties({"pipes", "groupingFields", "countField", "include"})
383  public CountBy( Pipe[] pipes, Fields groupingFields, Fields countField, Include include )
384    {
385    this( null, pipes, groupingFields, countField, include, USE_DEFAULT_THRESHOLD );
386    }
387
388  /**
389   * Constructor CountBy creates a new CountBy instance.
390   *
391   * @param pipes          of type Pipe[]
392   * @param groupingFields of type Fields
393   * @param countField     of type Fields
394   * @param include        of type Include
395   * @param threshold      of type int
396   */
397  @ConstructorProperties({"pipes", "groupingFields", "countField", "include", "threshold"})
398  public CountBy( Pipe[] pipes, Fields groupingFields, Fields countField, Include include, int threshold )
399    {
400    this( null, pipes, groupingFields, countField, include, threshold );
401    }
402
403  /**
404   * Constructor CountBy creates a new CountBy instance.
405   *
406   * @param name           of type String
407   * @param pipes          of type Pipe[]
408   * @param groupingFields of type Fields
409   * @param countField     of type Fields
410   * @param include        of type Include
411   */
412  @ConstructorProperties({"name", "pipes", "groupingFields", "countField", "include"})
413  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields countField, Include include )
414    {
415    this( name, pipes, groupingFields, countField, include, USE_DEFAULT_THRESHOLD );
416    }
417
418  /**
419   * Constructor CountBy creates a new CountBy instance.
420   *
421   * @param name           of type String
422   * @param pipes          of type Pipe[]
423   * @param groupingFields of type Fields
424   * @param countField     of type Fields
425   * @param include        of type Include
426   * @param threshold      of type int
427   */
428  @ConstructorProperties({"name", "pipes", "groupingFields", "countField", "include", "threshold"})
429  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields countField, Include include, int threshold )
430    {
431    super( name, pipes, groupingFields, groupingFields, new CountPartials( countField.applyTypes( Long.TYPE ), include ), new Sum( countField.applyTypes( Long.TYPE ) ), threshold );
432    }
433
434////////////
435
436  /**
437   * Constructor CountBy creates a new CountBy instance.
438   *
439   * @param pipe           of type Pipe
440   * @param groupingFields of type Fields
441   * @param valueFields    of type Fields
442   * @param countField     of type Fields
443   */
444  @ConstructorProperties({"pipe", "groupingFields", "valueFields", "countField"})
445  public CountBy( Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField )
446    {
447    this( null, pipe, groupingFields, valueFields, countField, Include.ALL );
448    }
449
450  /**
451   * Constructor CountBy creates a new CountBy instance.
452   *
453   * @param pipe           of type Pipe
454   * @param groupingFields of type Fields
455   * @param valueFields    of type Fields
456   * @param countField     fo type Fields
457   * @param threshold      of type int
458   */
459  @ConstructorProperties({"pipe", "groupingFields", "valueFields", "countField", "threshold"})
460  public CountBy( Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField, int threshold )
461    {
462    this( null, pipe, groupingFields, valueFields, countField, threshold );
463    }
464
465  /**
466   * Constructor CountBy creates a new CountBy instance.
467   *
468   * @param name           of type String
469   * @param pipe           of type Pipe
470   * @param groupingFields of type Fields
471   * @param valueFields    of type Fields
472   * @param countField     of type Fields
473   */
474  @ConstructorProperties({"name", "pipe", "groupingFields", "valueFields", "countField"})
475  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField )
476    {
477    this( name, pipe, groupingFields, valueFields, countField, USE_DEFAULT_THRESHOLD );
478    }
479
480  /**
481   * Constructor CountBy creates a new CountBy instance.
482   *
483   * @param name           of type String
484   * @param pipe           of type Pipe
485   * @param groupingFields of type Fields
486   * @param valueFields    of type Fields
487   * @param countField     of type Fields
488   * @param threshold      of type int
489   */
490  @ConstructorProperties({"name", "pipe", "groupingFields", "valueFields", "countField", "threshold"})
491  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField, int threshold )
492    {
493    this( name, Pipe.pipes( pipe ), groupingFields, valueFields, countField, threshold );
494    }
495
496  /**
497   * Constructor CountBy creates a new CountBy instance.
498   *
499   * @param pipes          of type Pipe[]
500   * @param groupingFields of type Fields
501   * @param valueFields    of type Fields
502   * @param countField     of type Fields
503   */
504  @ConstructorProperties({"pipes", "groupingFields", "valueFields", "countField"})
505  public CountBy( Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField )
506    {
507    this( null, pipes, groupingFields, valueFields, countField, USE_DEFAULT_THRESHOLD );
508    }
509
510  /**
511   * Constructor CountBy creates a new CountBy instance.
512   *
513   * @param pipes          of type Pipe[]
514   * @param groupingFields of type Fields
515   * @param valueFields    of type Fields
516   * @param countField     of type Fields
517   * @param threshold      of type int
518   */
519  @ConstructorProperties({"pipes", "groupingFields", "valueFields", "countField", "threshold"})
520  public CountBy( Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField, int threshold )
521    {
522    this( null, pipes, groupingFields, valueFields, countField, threshold );
523    }
524
525  /**
526   * Constructor CountBy creates a new CountBy instance.
527   *
528   * @param name           of type String
529   * @param pipes          of type Pipe[]
530   * @param groupingFields of type Fields
531   * @param valueFields    of type Fields
532   * @param countField     of type Fields
533   */
534  @ConstructorProperties({"name", "pipes", "groupingFields", "valueFields", "countField"})
535  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField )
536    {
537    this( name, pipes, groupingFields, valueFields, countField, USE_DEFAULT_THRESHOLD );
538    }
539
540  /**
541   * Constructor CountBy creates a new CountBy instance.
542   *
543   * @param name           of type String
544   * @param pipes          of type Pipe[]
545   * @param groupingFields of type Fields
546   * @param valueFields    of type Fields
547   * @param countField     of type Fields
548   * @param threshold      of type int
549   */
550  @ConstructorProperties({"name", "pipes", "groupingFields", "valueFields", "countField", "threshold"})
551  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField, int threshold )
552    {
553    super( name, pipes, groupingFields, valueFields, new CountPartials( countField.applyTypes( Long.TYPE ) ), new Sum( countField.applyTypes( Long.TYPE ) ), threshold );
554    }
555
556////////////
557
558  /**
559   * Constructor CountBy creates a new CountBy instance.
560   *
561   * @param pipe           of type Pipe
562   * @param groupingFields of type Fields
563   * @param valueFields    of type Fields
564   * @param countField     of type Fields
565   * @param include        of type Include
566   */
567  @ConstructorProperties({"pipe", "groupingFields", "valueFields", "countField", "include"})
568  public CountBy( Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField, Include include )
569    {
570    this( null, pipe, groupingFields, valueFields, countField, include );
571    }
572
573  /**
574   * Constructor CountBy creates a new CountBy instance.
575   *
576   * @param pipe           of type Pipe
577   * @param groupingFields of type Fields
578   * @param valueFields    of type Fields
579   * @param countField     fo type Fields
580   * @param include        of type Include
581   * @param threshold      of type int
582   */
583  @ConstructorProperties({"pipe", "groupingFields", "valueFields", "countField", "include", "threshold"})
584  public CountBy( Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField, Include include, int threshold )
585    {
586    this( null, pipe, groupingFields, valueFields, countField, include, threshold );
587    }
588
589  /**
590   * Constructor CountBy creates a new CountBy instance.
591   *
592   * @param name           of type String
593   * @param pipe           of type Pipe
594   * @param valueFields    of type Fields
595   * @param groupingFields of type Fields
596   * @param countField     of type Fields
597   * @param include        of type Include
598   */
599  @ConstructorProperties({"name", "pipe", "groupingFields", "valueFields", "countField", "include"})
600  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField, Include include )
601    {
602    this( name, pipe, groupingFields, valueFields, countField, include, USE_DEFAULT_THRESHOLD );
603    }
604
605  /**
606   * Constructor CountBy creates a new CountBy instance.
607   *
608   * @param name           of type String
609   * @param pipe           of type Pipe
610   * @param groupingFields of type Fields
611   * @param valueFields    of type Fields
612   * @param countField     of type Fields
613   * @param include        of type Include
614   * @param threshold      of type int
615   */
616  @ConstructorProperties({"name", "pipe", "groupingFields", "valueFields", "countField", "include", "threshold"})
617  public CountBy( String name, Pipe pipe, Fields groupingFields, Fields valueFields, Fields countField, Include include, int threshold )
618    {
619    this( name, Pipe.pipes( pipe ), groupingFields, valueFields, countField, include, threshold );
620    }
621
622  /**
623   * Constructor CountBy creates a new CountBy instance.
624   *
625   * @param pipes          of type Pipe[]
626   * @param groupingFields of type Fields
627   * @param valueFields    of type Fields
628   * @param countField     of type Fields
629   * @param include        of type Include
630   */
631  @ConstructorProperties({"pipes", "groupingFields", "valueFields", "countField", "include"})
632  public CountBy( Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField, Include include )
633    {
634    this( null, pipes, groupingFields, valueFields, countField, include, USE_DEFAULT_THRESHOLD );
635    }
636
637  /**
638   * Constructor CountBy creates a new CountBy instance.
639   *
640   * @param pipes          of type Pipe[]
641   * @param groupingFields of type Fields
642   * @param valueFields    of type Fields
643   * @param countField     of type Fields
644   * @param include        of type Include
645   * @param threshold      of type int
646   */
647  @ConstructorProperties({"pipes", "groupingFields", "valueFields", "countField", "include", "threshold"})
648  public CountBy( Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField, Include include, int threshold )
649    {
650    this( null, pipes, groupingFields, valueFields, countField, include, threshold );
651    }
652
653  /**
654   * Constructor CountBy creates a new CountBy instance.
655   *
656   * @param name           of type String
657   * @param pipes          of type Pipe[]
658   * @param groupingFields of type Fields
659   * @param valueFields    of type Fields
660   * @param countField     of type Fields
661   * @param include        of type Include
662   */
663  @ConstructorProperties({"name", "pipes", "groupingFields", "valueFields", "countField", "include"})
664  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField, Include include )
665    {
666    this( name, pipes, groupingFields, valueFields, countField, include, USE_DEFAULT_THRESHOLD );
667    }
668
669  /**
670   * Constructor CountBy creates a new CountBy instance.
671   *
672   * @param name           of type String
673   * @param pipes          of type Pipe[]
674   * @param groupingFields of type Fields
675   * @param valueFields    of type Fields
676   * @param countField     of type Fields
677   * @param include        of type Include
678   * @param threshold      of type int
679   */
680  @ConstructorProperties({"name", "pipes", "groupingFields", "valueFields", "countField", "include", "threshold"})
681  public CountBy( String name, Pipe[] pipes, Fields groupingFields, Fields valueFields, Fields countField, Include include, int threshold )
682    {
683    super( name, pipes, groupingFields, valueFields, new CountPartials( countField.applyTypes( Long.TYPE ), include ), new Sum( countField.applyTypes( Long.TYPE ) ), threshold );
684    }
685  }