@Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); out.writeByte(percolatorTypeId); out.writeVLong(requestedSize); out.writeVLong(count); out.writeVInt(matches.length); for (BytesRef match : matches) { out.writeBytesRef(match); } out.writeVLong(scores.length); for (float score : scores) { out.writeFloat(score); } out.writeVInt(hls.size()); for (Map<String, HighlightField> hl : hls) { out.writeVInt(hl.size()); for (Map.Entry<String, HighlightField> entry : hl.entrySet()) { out.writeString(entry.getKey()); entry.getValue().writeTo(out); } } out.writeOptionalStreamable(aggregations); if (pipelineAggregators == null) { out.writeBoolean(false); } else { out.writeBoolean(true); out.writeVInt(pipelineAggregators.size()); for (PipelineAggregator pipelineAggregator : pipelineAggregators) { out.writeBytesReference(pipelineAggregator.type().stream()); pipelineAggregator.writeTo(out); } } }
@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); }