Esempio n. 1
0
 protected final InternalAggregations buildEmptySubAggregations() {
   List<InternalAggregation> aggs = new ArrayList<>();
   for (Aggregator aggregator : subAggregators) {
     aggs.add(aggregator.buildEmptyAggregation());
   }
   return new InternalAggregations(aggs);
 }
Esempio n. 2
0
 /**
  * Returns whether any of the parent aggregators has {@link BucketAggregationMode#PER_BUCKET} as a
  * bucket aggregation mode.
  */
 public static boolean hasParentBucketAggregator(Aggregator parent) {
   if (parent == null) {
     return false;
   } else if (parent.bucketAggregationMode() == BucketAggregationMode.PER_BUCKET) {
     return true;
   } else {
     return hasParentBucketAggregator(parent.parent());
   }
 }
 /** Create all aggregators so that they can be consumed with multiple buckets. */
 public Aggregator[] createSubAggregators(Aggregator parent) throws IOException {
   Aggregator[] aggregators = new Aggregator[count()];
   for (int i = 0; i < factories.length; ++i) {
     // TODO: sometimes even sub aggregations always get called with bucket 0, eg. if
     // you have a terms agg under a top-level filter agg. We should have a way to
     // propagate the fact that only bucket 0 will be collected with single-bucket
     // aggs
     final boolean collectsFromSingleBucket = false;
     aggregators[i] = factories[i].create(parent.context(), parent, collectsFromSingleBucket);
   }
   return aggregators;
 }
Esempio n. 4
0
 @Override
 public Aggregator create(
     AggregationContext context, Aggregator parent, long expectedBucketsCount) {
   if (parent != null) {
     throw new AggregationExecutionException(
         "Aggregation ["
             + parent.name()
             + "] cannot have a global "
             + "sub-aggregation ["
             + name
             + "]. Global aggregations can only be defined as top level aggregations");
   }
   return new GlobalAggregator(name, factories, context);
 }
Esempio n. 5
0
 /**
  * Constructs a new Aggregator.
  *
  * @param name The name of the aggregation
  * @param bucketAggregationMode The nature of execution as a sub-aggregator (see {@link
  *     BucketAggregationMode})
  * @param factories The factories for all the sub-aggregators under this aggregator
  * @param estimatedBucketsCount When served as a sub-aggregator, indicate how many buckets the
  *     parent aggregator will generate.
  * @param context The aggregation context
  * @param parent The parent aggregator (may be {@code null} for top level aggregators)
  */
 protected Aggregator(
     String name,
     BucketAggregationMode bucketAggregationMode,
     AggregatorFactories factories,
     long estimatedBucketsCount,
     AggregationContext context,
     Aggregator parent) {
   this.name = name;
   this.parent = parent;
   this.estimatedBucketCount = estimatedBucketsCount;
   this.context = context;
   this.bigArrays = context.bigArrays();
   this.depth = parent == null ? 0 : 1 + parent.depth();
   this.bucketAggregationMode = bucketAggregationMode;
   assert factories != null
       : "sub-factories provided to BucketAggregator must not be null, use AggragatorFactories.EMPTY instead";
   this.factories = factories;
   this.subAggregators = factories.createSubAggregators(this, estimatedBucketsCount);
   collectableSugAggregators =
       BucketCollector.wrap(
           Iterables.filter(Arrays.asList(subAggregators), COLLECTABLE_AGGREGATOR));
   context.searchContext().addReleasable(this, Lifetime.PHASE);
 }
Esempio n. 6
0
 @Override
 public boolean apply(Aggregator aggregator) {
   return aggregator.shouldCollect();
 }
Esempio n. 7
0
 @Override
 protected boolean shouldDefer(Aggregator aggregator) {
   return collectMode == SubAggCollectionMode.BREADTH_FIRST
       && aggregator.needsScores() == false
       && !aggsUsedForSorting.contains(aggregator);
 }
  @Override
  public void execute(SearchContext context) {
    if (context.aggregations() == null) {
      context.queryResult().aggregations(null);
      return;
    }

    if (context.queryResult().aggregations() != null) {
      // no need to compute the aggs twice, they should be computed on a per context basis
      return;
    }

    Aggregator[] aggregators = context.aggregations().aggregators();
    List<Aggregator> globals = new ArrayList<>();
    for (int i = 0; i < aggregators.length; i++) {
      if (aggregators[i] instanceof GlobalAggregator) {
        globals.add(aggregators[i]);
      }
    }

    // optimize the global collector based execution
    if (!globals.isEmpty()) {
      BucketCollector globalsCollector = BucketCollector.wrap(globals);
      Query query = Queries.newMatchAllQuery();
      Query searchFilter = context.searchFilter(context.types());

      if (searchFilter != null) {
        BooleanQuery filtered =
            new BooleanQuery.Builder()
                .add(query, Occur.MUST)
                .add(searchFilter, Occur.FILTER)
                .build();
        query = filtered;
      }
      try {
        final Collector collector;
        if (context.getProfilers() == null) {
          collector = globalsCollector;
        } else {
          InternalProfileCollector profileCollector =
              new InternalProfileCollector(
                  globalsCollector,
                  CollectorResult.REASON_AGGREGATION_GLOBAL,
                  // TODO: report on sub collectors
                  Collections.emptyList());
          collector = profileCollector;
          // start a new profile with this collector
          context.getProfilers().addProfiler().setCollector(profileCollector);
        }
        globalsCollector.preCollection();
        context.searcher().search(query, collector);
      } catch (Exception e) {
        throw new QueryPhaseExecutionException(context, "Failed to execute global aggregators", e);
      } finally {
        context.clearReleasables(SearchContext.Lifetime.COLLECTION);
      }
    }

    List<InternalAggregation> aggregations = new ArrayList<>(aggregators.length);
    for (Aggregator aggregator : context.aggregations().aggregators()) {
      try {
        aggregator.postCollection();
        aggregations.add(aggregator.buildAggregation(0));
      } catch (IOException e) {
        throw new AggregationExecutionException(
            "Failed to build aggregation [" + aggregator.name() + "]", e);
      }
    }
    context.queryResult().aggregations(new InternalAggregations(aggregations));
    try {
      List<PipelineAggregator> pipelineAggregators =
          context.aggregations().factories().createPipelineAggregators();
      List<SiblingPipelineAggregator> siblingPipelineAggregators =
          new ArrayList<>(pipelineAggregators.size());
      for (PipelineAggregator pipelineAggregator : pipelineAggregators) {
        if (pipelineAggregator instanceof SiblingPipelineAggregator) {
          siblingPipelineAggregators.add((SiblingPipelineAggregator) pipelineAggregator);
        } else {
          throw new AggregationExecutionException(
              "Invalid pipeline aggregation named ["
                  + pipelineAggregator.name()
                  + "] of type ["
                  + pipelineAggregator.type().name()
                  + "]. Only sibling pipeline aggregations are allowed at the top level");
        }
      }
      context.queryResult().pipelineAggregators(siblingPipelineAggregators);
    } catch (IOException e) {
      throw new AggregationExecutionException("Failed to build top level pipeline aggregators", e);
    }

    // disable aggregations so that they don't run on next pages in case of scrolling
    context.aggregations(null);
    context.queryCollectors().remove(AggregationPhase.class);
  }
 @Override
 public final void close() {
   try (Releasable releasable = docCounts) {
     super.close();
   }
 }
  @Override
  protected Aggregator doCreateInternal(
      ValuesSource valuesSource,
      AggregationContext aggregationContext,
      Aggregator parent,
      boolean collectsFromSingleBucket,
      List<PipelineAggregator> pipelineAggregators,
      Map<String, Object> metaData)
      throws IOException {
    if (collectsFromSingleBucket == false) {
      return asMultiBucketAggregator(this, aggregationContext, parent);
    }

    numberOfAggregatorsCreated++;

    if (valuesSource instanceof ValuesSource.Bytes) {
      ExecutionMode execution = null;
      if (executionHint != null) {
        execution =
            ExecutionMode.fromString(
                executionHint, aggregationContext.searchContext().parseFieldMatcher());
      }
      if (!(valuesSource instanceof ValuesSource.Bytes.WithOrdinals)) {
        execution = ExecutionMode.MAP;
      }
      if (execution == null) {
        if (Aggregator.descendsFromBucketAggregator(parent)) {
          execution = ExecutionMode.GLOBAL_ORDINALS_HASH;
        } else {
          execution = ExecutionMode.GLOBAL_ORDINALS;
        }
      }
      assert execution != null;
      return execution.create(
          name,
          factories,
          valuesSource,
          bucketCountThresholds,
          includeExclude,
          aggregationContext,
          parent,
          this,
          pipelineAggregators,
          metaData);
    }

    if ((includeExclude != null) && (includeExclude.isRegexBased())) {
      throw new AggregationExecutionException(
          "Aggregation ["
              + name
              + "] cannot support regular expression style include/exclude "
              + "settings as they can only be applied to string fields. Use an array of numeric values for include/exclude clauses used to filter numeric fields");
    }

    if (valuesSource instanceof ValuesSource.Numeric) {

      if (((ValuesSource.Numeric) valuesSource).isFloatingPoint()) {
        throw new UnsupportedOperationException("No support for examining floating point numerics");
      }
      IncludeExclude.LongFilter longFilter = null;
      if (includeExclude != null) {
        longFilter = includeExclude.convertToLongFilter();
      }
      return new SignificantLongTermsAggregator(
          name,
          factories,
          (ValuesSource.Numeric) valuesSource,
          config.format(),
          bucketCountThresholds,
          aggregationContext,
          parent,
          this,
          longFilter,
          pipelineAggregators,
          metaData);
    }

    throw new AggregationExecutionException(
        "sigfnificant_terms aggregation cannot be applied to field ["
            + config.fieldContext().field()
            + "]. It can only be applied to numeric or string fields.");
  }