diff --git a/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java b/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java index ca9b8813aeb..6164e255057 100644 --- a/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java +++ b/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java @@ -33,7 +33,7 @@ import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.Scroll; import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.highlight.HighlightBuilder; import org.elasticsearch.search.rescore.RescoreBuilder; import org.elasticsearch.search.sort.SortBuilder; @@ -485,7 +485,7 @@ public class SearchRequestBuilder extends ActionRequestBuilder> cache; + + @Inject + public SimpleDocSetCache(Index index, @IndexSettings Settings indexSettings) { + super(index, indexSettings); + this.cache = ConcurrentCollections.newConcurrentMap(); + } + + @Override + public void onClose(SegmentReader owner) { + cache.remove(owner.getCoreCacheKey()); + } + + @Override + public void clear(String reason) { + cache.clear(); + } + + @Override + public void clear(IndexReader reader) { + cache.remove(reader.getCoreCacheKey()); + } + + @Override + public ContextDocIdSet obtain(AtomicReaderContext context) { + Queue docIdSets = cache.get(context.reader().getCoreCacheKey()); + if (docIdSets == null) { + if (context.reader() instanceof SegmentReader) { + ((SegmentReader) context.reader()).addCoreClosedListener(this); + } + cache.put(context.reader().getCoreCacheKey(), ConcurrentCollections.newQueue()); + return new ContextDocIdSet(context, new FixedBitSet(context.reader().maxDoc())); + } + FixedBitSet docIdSet = docIdSets.poll(); + if (docIdSet == null) { + docIdSet = new FixedBitSet(context.reader().maxDoc()); + } else { + docIdSet.clear(0, docIdSet.length()); + } + return new ContextDocIdSet(context, docIdSet); + } + + @Override + public void release(ContextDocIdSet docSet) { + Queue docIdSets = cache.get(docSet.context.reader().getCoreCacheKey()); + if (docIdSets != null) { + docIdSets.add((FixedBitSet) docSet.docSet); + } + } +} diff --git a/src/main/java/org/elasticsearch/index/search/nested/NestedChildrenCollector.java b/src/main/java/org/elasticsearch/index/search/nested/NestedChildrenCollector.java index a1701b66e98..70da008fbd2 100644 --- a/src/main/java/org/elasticsearch/index/search/nested/NestedChildrenCollector.java +++ b/src/main/java/org/elasticsearch/index/search/nested/NestedChildrenCollector.java @@ -20,47 +20,39 @@ package org.elasticsearch.index.search.nested; import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.Collector; import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.Filter; import org.apache.lucene.search.Scorer; import org.apache.lucene.util.Bits; import org.apache.lucene.util.FixedBitSet; import org.elasticsearch.common.lucene.docset.DocIdSets; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.FacetCollector; +import org.elasticsearch.common.lucene.search.XCollector; import java.io.IOException; /** * A collector that accepts parent docs, and calls back the collect on child docs of that parent. */ -public class NestedChildrenCollector extends FacetCollector { - - private final FacetCollector collector; +public class NestedChildrenCollector extends XCollector { + private final Collector collector; private final Filter parentFilter; - private final Filter childFilter; - private Bits childDocs; - private FixedBitSet parentDocs; - public NestedChildrenCollector(FacetCollector collector, Filter parentFilter, Filter childFilter) { + public NestedChildrenCollector(Collector collector, Filter parentFilter, Filter childFilter) { this.collector = collector; this.parentFilter = parentFilter; this.childFilter = childFilter; } @Override - public Facet facet() { - return collector.facet(); - } - - @Override - public void setFilter(Filter filter) { - // delegate the facet_filter to the children - collector.setFilter(filter); + public void postCollection() { + if (collector instanceof XCollector) { + ((XCollector) collector).postCollection(); + } } @Override diff --git a/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java b/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java index 5d5525efdfd..fe7cd5248d0 100644 --- a/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java +++ b/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java @@ -36,7 +36,7 @@ import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.highlight.HighlightBuilder; import org.elasticsearch.search.rescore.RescoreBuilder; import org.elasticsearch.search.sort.SortBuilder; @@ -99,14 +99,14 @@ public class SearchSourceBuilder implements ToXContent { private List scriptFields; private List partialFields; - private List facets; + private List facets; private BytesReference facetsBinary; private HighlightBuilder highlightBuilder; private SuggestBuilder suggestBuilder; - + private RescoreBuilder rescoreBuilder; private TObjectFloatHashMap indexBoost = null; @@ -341,7 +341,7 @@ public class SearchSourceBuilder implements ToXContent { /** * Add a facet to perform as part of the search. */ - public SearchSourceBuilder facet(AbstractFacetBuilder facet) { + public SearchSourceBuilder facet(FacetBuilder facet) { if (facets == null) { facets = Lists.newArrayList(); } @@ -412,7 +412,7 @@ public class SearchSourceBuilder implements ToXContent { } return suggestBuilder; } - + public RescoreBuilder rescore() { if (rescoreBuilder == null) { rescoreBuilder = new RescoreBuilder(); @@ -711,7 +711,7 @@ public class SearchSourceBuilder implements ToXContent { if (facets != null) { builder.field("facets"); builder.startObject(); - for (AbstractFacetBuilder facet : facets) { + for (FacetBuilder facet : facets) { facet.toXContent(builder, params); } builder.endObject(); @@ -732,9 +732,9 @@ public class SearchSourceBuilder implements ToXContent { if (suggestBuilder != null) { suggestBuilder.toXContent(builder, params); } - + if (rescoreBuilder != null) { - rescoreBuilder.toXContent(builder, params); + rescoreBuilder.toXContent(builder, params); } if (stats != null) { diff --git a/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java b/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java index 0f8ed1cdad3..55db09af5e5 100644 --- a/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java +++ b/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java @@ -309,7 +309,7 @@ public class SearchPhaseController extends AbstractComponent { namedFacets.clear(); for (QuerySearchResultProvider queryResultProvider : queryResults.values()) { for (Facet facet1 : queryResultProvider.queryResult().facets()) { - if (facet.name().equals(facet1.name())) { + if (facet.getName().equals(facet1.getName())) { namedFacets.add(facet1); } } diff --git a/src/main/java/org/elasticsearch/search/facet/AbstractFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/AbstractFacetCollector.java deleted file mode 100644 index 255c62bda59..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/AbstractFacetCollector.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to Elastic Search and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. Elastic Search licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet; - -import com.google.common.collect.ImmutableList; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Filter; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.util.Bits; -import org.elasticsearch.common.lucene.docset.DocIdSets; -import org.elasticsearch.common.lucene.search.AndFilter; - -import java.io.IOException; - -/** - * - */ -public abstract class AbstractFacetCollector extends FacetCollector { - - protected final String facetName; - - protected Filter filter; - - private Bits bits = null; - - public AbstractFacetCollector(String facetName) { - this.facetName = facetName; - } - - public Filter getFilter() { - return this.filter; - } - - public Filter getAndClearFilter() { - Filter filter = this.filter; - this.filter = null; - return filter; - } - - @Override - public void setFilter(Filter filter) { - if (this.filter == null) { - this.filter = filter; - } else { - this.filter = new AndFilter(ImmutableList.of(filter, this.filter)); - } - } - - @Override - public void setScorer(Scorer scorer) throws IOException { - // usually, there is nothing to do here - } - - @Override - public boolean acceptsDocsOutOfOrder() { - return true; // when working on FieldData, docs can be out of order - } - - @Override - public void setNextReader(AtomicReaderContext context) throws IOException { - if (filter != null) { - bits = DocIdSets.toSafeBits(context.reader(), filter.getDocIdSet(context, context.reader().getLiveDocs())); - } - doSetNextReader(context); - } - - protected abstract void doSetNextReader(AtomicReaderContext context) throws IOException; - - @Override - public void collect(int doc) throws IOException { - if (bits == null) { - doCollect(doc); - } else if (bits.get(doc)) { - doCollect(doc); - } - } - - protected abstract void doCollect(int doc) throws IOException; -} diff --git a/src/main/java/org/elasticsearch/search/facet/Facet.java b/src/main/java/org/elasticsearch/search/facet/Facet.java index a1fa2d79282..431f3c320d1 100644 --- a/src/main/java/org/elasticsearch/search/facet/Facet.java +++ b/src/main/java/org/elasticsearch/search/facet/Facet.java @@ -24,21 +24,11 @@ package org.elasticsearch.search.facet; */ public interface Facet { - /** - * The "logical" name of the search facet. - */ - String name(); - /** * The "logical" name of the search facet. */ String getName(); - /** - * The type of the facet. - */ - String type(); - /** * The type of the facet. */ diff --git a/src/main/java/org/elasticsearch/search/facet/FacetBinaryParseElement.java b/src/main/java/org/elasticsearch/search/facet/FacetBinaryParseElement.java index d374b157a78..1aadae12fd0 100644 --- a/src/main/java/org/elasticsearch/search/facet/FacetBinaryParseElement.java +++ b/src/main/java/org/elasticsearch/search/facet/FacetBinaryParseElement.java @@ -30,8 +30,8 @@ import org.elasticsearch.search.internal.SearchContext; public class FacetBinaryParseElement extends FacetParseElement { @Inject - public FacetBinaryParseElement(FacetProcessors facetProcessors) { - super(facetProcessors); + public FacetBinaryParseElement(FacetParsers facetParsers) { + super(facetParsers); } @Override diff --git a/src/main/java/org/elasticsearch/search/facet/AbstractFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/FacetBuilder.java similarity index 71% rename from src/main/java/org/elasticsearch/search/facet/AbstractFacetBuilder.java rename to src/main/java/org/elasticsearch/search/facet/FacetBuilder.java index b9fdad4c3a5..45b43bb9304 100644 --- a/src/main/java/org/elasticsearch/search/facet/AbstractFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/FacetBuilder.java @@ -28,21 +28,36 @@ import java.io.IOException; /** * */ -public abstract class AbstractFacetBuilder implements ToXContent { +public abstract class FacetBuilder implements ToXContent { + + public static enum Mode { + COLLECTOR() { + @Override + public String toString() { + return "collector"; + } + }, + POST() { + @Override + public String toString() { + return "post"; + } + }; + + public abstract String toString(); + } protected final String name; - protected FilterBuilder facetFilter; - protected Boolean global; - protected String nested; + protected Mode mode; - protected AbstractFacetBuilder(String name) { + protected FacetBuilder(String name) { this.name = name; } - public AbstractFacetBuilder facetFilter(FilterBuilder filter) { + public FacetBuilder facetFilter(FilterBuilder filter) { this.facetFilter = filter; return this; } @@ -51,7 +66,7 @@ public abstract class AbstractFacetBuilder implements ToXContent { * Sets the nested path the facet will execute on. A match (root object) will then cause all the * nested objects matching the path to be computed into the facet. */ - public AbstractFacetBuilder nested(String nested) { + public FacetBuilder nested(String nested) { this.nested = nested; return this; } @@ -59,23 +74,29 @@ public abstract class AbstractFacetBuilder implements ToXContent { /** * Marks the facet to run in a global scope, not bounded by any query. */ - public AbstractFacetBuilder global(boolean global) { + public FacetBuilder global(boolean global) { this.global = global; return this; } + public FacetBuilder mode(Mode mode) { + this.mode = mode; + return this; + } + protected void addFilterFacetAndGlobal(XContentBuilder builder, Params params) throws IOException { if (facetFilter != null) { builder.field("facet_filter"); facetFilter.toXContent(builder, params); } - if (nested != null) { builder.field("nested", nested); } - if (global != null) { builder.field("global", global); } + if (mode != null) { + builder.field("mode", mode.toString()); + } } } diff --git a/src/main/java/org/elasticsearch/search/facet/FacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/FacetExecutor.java new file mode 100644 index 00000000000..74152e9e5b4 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/FacetExecutor.java @@ -0,0 +1,123 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet; + +import org.apache.lucene.search.DocIdSet; +import org.apache.lucene.search.Filter; +import org.apache.lucene.search.Scorer; +import org.elasticsearch.common.lucene.docset.AndDocIdSet; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; +import org.elasticsearch.common.lucene.search.XCollector; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * A facet processor ends up actually executing the relevant facet for a specific + * search request. + *

+ * The facet executor requires at least one of the {@link #collector()} or {@link #post()} methods to be + * implemented. + */ +public abstract class FacetExecutor { + + /** + * A post class extends this class to implement post hits processing. + */ + public static abstract class Post { + + public abstract void executePost(List docSets) throws IOException; + + public static class Filtered extends Post { + + private final Post post; + private final Filter filter; + + public Filtered(Post post, Filter filter) { + this.post = post; + this.filter = filter; + } + + @Override + public void executePost(List docSets) throws IOException { + List filteredEntries = new ArrayList(docSets.size()); + for (int i = 0; i < docSets.size(); i++) { + ContextDocIdSet entry = docSets.get(i); + DocIdSet filteredSet = filter.getDocIdSet(entry.context, null); + filteredEntries.add(new ContextDocIdSet( + entry.context, + // TODO: can we be smart here, maybe AndDocIdSet is not always fastest? + new AndDocIdSet(new DocIdSet[]{entry.docSet, filteredSet}) + )); + } + post.executePost(filteredEntries); + } + } + } + + /** + * Simple extension to {@link XCollector} that implements methods that are typically + * not needed when doing collector based faceting. + */ + public static abstract class Collector extends XCollector { + + @Override + public void setScorer(Scorer scorer) throws IOException { + } + + @Override + public boolean acceptsDocsOutOfOrder() { + return true; + } + + @Override + public abstract void postCollection(); + } + + /** + * The mode of the execution. + */ + public static enum Mode { + /** + * Collector mode, maps to {@link #collector()}. + */ + COLLECTOR, + /** + * Post mode, maps to {@link #post()}. + */ + POST + } + + /** + * Builds the facet. + */ + public abstract InternalFacet buildFacet(String facetName); + + /** + * A collector based facet implementation, collection the facet as hits match. + */ + public abstract Collector collector(); + + /** + * A post based facet that executes the facet using the aggregated docs relevant. + */ + public abstract Post post(); +} diff --git a/src/main/java/org/elasticsearch/search/facet/FacetModule.java b/src/main/java/org/elasticsearch/search/facet/FacetModule.java index 24c444f2e74..e35329202bf 100644 --- a/src/main/java/org/elasticsearch/search/facet/FacetModule.java +++ b/src/main/java/org/elasticsearch/search/facet/FacetModule.java @@ -22,15 +22,15 @@ package org.elasticsearch.search.facet; import com.google.common.collect.Lists; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.multibindings.Multibinder; -import org.elasticsearch.search.facet.datehistogram.DateHistogramFacetProcessor; -import org.elasticsearch.search.facet.filter.FilterFacetProcessor; -import org.elasticsearch.search.facet.geodistance.GeoDistanceFacetProcessor; -import org.elasticsearch.search.facet.histogram.HistogramFacetProcessor; -import org.elasticsearch.search.facet.query.QueryFacetProcessor; -import org.elasticsearch.search.facet.range.RangeFacetProcessor; -import org.elasticsearch.search.facet.statistical.StatisticalFacetProcessor; -import org.elasticsearch.search.facet.terms.TermsFacetProcessor; -import org.elasticsearch.search.facet.termsstats.TermsStatsFacetProcessor; +import org.elasticsearch.search.facet.datehistogram.DateHistogramFacetParser; +import org.elasticsearch.search.facet.filter.FilterFacetParser; +import org.elasticsearch.search.facet.geodistance.GeoDistanceFacetParser; +import org.elasticsearch.search.facet.histogram.HistogramFacetParser; +import org.elasticsearch.search.facet.query.QueryFacetParser; +import org.elasticsearch.search.facet.range.RangeFacetParser; +import org.elasticsearch.search.facet.statistical.StatisticalFacetParser; +import org.elasticsearch.search.facet.terms.TermsFacetParser; +import org.elasticsearch.search.facet.termsstats.TermsStatsFacetParser; import java.util.List; @@ -39,31 +39,31 @@ import java.util.List; */ public class FacetModule extends AbstractModule { - private List> processors = Lists.newArrayList(); + private List> processors = Lists.newArrayList(); public FacetModule() { - processors.add(FilterFacetProcessor.class); - processors.add(QueryFacetProcessor.class); - processors.add(GeoDistanceFacetProcessor.class); - processors.add(HistogramFacetProcessor.class); - processors.add(DateHistogramFacetProcessor.class); - processors.add(RangeFacetProcessor.class); - processors.add(StatisticalFacetProcessor.class); - processors.add(TermsFacetProcessor.class); - processors.add(TermsStatsFacetProcessor.class); + processors.add(FilterFacetParser.class); + processors.add(QueryFacetParser.class); + processors.add(GeoDistanceFacetParser.class); + processors.add(HistogramFacetParser.class); + processors.add(DateHistogramFacetParser.class); + processors.add(RangeFacetParser.class); + processors.add(StatisticalFacetParser.class); + processors.add(TermsFacetParser.class); + processors.add(TermsStatsFacetParser.class); } - public void addFacetProcessor(Class facetProcessor) { + public void addFacetProcessor(Class facetProcessor) { processors.add(facetProcessor); } @Override protected void configure() { - Multibinder multibinder = Multibinder.newSetBinder(binder(), FacetProcessor.class); - for (Class processor : processors) { + Multibinder multibinder = Multibinder.newSetBinder(binder(), FacetParser.class); + for (Class processor : processors) { multibinder.addBinding().to(processor); } - bind(FacetProcessors.class).asEagerSingleton(); + bind(FacetParsers.class).asEagerSingleton(); bind(FacetParseElement.class).asEagerSingleton(); bind(FacetPhase.class).asEagerSingleton(); } diff --git a/src/main/java/org/elasticsearch/search/facet/FacetParseElement.java b/src/main/java/org/elasticsearch/search/facet/FacetParseElement.java index 65ac841cb7f..ef7b4ecc400 100644 --- a/src/main/java/org/elasticsearch/search/facet/FacetParseElement.java +++ b/src/main/java/org/elasticsearch/search/facet/FacetParseElement.java @@ -20,14 +20,12 @@ package org.elasticsearch.search.facet; import org.apache.lucene.search.Filter; +import org.elasticsearch.ElasticSearchIllegalArgumentException; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.object.ObjectMapper; -import org.elasticsearch.index.search.nested.NestedChildrenCollector; -import org.elasticsearch.index.search.nested.NonNestedDocsFilter; import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.SearchParseException; +import org.elasticsearch.search.facet.nested.NestedFacetExecutor; import org.elasticsearch.search.internal.SearchContext; import java.util.ArrayList; @@ -52,52 +50,66 @@ import java.util.List; */ public class FacetParseElement implements SearchParseElement { - private final FacetProcessors facetProcessors; + private final FacetParsers facetParsers; @Inject - public FacetParseElement(FacetProcessors facetProcessors) { - this.facetProcessors = facetProcessors; + public FacetParseElement(FacetParsers facetParsers) { + this.facetParsers = facetParsers; } @Override public void parse(XContentParser parser, SearchContext context) throws Exception { XContentParser.Token token; - List queryCollectors = null; - List globalCollectors = null; + List entries = new ArrayList(); - String topLevelFieldName = null; + String facetName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { - topLevelFieldName = parser.currentName(); + facetName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { - FacetCollector facet = null; + FacetExecutor facetExecutor = null; boolean global = false; - String facetFieldName = null; + FacetExecutor.Mode defaultMainMode = null; + FacetExecutor.Mode defaultGlobalMode = null; + FacetExecutor.Mode mode = null; Filter filter = null; - boolean cacheFilter = true; + boolean cacheFilter = false; String nestedPath = null; + + String fieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { - facetFieldName = parser.currentName(); + fieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { - if ("facet_filter".equals(facetFieldName) || "facetFilter".equals(facetFieldName)) { + if ("facet_filter".equals(fieldName) || "facetFilter".equals(fieldName)) { filter = context.queryParserService().parseInnerFilter(parser); } else { - FacetProcessor facetProcessor = facetProcessors.processor(facetFieldName); - if (facetProcessor == null) { - throw new SearchParseException(context, "No facet type found for [" + facetFieldName + "]"); + FacetParser facetParser = facetParsers.processor(fieldName); + if (facetParser == null) { + throw new SearchParseException(context, "No facet type found for [" + fieldName + "]"); } - facet = facetProcessor.parse(topLevelFieldName, parser, context); + facetExecutor = facetParser.parse(facetName, parser, context); + defaultMainMode = facetParser.defaultMainMode(); + defaultGlobalMode = facetParser.defaultGlobalMode(); } } else if (token.isValue()) { - if ("global".equals(facetFieldName)) { + if ("global".equals(fieldName)) { global = parser.booleanValue(); - } else if ("scope".equals(facetFieldName) || "_scope".equals(facetFieldName)) { + } else if ("mode".equals(fieldName)) { + String modeAsText = parser.text(); + if ("collector".equals(modeAsText)) { + mode = FacetExecutor.Mode.COLLECTOR; + } else if ("post".equals(modeAsText)) { + mode = FacetExecutor.Mode.POST; + } else { + throw new ElasticSearchIllegalArgumentException("failed to parse facet mode [" + modeAsText + "]"); + } + } else if ("scope".equals(fieldName) || "_scope".equals(fieldName)) { throw new SearchParseException(context, "the [scope] support in facets have been removed"); - } else if ("cache_filter".equals(facetFieldName) || "cacheFilter".equals(facetFieldName)) { + } else if ("cache_filter".equals(fieldName) || "cacheFilter".equals(fieldName)) { cacheFilter = parser.booleanValue(); - } else if ("nested".equals(facetFieldName)) { + } else if ("nested".equals(fieldName)) { nestedPath = parser.text(); } } @@ -106,44 +118,23 @@ public class FacetParseElement implements SearchParseElement { if (cacheFilter) { filter = context.filterCache().cache(filter); } - facet.setFilter(filter); + } + + if (facetExecutor == null) { + throw new SearchParseException(context, "no facet type found for facet named [" + facetName + "]"); } if (nestedPath != null) { - // its a nested facet, wrap the collector with a facet one... - MapperService.SmartNameObjectMapper mapper = context.smartNameObjectMapper(nestedPath); - if (mapper == null) { - throw new SearchParseException(context, "facet nested path [" + nestedPath + "] not found"); - } - ObjectMapper objectMapper = mapper.mapper(); - if (objectMapper == null) { - throw new SearchParseException(context, "facet nested path [" + nestedPath + "] not found"); - } - if (!objectMapper.nested().isNested()) { - throw new SearchParseException(context, "facet nested path [" + nestedPath + "] is not nested"); - } - facet = new NestedChildrenCollector(facet, context.filterCache().cache(NonNestedDocsFilter.INSTANCE), context.filterCache().cache(objectMapper.nestedTypeFilter())); + facetExecutor = new NestedFacetExecutor(facetExecutor, context, nestedPath); } - if (facet == null) { - throw new SearchParseException(context, "no facet type found for facet named [" + topLevelFieldName + "]"); + if (mode == null) { + mode = global ? defaultGlobalMode : defaultMainMode; } - - if (global) { - if (globalCollectors == null) { - globalCollectors = new ArrayList(); - } - globalCollectors.add(facet); - } else { - if (queryCollectors == null) { - queryCollectors = new ArrayList(); - } - queryCollectors.add(facet); - } - + entries.add(new SearchContextFacets.Entry(facetName, mode, facetExecutor, global, filter)); } } - context.facets(new SearchContextFacets(queryCollectors, globalCollectors)); + context.facets(new SearchContextFacets(entries)); } } diff --git a/src/main/java/org/elasticsearch/search/facet/FacetParser.java b/src/main/java/org/elasticsearch/search/facet/FacetParser.java new file mode 100644 index 00000000000..8688041faa5 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/FacetParser.java @@ -0,0 +1,53 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet; + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.search.internal.SearchContext; + +import java.io.IOException; + +/** + * A facet parser parses the relevant matching "type" of facet into a {@link FacetExecutor}. + *

+ * The parser also suggest the default {@link FacetExecutor.Mode} both for global and main executions. + */ +public interface FacetParser { + + /** + * The type of the facet, for example, terms. + */ + String[] types(); + + /** + * The default mode to use when executed as a "main" (query level) facet. + */ + FacetExecutor.Mode defaultMainMode(); + + /** + * The default mode to use when executed as a "global" (all docs) facet. + */ + FacetExecutor.Mode defaultGlobalMode(); + + /** + * Parses the facet into a {@link FacetExecutor}. + */ + FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException; +} diff --git a/src/main/java/org/elasticsearch/search/facet/FacetProcessors.java b/src/main/java/org/elasticsearch/search/facet/FacetParsers.java similarity index 78% rename from src/main/java/org/elasticsearch/search/facet/FacetProcessors.java rename to src/main/java/org/elasticsearch/search/facet/FacetParsers.java index 4d369324d98..2bc43d45537 100644 --- a/src/main/java/org/elasticsearch/search/facet/FacetProcessors.java +++ b/src/main/java/org/elasticsearch/search/facet/FacetParsers.java @@ -28,14 +28,14 @@ import java.util.Set; /** * */ -public class FacetProcessors { +public class FacetParsers { - private final ImmutableMap processors; + private final ImmutableMap processors; @Inject - public FacetProcessors(Set processors) { - MapBuilder builder = MapBuilder.newMapBuilder(); - for (FacetProcessor processor : processors) { + public FacetParsers(Set processors) { + MapBuilder builder = MapBuilder.newMapBuilder(); + for (FacetParser processor : processors) { for (String type : processor.types()) { builder.put(type, processor); } @@ -43,7 +43,7 @@ public class FacetProcessors { this.processors = builder.immutableMap(); } - public FacetProcessor processor(String type) { + public FacetParser processor(String type) { return processors.get(type); } } diff --git a/src/main/java/org/elasticsearch/search/facet/FacetPhase.java b/src/main/java/org/elasticsearch/search/facet/FacetPhase.java index 725c5fb656e..200f9aebd17 100644 --- a/src/main/java/org/elasticsearch/search/facet/FacetPhase.java +++ b/src/main/java/org/elasticsearch/search/facet/FacetPhase.java @@ -20,23 +20,20 @@ package org.elasticsearch.search.facet; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.Filter; -import org.apache.lucene.search.MultiCollector; -import org.apache.lucene.search.Query; +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.*; import org.elasticsearch.ElasticSearchException; +import org.elasticsearch.ElasticSearchIllegalStateException; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.lucene.search.Queries; -import org.elasticsearch.common.lucene.search.XConstantScoreQuery; -import org.elasticsearch.common.lucene.search.XFilteredQuery; +import org.elasticsearch.common.lucene.docset.AllDocIdSet; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; +import org.elasticsearch.common.lucene.search.*; import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.SearchPhase; import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.query.QueryPhaseExecutionException; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -63,9 +60,22 @@ public class FacetPhase implements SearchPhase { @Override public void preProcess(SearchContext context) { - if (context.facets() != null && context.facets().queryCollectors() != null) { - for (FacetCollector collector : context.facets().queryCollectors()) { - context.searcher().addMainQueryCollector(collector); + if (context.facets() != null && context.facets().hasQuery()) { + for (SearchContextFacets.Entry entry : context.facets().entries()) { + if (entry.isGlobal()) { + continue; + } + if (entry.getMode() == FacetExecutor.Mode.COLLECTOR) { + Collector collector = entry.getFacetExecutor().collector(); + if (entry.getFilter() != null) { + collector = new FilteredCollector(collector, entry.getFilter()); + } + context.searcher().addMainQueryCollector(collector); + } else if (entry.getMode() == FacetExecutor.Mode.POST) { + context.searcher().enableMainDocIdSetCollector(); + } else { + throw new ElasticSearchIllegalStateException("what mode?"); + } } } } @@ -75,42 +85,69 @@ public class FacetPhase implements SearchPhase { if (context.facets() == null) { return; } + if (context.queryResult().facets() != null) { // no need to compute the facets twice, they should be computed on a per context basis return; } - // optimize global facet execution, based on filters (don't iterate over all docs), and check - // if we have special facets that can be optimized for all execution, do it - List collectors = context.facets().globalCollectors(); - - if (collectors != null && !collectors.isEmpty()) { - Map> filtersByCollector = Maps.newHashMap(); - for (Collector collector : collectors) { - if (collector instanceof OptimizeGlobalFacetCollector) { - try { - ((OptimizeGlobalFacetCollector) collector).optimizedGlobalExecution(context); - } catch (IOException e) { - throw new QueryPhaseExecutionException(context, "Failed to execute global facets", e); + Map> filtersByCollector = null; + List globalDocSets = null; + for (SearchContextFacets.Entry entry : context.facets().entries()) { + if (!entry.isGlobal()) { + if (entry.getMode() == FacetExecutor.Mode.POST) { + FacetExecutor.Post post = entry.getFacetExecutor().post(); + if (entry.getFilter() != null) { + post = new FacetExecutor.Post.Filtered(post, entry.getFilter()); } - } else { - Filter filter = Queries.MATCH_ALL_FILTER; - if (collector instanceof AbstractFacetCollector) { - AbstractFacetCollector facetCollector = (AbstractFacetCollector) collector; - if (facetCollector.getFilter() != null) { - // we can clear the filter, since we are anyhow going to iterate over it - // so no need to double check it... - filter = facetCollector.getAndClearFilter(); + try { + post.executePost(context.searcher().mainDocIdSetCollector().docSets()); + } catch (Exception e) { + throw new QueryPhaseExecutionException(context, "failed to execute facet [" + entry.getFacetName() + "]", e); + } + } + } else { + if (entry.getMode() == FacetExecutor.Mode.POST) { + if (globalDocSets == null) { + // build global post entries, map a reader context to a live docs docIdSet + List leaves = context.searcher().getIndexReader().leaves(); + globalDocSets = new ArrayList(leaves.size()); + for (AtomicReaderContext leaf : leaves) { + globalDocSets.add(new ContextDocIdSet( + leaf, + BitsFilteredDocIdSet.wrap(new AllDocIdSet(leaf.reader().maxDoc()), leaf.reader().getLiveDocs())) // need to only include live docs + ); } } + try { + FacetExecutor.Post post = entry.getFacetExecutor().post(); + if (entry.getFilter() != null) { + post = new FacetExecutor.Post.Filtered(post, entry.getFilter()); + } + post.executePost(globalDocSets); + } catch (Exception e) { + throw new QueryPhaseExecutionException(context, "Failed to execute facet [" + entry.getFacetName() + "]", e); + } + } else if (entry.getMode() == FacetExecutor.Mode.COLLECTOR) { + Filter filter = Queries.MATCH_ALL_FILTER; + if (entry.getFilter() != null) { + filter = entry.getFilter(); + } + if (filtersByCollector == null) { + filtersByCollector = Maps.newHashMap(); + } List list = filtersByCollector.get(filter); if (list == null) { list = new ArrayList(); filtersByCollector.put(filter, list); } - list.add(collector); + list.add(entry.getFacetExecutor().collector()); } } + } + + // optimize the global collector based execution + if (filtersByCollector != null) { // now, go and execute the filters->collector ones for (Map.Entry> entry : filtersByCollector.entrySet()) { Filter filter = entry.getKey(); @@ -121,24 +158,20 @@ public class FacetPhase implements SearchPhase { } try { context.searcher().search(query, MultiCollector.wrap(entry.getValue().toArray(new Collector[entry.getValue().size()]))); - } catch (IOException e) { + } catch (Exception e) { throw new QueryPhaseExecutionException(context, "Failed to execute global facets", e); } + for (Collector collector : entry.getValue()) { + if (collector instanceof XCollector) { + ((XCollector) collector).postCollection(); + } + } } } - SearchContextFacets contextFacets = context.facets(); - - List facets = Lists.newArrayListWithCapacity(2); - if (contextFacets.queryCollectors() != null) { - for (FacetCollector facetCollector : contextFacets.queryCollectors()) { - facets.add(facetCollector.facet()); - } - } - if (contextFacets.globalCollectors() != null) { - for (FacetCollector facetCollector : contextFacets.globalCollectors()) { - facets.add(facetCollector.facet()); - } + List facets = new ArrayList(context.facets().entries().size()); + for (SearchContextFacets.Entry entry : context.facets().entries()) { + facets.add(entry.getFacetExecutor().buildFacet(entry.getFacetName())); } context.queryResult().facets(new InternalFacets(facets)); } diff --git a/src/main/java/org/elasticsearch/search/facet/InternalFacet.java b/src/main/java/org/elasticsearch/search/facet/InternalFacet.java index 01b3c05d870..c12981a428b 100644 --- a/src/main/java/org/elasticsearch/search/facet/InternalFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/InternalFacet.java @@ -22,6 +22,7 @@ package org.elasticsearch.search.facet; import com.google.common.collect.ImmutableMap; import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Streamable; import org.elasticsearch.common.xcontent.ToXContent; @@ -31,11 +32,24 @@ import java.util.List; /** * */ -public interface InternalFacet extends Facet, Streamable, ToXContent { +public abstract class InternalFacet implements Facet, Streamable, ToXContent { - String streamType(); + private String facetName; - Facet reduce(List facets); + /** + * Here just for streams... + */ + protected InternalFacet() { + + } + + protected InternalFacet(String facetName) { + this.facetName = facetName; + } + + public abstract String streamType(); + + public abstract Facet reduce(List facets); public static interface Stream { Facet readFacet(String type, StreamInput in) throws IOException; @@ -57,4 +71,19 @@ public interface InternalFacet extends Facet, Streamable, ToXContent { return streams.get(type); } } + + @Override + public final String getName() { + return facetName; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + facetName = in.readString(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(facetName); + } } diff --git a/src/main/java/org/elasticsearch/search/facet/InternalFacets.java b/src/main/java/org/elasticsearch/search/facet/InternalFacets.java index 5ed3df57335..0be243e1a42 100644 --- a/src/main/java/org/elasticsearch/search/facet/InternalFacets.java +++ b/src/main/java/org/elasticsearch/search/facet/InternalFacets.java @@ -87,7 +87,7 @@ public class InternalFacets implements Facets, Streamable, ToXContent, Iterable< } Map facetsAsMap = newHashMap(); for (Facet facet : facets) { - facetsAsMap.put(facet.name(), facet); + facetsAsMap.put(facet.getName(), facet); } this.facetsAsMap = facetsAsMap; return facetsAsMap; diff --git a/src/main/java/org/elasticsearch/search/facet/SearchContextFacets.java b/src/main/java/org/elasticsearch/search/facet/SearchContextFacets.java index 848e2c4e963..5308a2e9780 100644 --- a/src/main/java/org/elasticsearch/search/facet/SearchContextFacets.java +++ b/src/main/java/org/elasticsearch/search/facet/SearchContextFacets.java @@ -19,6 +19,9 @@ package org.elasticsearch.search.facet; +import org.apache.lucene.search.Filter; +import org.elasticsearch.common.Nullable; + import java.util.List; /** @@ -26,19 +29,74 @@ import java.util.List; */ public class SearchContextFacets { - private final List queryCollectors; - private final List globalCollectors; + public static class Entry { + private final String facetName; + private final FacetExecutor.Mode mode; + private final FacetExecutor facetExecutor; + private final boolean global; + @Nullable + private final Filter filter; - public SearchContextFacets(List queryCollectors, List globalCollectors) { - this.queryCollectors = queryCollectors; - this.globalCollectors = globalCollectors; + public Entry(String facetName, FacetExecutor.Mode mode, FacetExecutor facetExecutor, boolean global, @Nullable Filter filter) { + this.facetName = facetName; + this.mode = mode; + this.facetExecutor = facetExecutor; + this.global = global; + this.filter = filter; + } + + public String getFacetName() { + return facetName; + } + + public FacetExecutor.Mode getMode() { + return mode; + } + + public FacetExecutor getFacetExecutor() { + return facetExecutor; + } + + public boolean isGlobal() { + return global; + } + + public Filter getFilter() { + return filter; + } } - public List queryCollectors() { - return queryCollectors; + private final List entries; + + private boolean hasQuery; + private boolean hasGlobal; + + public SearchContextFacets(List entries) { + this.entries = entries; + for (Entry entry : entries) { + if (entry.global) { + hasGlobal = true; + } else { + hasQuery = true; + } + } } - public List globalCollectors() { - return globalCollectors; + public List entries() { + return this.entries; + } + + /** + * Are there facets that need to be computed on the query hits? + */ + public boolean hasQuery() { + return hasQuery; + } + + /** + * Are there global facets that need to be computed on all the docs. + */ + public boolean hasGlobal() { + return hasGlobal; } } diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetCollector.java deleted file mode 100644 index 217bb795f3c..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetCollector.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.datehistogram; - -import gnu.trove.map.hash.TLongLongHashMap; -import org.apache.lucene.index.AtomicReaderContext; -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.common.joda.TimeZoneRounding; -import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.index.fielddata.LongValues; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; - -/** - * A date histogram facet collector that uses the same field as the key as well as the - * value. - */ -public class CountDateHistogramFacetCollector extends AbstractFacetCollector { - - private final IndexNumericFieldData indexFieldData; - - private final DateHistogramFacet.ComparatorType comparatorType; - - private LongValues values; - private final DateHistogramProc histoProc; - - public CountDateHistogramFacetCollector(String facetName, IndexNumericFieldData indexFieldData, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); - this.comparatorType = comparatorType; - this.indexFieldData = indexFieldData; - this.histoProc = new DateHistogramProc(tzRounding); - } - - @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, histoProc); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getLongValues(); - } - - @Override - public Facet facet() { - return new InternalCountDateHistogramFacet(facetName, comparatorType, histoProc.counts(), true); - } - - public static class DateHistogramProc implements LongValues.ValueInDocProc { - - private final TLongLongHashMap counts = CacheRecycler.popLongLongMap(); - - private final TimeZoneRounding tzRounding; - - public DateHistogramProc(TimeZoneRounding tzRounding) { - this.tzRounding = tzRounding; - } - - @Override - public void onMissing(int docId) { - } - - @Override - public void onValue(int docId, long value) { - counts.adjustOrPutValue(tzRounding.calc(value), 1, 1); - } - - public TLongLongHashMap counts() { - return counts; - } - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetExecutor.java new file mode 100644 index 00000000000..ddab6f6dac5 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetExecutor.java @@ -0,0 +1,134 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet.datehistogram; + +import gnu.trove.map.hash.TLongLongHashMap; +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.DocIdSetIterator; +import org.elasticsearch.common.CacheRecycler; +import org.elasticsearch.common.joda.TimeZoneRounding; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; +import org.elasticsearch.index.fielddata.IndexNumericFieldData; +import org.elasticsearch.index.fielddata.LongValues; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; + +import java.io.IOException; +import java.util.List; + +/** + * A date histogram facet collector that uses the same field as the key as well as the + * value. + */ +public class CountDateHistogramFacetExecutor extends FacetExecutor { + + private final TimeZoneRounding tzRounding; + private final IndexNumericFieldData indexFieldData; + final DateHistogramFacet.ComparatorType comparatorType; + + final TLongLongHashMap counts; + + public CountDateHistogramFacetExecutor(IndexNumericFieldData indexFieldData, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType) { + this.comparatorType = comparatorType; + this.indexFieldData = indexFieldData; + this.tzRounding = tzRounding; + + this.counts = CacheRecycler.popLongLongMap(); + } + + @Override + public Collector collector() { + return new Collector(); + } + + @Override + public Post post() { + return new Post(); + } + + @Override + public InternalFacet buildFacet(String facetName) { + return new InternalCountDateHistogramFacet(facetName, comparatorType, counts, true); + } + + class Post extends FacetExecutor.Post { + + @Override + public void executePost(List docSets) throws IOException { + DateHistogramProc histoProc = new DateHistogramProc(counts, tzRounding); + for (ContextDocIdSet docSet : docSets) { + LongValues values = indexFieldData.load(docSet.context).getLongValues(); + DocIdSetIterator it = docSet.docSet.iterator(); + int doc; + while ((doc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + values.forEachValueInDoc(doc, histoProc); + } + } + } + } + + class Collector extends FacetExecutor.Collector { + + private LongValues values; + private final DateHistogramProc histoProc; + + public Collector() { + this.histoProc = new DateHistogramProc(counts, tzRounding); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getLongValues(); + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } + } + + public static class DateHistogramProc implements LongValues.ValueInDocProc { + + private final TLongLongHashMap counts; + private final TimeZoneRounding tzRounding; + + public DateHistogramProc(TLongLongHashMap counts, TimeZoneRounding tzRounding) { + this.counts = counts; + this.tzRounding = tzRounding; + } + + @Override + public void onMissing(int docId) { + } + + @Override + public void onValue(int docId, long value) { + counts.adjustOrPutValue(tzRounding.calc(value), 1, 1); + } + + public TLongLongHashMap counts() { + return counts; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacet.java index 3f574d70171..91e36333b3f 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacet.java @@ -35,11 +35,6 @@ public interface DateHistogramFacet extends Facet, Iterable entries(); - /** * An ordered list of histogram facet entries. */ @@ -60,7 +55,7 @@ public interface DateHistogramFacet extends Facet, Iterable() { @@ -77,7 +72,7 @@ public interface DateHistogramFacet extends Facet, Iterable() { @@ -94,7 +89,7 @@ public interface DateHistogramFacet extends Facet, Iterable dateFieldParsers; @Inject - public DateHistogramFacetProcessor(Settings settings) { + public DateHistogramFacetParser(Settings settings) { super(settings); InternalDateHistogramFacet.registerStreams(); @@ -80,7 +80,17 @@ public class DateHistogramFacetProcessor extends AbstractComponent implements Fa } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { String keyField = null; String valueField = null; String valueScript = null; @@ -169,16 +179,16 @@ public class DateHistogramFacetProcessor extends AbstractComponent implements Fa if (valueScript != null) { SearchScript script = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); - return new ValueScriptDateHistogramFacetCollector(facetName, keyIndexFieldData, script, tzRounding, comparatorType, context); + return new ValueScriptDateHistogramFacetExecutor(keyIndexFieldData, script, tzRounding, comparatorType); } else if (valueField != null) { FieldMapper valueMapper = context.smartNameFieldMapper(valueField); if (valueMapper == null) { throw new FacetPhaseExecutionException(facetName, "(value) field [" + valueField + "] not found"); } IndexNumericFieldData valueIndexFieldData = context.fieldData().getForField(valueMapper); - return new ValueDateHistogramFacetCollector(facetName, keyIndexFieldData, valueIndexFieldData, tzRounding, comparatorType, context); + return new ValueDateHistogramFacetExecutor(keyIndexFieldData, valueIndexFieldData, tzRounding, comparatorType); } else { - return new CountDateHistogramFacetCollector(facetName, keyIndexFieldData, tzRounding, comparatorType, context); + return new CountDateHistogramFacetExecutor(keyIndexFieldData, tzRounding, comparatorType); } } diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalCountDateHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalCountDateHistogramFacet.java index 4254d7f684a..1ef7dd19a9d 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalCountDateHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalCountDateHistogramFacet.java @@ -70,28 +70,13 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet } @Override - public long time() { + public long getTime() { return time; } - @Override - public long getTime() { - return time(); - } - - @Override - public long count() { - return count; - } - @Override public long getCount() { - return count(); - } - - @Override - public long totalCount() { - return 0; + return count; } @Override @@ -99,28 +84,13 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet return 0; } - @Override - public double total() { - return Double.NaN; - } - @Override public double getTotal() { - return total(); - } - - @Override - public double mean() { return Double.NaN; } @Override public double getMean() { - return mean(); - } - - @Override - public double min() { return Double.NaN; } @@ -129,69 +99,35 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet return Double.NaN; } - @Override - public double max() { - return Double.NaN; - } - @Override public double getMax() { return Double.NaN; } } - private String name; - private ComparatorType comparatorType; - TLongLongHashMap counts; boolean cachedCounts; - CountEntry[] entries = null; private InternalCountDateHistogramFacet() { } public InternalCountDateHistogramFacet(String name, ComparatorType comparatorType, TLongLongHashMap counts, boolean cachedCounts) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.counts = counts; this.cachedCounts = cachedCounts; } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { return Arrays.asList(computeEntries()); } - @Override - public List getEntries() { - return entries(); - } - @Override public Iterator iterator() { - return (Iterator) entries().iterator(); + return (Iterator) getEntries().iterator(); } void releaseCache() { @@ -234,7 +170,7 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet } - return new InternalCountDateHistogramFacet(name, comparatorType, counts, true); + return new InternalCountDateHistogramFacet(getName(), comparatorType, counts, true); } static final class Fields { @@ -246,13 +182,13 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, TYPE); builder.startArray(Fields.ENTRIES); for (Entry entry : computeEntries()) { builder.startObject(); - builder.field(Fields.TIME, entry.time()); - builder.field(Fields.COUNT, entry.count()); + builder.field(Fields.TIME, entry.getTime()); + builder.field(Fields.COUNT, entry.getCount()); builder.endObject(); } builder.endArray(); @@ -268,7 +204,7 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); int size = in.readVInt(); @@ -282,7 +218,7 @@ public class InternalCountDateHistogramFacet extends InternalDateHistogramFacet @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(counts.size()); for (TLongLongIterator it = counts.iterator(); it.hasNext(); ) { diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalDateHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalDateHistogramFacet.java index 66a2606d944..bb166b2cc98 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalDateHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalDateHistogramFacet.java @@ -24,10 +24,22 @@ import org.elasticsearch.search.facet.InternalFacet; /** * */ -public abstract class InternalDateHistogramFacet implements DateHistogramFacet, InternalFacet { +public abstract class InternalDateHistogramFacet extends InternalFacet implements DateHistogramFacet { public static void registerStreams() { InternalCountDateHistogramFacet.registerStreams(); InternalFullDateHistogramFacet.registerStreams(); } + + protected InternalDateHistogramFacet() { + } + + protected InternalDateHistogramFacet(String facetName) { + super(facetName); + } + + @Override + public final String getType() { + return TYPE; + } } diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalFullDateHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalFullDateHistogramFacet.java index 9a8159e5f04..14a2d44b747 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalFullDateHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/InternalFullDateHistogramFacet.java @@ -75,92 +75,58 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { } @Override - public long time() { + public long getTime() { return time; } @Override - public long getTime() { - return time(); - } - - @Override - public long count() { + public long getCount() { return count; } @Override - public long getCount() { - return count(); - } - - @Override - public double total() { + public double getTotal() { return total; } @Override - public double getTotal() { - return total(); - } - - @Override - public long totalCount() { + public long getTotalCount() { return totalCount; } @Override - public long getTotalCount() { - return this.totalCount; - } - - @Override - public double mean() { + public double getMean() { if (totalCount == 0) { return totalCount; } return total / totalCount; } - @Override - public double getMean() { - return total / totalCount; - } - - @Override - public double min() { - return this.min; - } - @Override public double getMin() { return this.min; } - @Override - public double max() { - return this.max; - } - @Override public double getMax() { return this.max; } } - private String name; - private ComparatorType comparatorType; - ExtTLongObjectHashMap tEntries; boolean cachedEntries; Collection entries; - private InternalFullDateHistogramFacet() { + InternalFullDateHistogramFacet() { + } + + InternalFullDateHistogramFacet(String name) { + super(name); } public InternalFullDateHistogramFacet(String name, ComparatorType comparatorType, ExtTLongObjectHashMap entries, boolean cachedEntries) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.tEntries = entries; this.cachedEntries = cachedEntries; @@ -168,41 +134,16 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = new ArrayList(entries); } return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @Override public Iterator iterator() { - return (Iterator) entries().iterator(); + return (Iterator) getEntries().iterator(); } void releaseCache() { @@ -218,7 +159,7 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { if (facets.size() == 1) { // we need to sort it InternalFullDateHistogramFacet internalFacet = (InternalFullDateHistogramFacet) facets.get(0); - List entries = internalFacet.entries(); + List entries = internalFacet.getEntries(); Collections.sort(entries, comparatorType.comparator()); internalFacet.releaseCache(); return internalFacet; @@ -262,8 +203,7 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { CacheRecycler.pushLongObjectMap(map); // just initialize it as already ordered facet - InternalFullDateHistogramFacet ret = new InternalFullDateHistogramFacet(); - ret.name = name; + InternalFullDateHistogramFacet ret = new InternalFullDateHistogramFacet(getName()); ret.comparatorType = comparatorType; ret.entries = ordered; return ret; @@ -283,18 +223,18 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, TYPE); builder.startArray(Fields.ENTRIES); - for (Entry entry : entries()) { + for (Entry entry : getEntries()) { builder.startObject(); - builder.field(Fields.TIME, entry.time()); - builder.field(Fields.COUNT, entry.count()); - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.TIME, entry.getTime()); + builder.field(Fields.COUNT, entry.getCount()); + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); @@ -310,7 +250,7 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); cachedEntries = false; @@ -323,7 +263,7 @@ public class InternalFullDateHistogramFacet extends InternalDateHistogramFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(entries.size()); for (FullEntry entry : entries) { diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueDateHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueDateHistogramFacetExecutor.java similarity index 56% rename from src/main/java/org/elasticsearch/search/facet/datehistogram/ValueDateHistogramFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/datehistogram/ValueDateHistogramFacetExecutor.java index 281d05712eb..f95a3ec47bf 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueDateHistogramFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueDateHistogramFacetExecutor.java @@ -20,67 +20,111 @@ package org.elasticsearch.search.facet.datehistogram; import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.DocIdSetIterator; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.common.joda.TimeZoneRounding; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.LongValues; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.internal.SearchContext; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import java.io.IOException; +import java.util.List; /** * A histogram facet collector that uses different fields for the key and the value. */ -public class ValueDateHistogramFacetCollector extends AbstractFacetCollector { +public class ValueDateHistogramFacetExecutor extends FacetExecutor { private final IndexNumericFieldData keyIndexFieldData; private final IndexNumericFieldData valueIndexFieldData; - private final DateHistogramFacet.ComparatorType comparatorType; + final TimeZoneRounding tzRounding; - private LongValues keyValues; - private final DateHistogramProc histoProc; + final ExtTLongObjectHashMap entries; - public ValueDateHistogramFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public ValueDateHistogramFacetExecutor(IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType) { this.comparatorType = comparatorType; this.keyIndexFieldData = keyIndexFieldData; this.valueIndexFieldData = valueIndexFieldData; - this.histoProc = new DateHistogramProc(tzRounding); + this.tzRounding = tzRounding; + + this.entries = CacheRecycler.popLongObjectMap(); } @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, histoProc); + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getLongValues(); - histoProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + public Post post() { + return new Post(); } @Override - public Facet facet() { - return new InternalFullDateHistogramFacet(facetName, comparatorType, histoProc.entries, true); + public InternalFacet buildFacet(String facetName) { + return new InternalFullDateHistogramFacet(facetName, comparatorType, entries, true); + } + + class Post extends FacetExecutor.Post { + + @Override + public void executePost(List docSets) throws IOException { + DateHistogramProc histoProc = new DateHistogramProc(tzRounding, ValueDateHistogramFacetExecutor.this.entries); + for (ContextDocIdSet docSet : docSets) { + LongValues keyValues = keyIndexFieldData.load(docSet.context).getLongValues(); + histoProc.valueValues = valueIndexFieldData.load(docSet.context).getDoubleValues(); + + DocIdSetIterator it = docSet.docSet.iterator(); + int doc; + while ((doc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + keyValues.forEachValueInDoc(doc, histoProc); + } + } + } + } + + class Collector extends FacetExecutor.Collector { + + private final DateHistogramProc histoProc; + private LongValues keyValues; + + public Collector() { + this.histoProc = new DateHistogramProc(tzRounding, entries); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getLongValues(); + histoProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + keyValues.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } } public static class DateHistogramProc implements LongValues.ValueInDocProc { - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); - + final ExtTLongObjectHashMap entries; private final TimeZoneRounding tzRounding; DoubleValues valueValues; final ValueAggregator valueAggregator = new ValueAggregator(); - public DateHistogramProc(TimeZoneRounding tzRounding) { + public DateHistogramProc(TimeZoneRounding tzRounding, ExtTLongObjectHashMap entries) { this.tzRounding = tzRounding; + this.entries = entries; } @Override diff --git a/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueScriptDateHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueScriptDateHistogramFacetExecutor.java similarity index 53% rename from src/main/java/org/elasticsearch/search/facet/datehistogram/ValueScriptDateHistogramFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/datehistogram/ValueScriptDateHistogramFacetExecutor.java index e340e102669..25fa538259f 100644 --- a/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueScriptDateHistogramFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/datehistogram/ValueScriptDateHistogramFacetExecutor.java @@ -20,73 +20,116 @@ package org.elasticsearch.search.facet.datehistogram; import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.search.Scorer; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.common.joda.TimeZoneRounding; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.LongValues; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.internal.SearchContext; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import java.io.IOException; +import java.util.List; /** * A histogram facet collector that uses the same field as the key as well as the * value. */ -public class ValueScriptDateHistogramFacetCollector extends AbstractFacetCollector { +public class ValueScriptDateHistogramFacetExecutor extends FacetExecutor { private final IndexNumericFieldData keyIndexFieldData; - private final DateHistogramFacet.ComparatorType comparatorType; + final SearchScript valueScript; + final TimeZoneRounding tzRounding; - private LongValues keyValues; - private final SearchScript valueScript; - private final DateHistogramProc histoProc; + final ExtTLongObjectHashMap entries; - public ValueScriptDateHistogramFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, SearchScript valueScript, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public ValueScriptDateHistogramFacetExecutor(IndexNumericFieldData keyIndexFieldData, SearchScript valueScript, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType) { this.comparatorType = comparatorType; this.keyIndexFieldData = keyIndexFieldData; this.valueScript = valueScript; - histoProc = new DateHistogramProc(tzRounding, this.valueScript); + this.tzRounding = tzRounding; + + this.entries = CacheRecycler.popLongObjectMap(); } @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, histoProc); + public Collector collector() { + return new Collector(); } @Override - public void setScorer(Scorer scorer) throws IOException { - valueScript.setScorer(scorer); + public Post post() { + return new Post(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getLongValues(); - valueScript.setNextReader(context); + public InternalFacet buildFacet(String facetName) { + return new InternalFullDateHistogramFacet(facetName, comparatorType, entries, true); } - @Override - public Facet facet() { - return new InternalFullDateHistogramFacet(facetName, comparatorType, histoProc.entries, true); + class Post extends FacetExecutor.Post { + + @Override + public void executePost(List docSets) throws IOException { + DateHistogramProc histoProc = new DateHistogramProc(tzRounding, valueScript, ValueScriptDateHistogramFacetExecutor.this.entries); + for (ContextDocIdSet entry : docSets) { + LongValues keyValues = keyIndexFieldData.load(entry.context).getLongValues(); + valueScript.setNextReader(entry.context); + DocIdSetIterator it = entry.docSet.iterator(); + int doc; + while ((doc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + keyValues.forEachValueInDoc(doc, histoProc); + } + } + } + } + + class Collector extends FacetExecutor.Collector { + + private final DateHistogramProc histoProc; + private LongValues keyValues; + + public Collector() { + histoProc = new DateHistogramProc(tzRounding, valueScript, entries); + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + valueScript.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getLongValues(); + valueScript.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + keyValues.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } } public static class DateHistogramProc implements LongValues.ValueInDocProc { private final TimeZoneRounding tzRounding; - protected final SearchScript valueScript; - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); + final ExtTLongObjectHashMap entries; - public DateHistogramProc(TimeZoneRounding tzRounding, SearchScript valueScript) { + public DateHistogramProc(TimeZoneRounding tzRounding, SearchScript valueScript, final ExtTLongObjectHashMap entries) { this.tzRounding = tzRounding; this.valueScript = valueScript; + this.entries = entries; } @Override diff --git a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacet.java b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacet.java index 2c4ef297f3c..96e5fbbee0e 100644 --- a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacet.java @@ -23,8 +23,6 @@ import org.elasticsearch.search.facet.Facet; /** * A query facets returns the count (number of hits) for a facet based on a query. - * - * */ public interface FilterFacet extends Facet { @@ -33,11 +31,6 @@ public interface FilterFacet extends Facet { */ public static final String TYPE = "filter"; - /** - * The count of the facet. - */ - long count(); - /** * The count of the facet. */ diff --git a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetBuilder.java index 2b93de878d3..bde903d1d19 100644 --- a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetBuilder.java @@ -22,14 +22,14 @@ package org.elasticsearch.search.facet.filter; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; /** * */ -public class FilterFacetBuilder extends AbstractFacetBuilder { +public class FilterFacetBuilder extends FacetBuilder { private FilterBuilder filter; diff --git a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetCollector.java deleted file mode 100644 index a44f7ec382d..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetCollector.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.filter; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Filter; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TotalHitCountCollector; -import org.apache.lucene.util.Bits; -import org.elasticsearch.common.lucene.docset.DocIdSets; -import org.elasticsearch.common.lucene.search.XConstantScoreQuery; -import org.elasticsearch.common.lucene.search.XFilteredQuery; -import org.elasticsearch.index.cache.filter.FilterCache; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.OptimizeGlobalFacetCollector; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; - -/** - * - */ -public class FilterFacetCollector extends AbstractFacetCollector implements OptimizeGlobalFacetCollector { - - private final Filter filter; - - private Bits bits; - - private int count = 0; - - public FilterFacetCollector(String facetName, Filter filter, FilterCache filterCache) { - super(facetName); - this.filter = filter; - } - - @Override - public void optimizedGlobalExecution(SearchContext searchContext) throws IOException { - Query query = new XConstantScoreQuery(filter); - if (super.filter != null) { - query = new XFilteredQuery(query, super.filter); - } - Filter searchFilter = searchContext.mapperService().searchFilter(searchContext.types()); - if (searchFilter != null) { - query = new XFilteredQuery(query, searchContext.filterCache().cache(searchFilter)); - } - TotalHitCountCollector collector = new TotalHitCountCollector(); - searchContext.searcher().search(query, collector); - count = collector.getTotalHits(); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - bits = DocIdSets.toSafeBits(context.reader(), filter.getDocIdSet(context, context.reader().getLiveDocs())); - } - - @Override - protected void doCollect(int doc) throws IOException { - if (bits.get(doc)) { - count++; - } - } - - @Override - public Facet facet() { - return new InternalFilterFacet(facetName, count); - } -} diff --git a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetExecutor.java new file mode 100644 index 00000000000..c324089630f --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetExecutor.java @@ -0,0 +1,106 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet.filter; + +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.DocIdSet; +import org.apache.lucene.search.DocIdSetIterator; +import org.apache.lucene.search.Filter; +import org.apache.lucene.util.Bits; +import org.elasticsearch.common.lucene.docset.AndDocIdSet; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; +import org.elasticsearch.common.lucene.docset.DocIdSets; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; + +import java.io.IOException; +import java.util.List; + +/** + * + */ +public class FilterFacetExecutor extends FacetExecutor { + + private final Filter filter; + + int count = -1; + + public FilterFacetExecutor(Filter filter) { + this.filter = filter; + } + + @Override + public Collector collector() { + return new Collector(); + } + + @Override + public Post post() { + return new Post(); + } + + @Override + public InternalFacet buildFacet(String facetName) { + return new InternalFilterFacet(facetName, count); + } + + class Post extends FacetExecutor.Post { + + @Override + public void executePost(List docSets) throws IOException { + int count = 0; + for (ContextDocIdSet docSet : docSets) { + DocIdSet filteredDocIdSet = filter.getDocIdSet(docSet.context, docSet.context.reader().getLiveDocs()); + if (filteredDocIdSet == null || docSet.docSet == null) { + continue; + } + DocIdSetIterator iter = new AndDocIdSet(new DocIdSet[]{docSet.docSet, filteredDocIdSet}).iterator(); + while (iter.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { + count++; + } + } + FilterFacetExecutor.this.count = count; + } + } + + class Collector extends FacetExecutor.Collector { + + private int count = 0; + private Bits bits; + + @Override + public void collect(int doc) throws IOException { + if (bits.get(doc)) { + count++; + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + bits = DocIdSets.toSafeBits(context.reader(), filter.getDocIdSet(context, context.reader().getLiveDocs())); + } + + @Override + public void postCollection() { + bits = null; + FilterFacetExecutor.this.count = count; + } + } +} diff --git a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetParser.java similarity index 70% rename from src/main/java/org/elasticsearch/search/facet/filter/FilterFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/filter/FilterFacetParser.java index 16bbeb8f493..ce3a48a9bd7 100644 --- a/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/filter/FilterFacetParser.java @@ -24,8 +24,8 @@ import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.search.facet.FacetCollector; -import org.elasticsearch.search.facet.FacetProcessor; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -33,10 +33,10 @@ import java.io.IOException; /** * */ -public class FilterFacetProcessor extends AbstractComponent implements FacetProcessor { +public class FilterFacetParser extends AbstractComponent implements FacetParser { @Inject - public FilterFacetProcessor(Settings settings) { + public FilterFacetParser(Settings settings) { super(settings); InternalFilterFacet.registerStreams(); } @@ -47,8 +47,18 @@ public class FilterFacetProcessor extends AbstractComponent implements FacetProc } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.POST; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { Filter facetFilter = context.queryParserService().parseInnerFilter(parser); - return new FilterFacetCollector(facetName, facetFilter, context.filterCache()); + return new FilterFacetExecutor(facetFilter); } } diff --git a/src/main/java/org/elasticsearch/search/facet/filter/InternalFilterFacet.java b/src/main/java/org/elasticsearch/search/facet/filter/InternalFilterFacet.java index 59789d482a8..232a4223918 100644 --- a/src/main/java/org/elasticsearch/search/facet/filter/InternalFilterFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/filter/InternalFilterFacet.java @@ -32,7 +32,7 @@ import java.util.List; /** * */ -public class InternalFilterFacet implements FilterFacet, InternalFacet { +public class InternalFilterFacet extends InternalFacet implements FilterFacet { private static final String STREAM_TYPE = "filter"; @@ -52,48 +52,21 @@ public class InternalFilterFacet implements FilterFacet, InternalFacet { return STREAM_TYPE; } - private String name; - private long count; - private InternalFilterFacet() { - + InternalFilterFacet() { } public InternalFilterFacet(String name, long count) { - this.name = name; + super(name); this.count = count; } - @Override - public String type() { - return TYPE; - } - @Override public String getType() { return TYPE; } - /** - * The "logical" name of the facet. - */ - public String name() { - return name; - } - - @Override - public String getName() { - return name(); - } - - /** - * The count of the facet. - */ - public long count() { - return count; - } - /** * The count of the facet. */ @@ -108,9 +81,9 @@ public class InternalFilterFacet implements FilterFacet, InternalFacet { } int count = 0; for (Facet facet : facets) { - count += ((FilterFacet) facet).count(); + count += ((FilterFacet) facet).getCount(); } - return new InternalFilterFacet(name, count); + return new InternalFilterFacet(getName(), count); } static final class Fields { @@ -120,7 +93,7 @@ public class InternalFilterFacet implements FilterFacet, InternalFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, FilterFacet.TYPE); builder.field(Fields.COUNT, count); builder.endObject(); @@ -135,13 +108,13 @@ public class InternalFilterFacet implements FilterFacet, InternalFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); count = in.readVLong(); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeVLong(count); } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/geodistance/GeoDistanceFacet.java b/src/main/java/org/elasticsearch/search/facet/geodistance/GeoDistanceFacet.java index 82d393abd32..b6e9008df57 100644 --- a/src/main/java/org/elasticsearch/search/facet/geodistance/GeoDistanceFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/geodistance/GeoDistanceFacet.java @@ -33,11 +33,6 @@ public interface GeoDistanceFacet extends Facet, Iterable entries(); - /** * An ordered list of geo distance facet entries. */ @@ -46,11 +41,8 @@ public interface GeoDistanceFacet extends Facet, Iterable entries() { + public List getEntries() { return ImmutableList.copyOf(entries); } - @Override - public List getEntries() { - return entries(); - } - @Override public Iterator iterator() { - return entries().iterator(); + return getEntries().iterator(); } @Override @@ -134,7 +112,7 @@ public class InternalGeoDistanceFacet implements GeoDistanceFacet, InternalFacet @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); entries = new Entry[in.readVInt()]; for (int i = 0; i < entries.length; i++) { entries[i] = new Entry(in.readDouble(), in.readDouble(), in.readVLong(), in.readVLong(), in.readDouble(), in.readDouble(), in.readDouble()); @@ -143,7 +121,7 @@ public class InternalGeoDistanceFacet implements GeoDistanceFacet, InternalFacet @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeVInt(entries.length); for (Entry entry : entries) { out.writeDouble(entry.from); @@ -172,7 +150,7 @@ public class InternalGeoDistanceFacet implements GeoDistanceFacet, InternalFacet @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, GeoDistanceFacet.TYPE); builder.startArray(Fields.RANGES); for (Entry entry : entries) { @@ -183,11 +161,12 @@ public class InternalGeoDistanceFacet implements GeoDistanceFacet, InternalFacet if (!Double.isInfinite(entry.to)) { builder.field(Fields.TO, entry.to); } - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.COUNT, entry.getCount()); + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); diff --git a/src/main/java/org/elasticsearch/search/facet/geodistance/ScriptGeoDistanceFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/geodistance/ScriptGeoDistanceFacetExecutor.java similarity index 66% rename from src/main/java/org/elasticsearch/search/facet/geodistance/ScriptGeoDistanceFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/geodistance/ScriptGeoDistanceFacetExecutor.java index b665ea31fbf..29ecdfd2288 100644 --- a/src/main/java/org/elasticsearch/search/facet/geodistance/ScriptGeoDistanceFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/geodistance/ScriptGeoDistanceFacetExecutor.java @@ -34,38 +34,53 @@ import java.util.Map; /** * */ -public class ScriptGeoDistanceFacetCollector extends GeoDistanceFacetCollector { +public class ScriptGeoDistanceFacetExecutor extends GeoDistanceFacetExecutor { private final SearchScript script; - private Aggregator scriptAggregator; - - public ScriptGeoDistanceFacetCollector(String facetName, IndexGeoPointFieldData indexFieldData, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance, - GeoDistanceFacet.Entry[] entries, SearchContext context, - String scriptLang, String script, Map params) { - super(facetName, indexFieldData, lat, lon, unit, geoDistance, entries, context); - + public ScriptGeoDistanceFacetExecutor(IndexGeoPointFieldData indexFieldData, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance, + GeoDistanceFacet.Entry[] entries, SearchContext context, + String scriptLang, String script, Map params) { + super(indexFieldData, lat, lon, unit, geoDistance, entries, context); this.script = context.scriptService().search(context.lookup(), scriptLang, script, params); - this.aggregator = new Aggregator(fixedSourceDistance, entries); - this.scriptAggregator = (Aggregator) this.aggregator; } @Override - public void setScorer(Scorer scorer) throws IOException { - script.setScorer(scorer); + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - super.doSetNextReader(context); - script.setNextReader(context); + public Post post() { + return null; } - @Override - protected void doCollect(int doc) throws IOException { - script.setNextDocId(doc); - this.scriptAggregator.scriptValue = script.runAsDouble(); - super.doCollect(doc); + class Collector extends GeoDistanceFacetExecutor.Collector { + + private Aggregator scriptAggregator; + + Collector() { + this.aggregator = new Aggregator(fixedSourceDistance, entries); + this.scriptAggregator = (Aggregator) this.aggregator; + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + script.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + super.setNextReader(context); + script.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + script.setNextDocId(doc); + this.scriptAggregator.scriptValue = script.runAsDouble(); + super.collect(doc); + } } public static class Aggregator implements GeoPointValues.LatLonValueInDocProc { diff --git a/src/main/java/org/elasticsearch/search/facet/geodistance/ValueGeoDistanceFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/geodistance/ValueGeoDistanceFacetExecutor.java similarity index 76% rename from src/main/java/org/elasticsearch/search/facet/geodistance/ValueGeoDistanceFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/geodistance/ValueGeoDistanceFacetExecutor.java index 4f35748fc10..952e5c9cd3d 100644 --- a/src/main/java/org/elasticsearch/search/facet/geodistance/ValueGeoDistanceFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/geodistance/ValueGeoDistanceFacetExecutor.java @@ -33,21 +33,37 @@ import java.io.IOException; /** * */ -public class ValueGeoDistanceFacetCollector extends GeoDistanceFacetCollector { +public class ValueGeoDistanceFacetExecutor extends GeoDistanceFacetExecutor { private final IndexNumericFieldData valueIndexFieldData; - public ValueGeoDistanceFacetCollector(String facetName, IndexGeoPointFieldData indexFieldData, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance, - GeoDistanceFacet.Entry[] entries, SearchContext context, IndexNumericFieldData valueIndexFieldData) { - super(facetName, indexFieldData, lat, lon, unit, geoDistance, entries, context); + public ValueGeoDistanceFacetExecutor(IndexGeoPointFieldData indexFieldData, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance, + GeoDistanceFacet.Entry[] entries, SearchContext context, IndexNumericFieldData valueIndexFieldData) { + super(indexFieldData, lat, lon, unit, geoDistance, entries, context); this.valueIndexFieldData = valueIndexFieldData; - this.aggregator = new Aggregator(fixedSourceDistance, entries); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - super.doSetNextReader(context); - ((Aggregator) this.aggregator).valueValues = valueIndexFieldData.load(context).getDoubleValues(); + public Collector collector() { + return new Collector(); + } + + @Override + public Post post() { + return null; + } + + class Collector extends GeoDistanceFacetExecutor.Collector { + + Collector() { + this.aggregator = new Aggregator(fixedSourceDistance, entries); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + super.setNextReader(context); + ((Aggregator) this.aggregator).valueValues = valueIndexFieldData.load(context).getDoubleValues(); + } } public static class Aggregator implements GeoPointValues.LatLonValueInDocProc { diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/CountHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/CountHistogramFacetExecutor.java similarity index 59% rename from src/main/java/org/elasticsearch/search/facet/histogram/unbounded/CountHistogramFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/histogram/CountHistogramFacetExecutor.java index 2c36711d150..5b2974f882d 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/CountHistogramFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/CountHistogramFacetExecutor.java @@ -17,16 +17,15 @@ * under the License. */ -package org.elasticsearch.search.facet.histogram.unbounded; +package org.elasticsearch.search.facet.histogram; import gnu.trove.map.hash.TLongLongHashMap; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -35,49 +34,73 @@ import java.io.IOException; * A histogram facet collector that uses the same field as the key as well as the * value. */ -public class CountHistogramFacetCollector extends AbstractFacetCollector { +public class CountHistogramFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private final HistogramFacet.ComparatorType comparatorType; + final long interval; - private DoubleValues values; - private final HistogramProc histoProc; + final TLongLongHashMap counts; - public CountHistogramFacetCollector(String facetName, IndexNumericFieldData indexFieldData, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public CountHistogramFacetExecutor(IndexNumericFieldData indexFieldData, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { this.comparatorType = comparatorType; this.indexFieldData = indexFieldData; - histoProc = new HistogramProc(interval); + this.interval = interval; + + this.counts = CacheRecycler.popLongLongMap(); } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, histoProc); + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getDoubleValues(); + public Post post() { + return null; } @Override - public Facet facet() { - return new InternalCountHistogramFacet(facetName, comparatorType, histoProc.counts(), true); + public InternalFacet buildFacet(String facetName) { + return new InternalCountHistogramFacet(facetName, comparatorType, counts, true); } public static long bucket(double value, long interval) { return (((long) (value / interval)) * interval); } + class Collector extends FacetExecutor.Collector { + + private final HistogramProc histoProc; + private DoubleValues values; + + public Collector() { + histoProc = new HistogramProc(interval, counts); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } + } + public static class HistogramProc implements DoubleValues.ValueInDocProc { private final long interval; + private final TLongLongHashMap counts; - private final TLongLongHashMap counts = CacheRecycler.popLongLongMap(); - - public HistogramProc(long interval) { + public HistogramProc(long interval, TLongLongHashMap counts) { this.interval = interval; + this.counts = counts; } @Override diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/FullHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/FullHistogramFacetExecutor.java similarity index 63% rename from src/main/java/org/elasticsearch/search/facet/histogram/unbounded/FullHistogramFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/histogram/FullHistogramFacetExecutor.java index 440523b1854..edb26c1df9f 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/FullHistogramFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/FullHistogramFacetExecutor.java @@ -17,16 +17,15 @@ * under the License. */ -package org.elasticsearch.search.facet.histogram.unbounded; +package org.elasticsearch.search.facet.histogram; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -35,49 +34,73 @@ import java.io.IOException; * A histogram facet collector that uses the same field as the key as well as the * value. */ -public class FullHistogramFacetCollector extends AbstractFacetCollector { +public class FullHistogramFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private final HistogramFacet.ComparatorType comparatorType; + final long interval; - private DoubleValues values; - private final HistogramProc histoProc; + final ExtTLongObjectHashMap entries; - public FullHistogramFacetCollector(String facetName, IndexNumericFieldData indexFieldData, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public FullHistogramFacetExecutor(IndexNumericFieldData indexFieldData, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { this.comparatorType = comparatorType; this.indexFieldData = indexFieldData; - histoProc = new HistogramProc(interval); + this.interval = interval; + + this.entries = CacheRecycler.popLongObjectMap(); } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, histoProc); + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getDoubleValues(); + public Post post() { + return null; } @Override - public Facet facet() { - return new InternalFullHistogramFacet(facetName, comparatorType, histoProc.entries, true); + public InternalFacet buildFacet(String facetName) { + return new InternalFullHistogramFacet(facetName, comparatorType, entries, true); } public static long bucket(double value, long interval) { return (((long) (value / interval)) * interval); } + class Collector extends FacetExecutor.Collector { + + private final HistogramProc histoProc; + private DoubleValues values; + + Collector() { + this.histoProc = new HistogramProc(interval, entries); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } + } + public static class HistogramProc implements DoubleValues.ValueInDocProc { final long interval; + final ExtTLongObjectHashMap entries; - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); - - public HistogramProc(long interval) { + public HistogramProc(long interval, ExtTLongObjectHashMap entries) { this.interval = interval; + this.entries = entries; } @Override diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacet.java index 0068aeb3f67..dff458d7a6d 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacet.java @@ -35,11 +35,6 @@ public interface HistogramFacet extends Facet, Iterable { */ public static final String TYPE = "histogram"; - /** - * An ordered list of histogram facet entries. - */ - List entries(); - /** * An ordered list of histogram facet entries. */ @@ -60,7 +55,7 @@ public interface HistogramFacet extends Facet, Iterable { if (o2 == null) { return -1; } - return (o1.key() < o2.key() ? -1 : (o1.key() == o2.key() ? 0 : 1)); + return (o1.getKey() < o2.getKey() ? -1 : (o1.getKey() == o2.getKey() ? 0 : 1)); } }), COUNT((byte) 1, "count", new Comparator() { @@ -77,7 +72,7 @@ public interface HistogramFacet extends Facet, Iterable { if (o2 == null) { return -1; } - return (o1.count() < o2.count() ? -1 : (o1.count() == o2.count() ? 0 : 1)); + return (o1.getCount() < o2.getCount() ? -1 : (o1.getCount() == o2.getCount() ? 0 : 1)); } }), TOTAL((byte) 2, "total", new Comparator() { @@ -94,7 +89,7 @@ public interface HistogramFacet extends Facet, Iterable { if (o2 == null) { return -1; } - return (o1.total() < o2.total() ? -1 : (o1.total() == o2.total() ? 0 : 1)); + return (o1.getTotal() < o2.getTotal() ? -1 : (o1.getTotal() == o2.getTotal() ? 0 : 1)); } }); @@ -147,71 +142,36 @@ public interface HistogramFacet extends Facet, Iterable { public interface Entry { - /** - * The key value of the histogram. - */ - long key(); - /** * The key value of the histogram. */ long getKey(); - /** - * The number of hits that fall within that key "range" or "interval". - */ - long count(); - /** * The number of hits that fall within that key "range" or "interval". */ long getCount(); - /** - * The total count of values aggregated to compute the total. - */ - long totalCount(); - /** * The total count of values aggregated to compute the total. */ long getTotalCount(); - /** - * The sum / total of the value field that fall within this key "interval". - */ - double total(); - /** * The sum / total of the value field that fall within this key "interval". */ double getTotal(); - /** - * The mean of this facet interval. - */ - double mean(); - /** * The mean of this facet interval. */ double getMean(); - /** - * The minimum value. - */ - double min(); - /** * The minimum value. */ double getMin(); - /** - * The maximum value. - */ - double max(); - /** * The maximum value. */ diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetBuilder.java index 5e436b519da..adcb7b5baa4 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetBuilder.java @@ -22,7 +22,7 @@ package org.elasticsearch.search.facet.histogram; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -30,13 +30,11 @@ import java.util.concurrent.TimeUnit; /** * A facet builder of histogram facets. */ -public class HistogramFacetBuilder extends AbstractFacetBuilder { +public class HistogramFacetBuilder extends FacetBuilder { private String keyFieldName; private String valueFieldName; private long interval = -1; private HistogramFacet.ComparatorType comparatorType; - private Object from; - private Object to; /** * Constructs a new histogram facet with the provided facet logical name. @@ -90,16 +88,6 @@ public class HistogramFacetBuilder extends AbstractFacetBuilder { return interval(unit.toMillis(interval)); } - /** - * Sets the bounds from and to for the facet. Both performs bounds check and includes only - * values within the bounds, and improves performance. - */ - public HistogramFacetBuilder bounds(Object from, Object to) { - this.from = from; - this.to = to; - return this; - } - public HistogramFacetBuilder comparator(HistogramFacet.ComparatorType comparatorType) { this.comparatorType = comparatorType; return this; @@ -150,11 +138,6 @@ public class HistogramFacetBuilder extends AbstractFacetBuilder { } builder.field("interval", interval); - if (from != null && to != null) { - builder.field("from", from); - builder.field("to", to); - } - if (comparatorType != null) { builder.field("comparator", comparatorType.description()); } diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetParser.java similarity index 67% rename from src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetParser.java index 4caee82a0cf..6d201a26662 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramFacetParser.java @@ -26,13 +26,9 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.mapper.FieldMapper; -import org.elasticsearch.search.facet.FacetCollector; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.facet.FacetPhaseExecutionException; -import org.elasticsearch.search.facet.FacetProcessor; -import org.elasticsearch.search.facet.histogram.bounded.BoundedCountHistogramFacetCollector; -import org.elasticsearch.search.facet.histogram.bounded.BoundedValueHistogramFacetCollector; -import org.elasticsearch.search.facet.histogram.bounded.BoundedValueScriptHistogramFacetCollector; -import org.elasticsearch.search.facet.histogram.unbounded.*; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -41,10 +37,10 @@ import java.util.Map; /** * */ -public class HistogramFacetProcessor extends AbstractComponent implements FacetProcessor { +public class HistogramFacetParser extends AbstractComponent implements FacetParser { @Inject - public HistogramFacetProcessor(Settings settings) { + public HistogramFacetParser(Settings settings) { super(settings); InternalHistogramFacet.registerStreams(); } @@ -55,7 +51,17 @@ public class HistogramFacetProcessor extends AbstractComponent implements FacetP } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { String keyField = null; String valueField = null; String keyScript = null; @@ -66,8 +72,6 @@ public class HistogramFacetProcessor extends AbstractComponent implements FacetP HistogramFacet.ComparatorType comparatorType = HistogramFacet.ComparatorType.KEY; XContentParser.Token token; String fieldName = null; - String sFrom = null; - String sTo = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { fieldName = parser.currentName(); @@ -84,10 +88,6 @@ public class HistogramFacetProcessor extends AbstractComponent implements FacetP valueField = parser.text(); } else if ("interval".equals(fieldName)) { interval = parser.longValue(); - } else if ("from".equals(fieldName)) { - sFrom = parser.text(); - } else if ("to".equals(fieldName)) { - sTo = parser.text(); } else if ("time_interval".equals(fieldName)) { interval = TimeValue.parseTimeValue(parser.text(), null).millis(); } else if ("key_script".equals(fieldName) || "keyScript".equals(fieldName)) { @@ -103,7 +103,7 @@ public class HistogramFacetProcessor extends AbstractComponent implements FacetP } if (keyScript != null && valueScript != null) { - return new ScriptHistogramFacetCollector(facetName, scriptLang, keyScript, valueScript, params, interval, comparatorType, context); + return new ScriptHistogramFacetExecutor(scriptLang, keyScript, valueScript, params, interval, comparatorType, context); } if (keyField == null) { @@ -129,28 +129,15 @@ public class HistogramFacetProcessor extends AbstractComponent implements FacetP valueIndexFieldData = context.fieldData().getForField(valueMapper); } - if (sFrom != null && sTo != null && keyField != null) { - long from = ((Number) keyMapper.value(sFrom)).longValue(); - long to = ((Number) keyMapper.value(sTo)).longValue(); - - if (valueField != null) { - return new BoundedValueHistogramFacetCollector(facetName, keyIndexFieldData, valueIndexFieldData, interval, from, to, comparatorType, context); - } else if (valueScript != null) { - return new BoundedValueScriptHistogramFacetCollector(facetName, keyIndexFieldData, scriptLang, valueScript, params, interval, from, to, comparatorType, context); - } else { - return new BoundedCountHistogramFacetCollector(facetName, keyIndexFieldData, interval, from, to, comparatorType, context); - } - } - if (valueScript != null) { - return new ValueScriptHistogramFacetCollector(facetName, keyIndexFieldData, scriptLang, valueScript, params, interval, comparatorType, context); + return new ValueScriptHistogramFacetExecutor(keyIndexFieldData, scriptLang, valueScript, params, interval, comparatorType, context); } else if (valueField == null) { - return new CountHistogramFacetCollector(facetName, keyIndexFieldData, interval, comparatorType, context); + return new CountHistogramFacetExecutor(keyIndexFieldData, interval, comparatorType, context); } else if (keyField.equals(valueField)) { - return new FullHistogramFacetCollector(facetName, keyIndexFieldData, interval, comparatorType, context); + return new FullHistogramFacetExecutor(keyIndexFieldData, interval, comparatorType, context); } else { // we have a value field, and its different than the key - return new ValueHistogramFacetCollector(facetName, keyIndexFieldData, valueIndexFieldData, interval, comparatorType, context); + return new ValueHistogramFacetExecutor(keyIndexFieldData, valueIndexFieldData, interval, comparatorType, context); } } } diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramScriptFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramScriptFacetBuilder.java index ae009a0f191..1c919832f9b 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/HistogramScriptFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/HistogramScriptFacetBuilder.java @@ -23,7 +23,7 @@ import com.google.common.collect.Maps; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.Map; @@ -31,7 +31,7 @@ import java.util.Map; /** * */ -public class HistogramScriptFacetBuilder extends AbstractFacetBuilder { +public class HistogramScriptFacetBuilder extends FacetBuilder { private String lang; private String keyFieldName; private String keyScript; @@ -39,8 +39,6 @@ public class HistogramScriptFacetBuilder extends AbstractFacetBuilder { private Map params; private long interval = -1; private HistogramFacet.ComparatorType comparatorType; - private Object from; - private Object to; public HistogramScriptFacetBuilder(String name) { super(name); @@ -96,16 +94,6 @@ public class HistogramScriptFacetBuilder extends AbstractFacetBuilder { return this; } - /** - * Sets the bounds from and to for the facet. Both performs bounds check and includes only - * values within the bounds, and improves performance. - */ - public HistogramScriptFacetBuilder bounds(Object from, Object to) { - this.from = from; - this.to = to; - return this; - } - public HistogramScriptFacetBuilder facetFilter(FilterBuilder filter) { this.facetFilter = filter; return this; @@ -138,11 +126,6 @@ public class HistogramScriptFacetBuilder extends AbstractFacetBuilder { } builder.field("value_script", valueScript); - if (from != null && to != null) { - builder.field("from", from); - builder.field("to", to); - } - if (lang != null) { builder.field("lang", lang); } diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/InternalCountHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/histogram/InternalCountHistogramFacet.java similarity index 80% rename from src/main/java/org/elasticsearch/search/facet/histogram/unbounded/InternalCountHistogramFacet.java rename to src/main/java/org/elasticsearch/search/facet/histogram/InternalCountHistogramFacet.java index 7e5c746eb91..c15f5be476f 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/InternalCountHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/InternalCountHistogramFacet.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.search.facet.histogram.unbounded; +package org.elasticsearch.search.facet.histogram; import gnu.trove.iterator.TLongLongIterator; import gnu.trove.map.hash.TLongLongHashMap; @@ -27,8 +27,6 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.facet.histogram.InternalHistogramFacet; import java.io.IOException; import java.util.Arrays; @@ -72,38 +70,18 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { } @Override - public long key() { + public long getKey() { return key; } @Override - public long getKey() { - return key(); - } - - @Override - public long count() { + public long getCount() { return count; } - @Override - public long getCount() { - return count(); - } - - @Override - public double total() { - return Double.NaN; - } - @Override public double getTotal() { - return total(); - } - - @Override - public long totalCount() { - return 0; + return Double.NaN; } @Override @@ -111,18 +89,8 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { return 0; } - @Override - public double mean() { - return Double.NaN; - } - @Override public double getMean() { - return mean(); - } - - @Override - public double min() { return Double.NaN; } @@ -131,69 +99,35 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { return Double.NaN; } - @Override - public double max() { - return Double.NaN; - } - @Override public double getMax() { return Double.NaN; } } - private String name; - ComparatorType comparatorType; - TLongLongHashMap counts; boolean cachedCounts; - CountEntry[] entries = null; private InternalCountHistogramFacet() { } public InternalCountHistogramFacet(String name, ComparatorType comparatorType, TLongLongHashMap counts, boolean cachedCounts) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.counts = counts; this.cachedCounts = cachedCounts; } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { return Arrays.asList(computeEntries()); } - @Override - public List getEntries() { - return entries(); - } - @Override public Iterator iterator() { - return (Iterator) entries().iterator(); + return (Iterator) getEntries().iterator(); } private CountEntry[] computeEntries() { @@ -235,7 +169,7 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { histoFacet.releaseCache(); } - return new InternalCountHistogramFacet(name, comparatorType, counts, true); + return new InternalCountHistogramFacet(getName(), comparatorType, counts, true); } static final class Fields { @@ -247,13 +181,13 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, HistogramFacet.TYPE); builder.startArray(Fields.ENTRIES); for (Entry entry : computeEntries()) { builder.startObject(); - builder.field(Fields.KEY, entry.key()); - builder.field(Fields.COUNT, entry.count()); + builder.field(Fields.KEY, entry.getKey()); + builder.field(Fields.COUNT, entry.getCount()); builder.endObject(); } builder.endArray(); @@ -269,7 +203,7 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); int size = in.readVInt(); @@ -283,7 +217,7 @@ public class InternalCountHistogramFacet extends InternalHistogramFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); // optimize the write, since we know we have the same buckets as keys out.writeVInt(counts.size()); diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/InternalFullHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/histogram/InternalFullHistogramFacet.java similarity index 81% rename from src/main/java/org/elasticsearch/search/facet/histogram/unbounded/InternalFullHistogramFacet.java rename to src/main/java/org/elasticsearch/search/facet/histogram/InternalFullHistogramFacet.java index 939da313fbf..f59088d8387 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/InternalFullHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/InternalFullHistogramFacet.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.search.facet.histogram.unbounded; +package org.elasticsearch.search.facet.histogram; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.common.io.stream.StreamInput; @@ -26,8 +26,6 @@ import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.facet.histogram.InternalHistogramFacet; import java.io.IOException; import java.util.*; @@ -77,38 +75,18 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { } @Override - public long key() { + public long getKey() { return key; } @Override - public long getKey() { - return key(); - } - - @Override - public long count() { + public long getCount() { return count; } - @Override - public long getCount() { - return count(); - } - - @Override - public double total() { - return total; - } - @Override public double getTotal() { - return total(); - } - - @Override - public long totalCount() { - return totalCount; + return total; } @Override @@ -116,50 +94,36 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { return this.totalCount; } - @Override - public double mean() { - return total / totalCount; - } - @Override public double getMean() { return total / totalCount; } - @Override - public double min() { - return this.min; - } - @Override public double getMin() { return this.min; } - @Override - public double max() { - return this.max; - } - @Override public double getMax() { return this.max; } } - private String name; - private ComparatorType comparatorType; - ExtTLongObjectHashMap tEntries; boolean cachedEntries; Collection entries; - private InternalFullHistogramFacet() { + InternalFullHistogramFacet() { + } + + InternalFullHistogramFacet(String name) { + super(name); } public InternalFullHistogramFacet(String name, ComparatorType comparatorType, ExtTLongObjectHashMap entries, boolean cachedEntries) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.tEntries = entries; this.cachedEntries = cachedEntries; @@ -167,41 +131,16 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = new ArrayList(entries); } return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @Override public Iterator iterator() { - return (Iterator) entries().iterator(); + return (Iterator) getEntries().iterator(); } void releaseCache() { @@ -217,7 +156,7 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { if (facets.size() == 1) { // we need to sort it InternalFullHistogramFacet internalFacet = (InternalFullHistogramFacet) facets.get(0); - List entries = internalFacet.entries(); + List entries = internalFacet.getEntries(); Collections.sort(entries, comparatorType.comparator()); internalFacet.releaseCache(); return internalFacet; @@ -261,8 +200,7 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { CacheRecycler.pushLongObjectMap(map); // just initialize it as already ordered facet - InternalFullHistogramFacet ret = new InternalFullHistogramFacet(); - ret.name = name; + InternalFullHistogramFacet ret = new InternalFullHistogramFacet(getName()); ret.comparatorType = comparatorType; ret.entries = ordered; return ret; @@ -282,18 +220,18 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, HistogramFacet.TYPE); builder.startArray(Fields.ENTRIES); for (Entry entry : entries) { builder.startObject(); - builder.field(Fields.KEY, entry.key()); - builder.field(Fields.COUNT, entry.count()); - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.KEY, entry.getKey()); + builder.field(Fields.COUNT, entry.getCount()); + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); @@ -309,7 +247,7 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); cachedEntries = false; @@ -322,7 +260,7 @@ public class InternalFullHistogramFacet extends InternalHistogramFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(entries.size()); for (FullEntry entry : entries) { diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/InternalHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/histogram/InternalHistogramFacet.java index 0ec6a8e2ae9..5182f85ab8a 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/InternalHistogramFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/InternalHistogramFacet.java @@ -20,20 +20,26 @@ package org.elasticsearch.search.facet.histogram; import org.elasticsearch.search.facet.InternalFacet; -import org.elasticsearch.search.facet.histogram.bounded.InternalBoundedCountHistogramFacet; -import org.elasticsearch.search.facet.histogram.bounded.InternalBoundedFullHistogramFacet; -import org.elasticsearch.search.facet.histogram.unbounded.InternalCountHistogramFacet; -import org.elasticsearch.search.facet.histogram.unbounded.InternalFullHistogramFacet; /** * */ -public abstract class InternalHistogramFacet implements HistogramFacet, InternalFacet { +public abstract class InternalHistogramFacet extends InternalFacet implements HistogramFacet { public static void registerStreams() { InternalFullHistogramFacet.registerStreams(); InternalCountHistogramFacet.registerStreams(); - InternalBoundedCountHistogramFacet.registerStreams(); - InternalBoundedFullHistogramFacet.registerStreams(); + } + + protected InternalHistogramFacet() { + } + + protected InternalHistogramFacet(String facetName) { + super(facetName); + } + + @Override + public final String getType() { + return TYPE; } } diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/ScriptHistogramFacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/histogram/ScriptHistogramFacetExecutor.java new file mode 100644 index 00000000000..3e663fdeef9 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/histogram/ScriptHistogramFacetExecutor.java @@ -0,0 +1,127 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet.histogram; + +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.Scorer; +import org.elasticsearch.common.CacheRecycler; +import org.elasticsearch.common.trove.ExtTLongObjectHashMap; +import org.elasticsearch.script.SearchScript; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; +import org.elasticsearch.search.internal.SearchContext; + +import java.io.IOException; +import java.util.Map; + +/** + * + */ +public class ScriptHistogramFacetExecutor extends FacetExecutor { + + final SearchScript keyScript; + final SearchScript valueScript; + final long interval; + private final HistogramFacet.ComparatorType comparatorType; + + final ExtTLongObjectHashMap entries; + + public ScriptHistogramFacetExecutor(String scriptLang, String keyScript, String valueScript, Map params, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { + this.keyScript = context.scriptService().search(context.lookup(), scriptLang, keyScript, params); + this.valueScript = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); + this.interval = interval > 0 ? interval : 0; + this.comparatorType = comparatorType; + + this.entries = CacheRecycler.popLongObjectMap(); + } + + @Override + public Collector collector() { + return new Collector(entries); + } + + @Override + public Post post() { + return null; + } + + @Override + public InternalFacet buildFacet(String facetName) { + return new InternalFullHistogramFacet(facetName, comparatorType, entries, true); + } + + public static long bucket(double value, long interval) { + return (((long) (value / interval)) * interval); + } + + class Collector extends FacetExecutor.Collector { + + final ExtTLongObjectHashMap entries; + + Collector(ExtTLongObjectHashMap entries) { + this.entries = entries; + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + keyScript.setScorer(scorer); + valueScript.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyScript.setNextReader(context); + valueScript.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + keyScript.setNextDocId(doc); + valueScript.setNextDocId(doc); + long bucket; + if (interval == 0) { + bucket = keyScript.runAsLong(); + } else { + bucket = bucket(keyScript.runAsDouble(), interval); + } + double value = valueScript.runAsDouble(); + + InternalFullHistogramFacet.FullEntry entry = entries.get(bucket); + if (entry == null) { + entry = new InternalFullHistogramFacet.FullEntry(bucket, 1, value, value, 1, value); + entries.put(bucket, entry); + } else { + entry.count++; + entry.totalCount++; + entry.total += value; + if (value < entry.min) { + entry.min = value; + } + if (value > entry.max) { + entry.max = value; + } + } + } + + @Override + public void postCollection() { + } + } +} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ValueHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/ValueHistogramFacetExecutor.java similarity index 64% rename from src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ValueHistogramFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/histogram/ValueHistogramFacetExecutor.java index 43560f9ae68..19e72957c1e 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ValueHistogramFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/ValueHistogramFacetExecutor.java @@ -17,16 +17,15 @@ * under the License. */ -package org.elasticsearch.search.facet.histogram.unbounded; +package org.elasticsearch.search.facet.histogram; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -34,53 +33,75 @@ import java.io.IOException; /** * A histogram facet collector that uses different fields for the key and the value. */ -public class ValueHistogramFacetCollector extends AbstractFacetCollector { +public class ValueHistogramFacetExecutor extends FacetExecutor { private final IndexNumericFieldData keyIndexFieldData; private final IndexNumericFieldData valueIndexFieldData; - private final HistogramFacet.ComparatorType comparatorType; + private final long interval; - private DoubleValues keyValues; + final ExtTLongObjectHashMap entries; - private final HistogramProc histoProc; - - public ValueHistogramFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public ValueHistogramFacetExecutor(IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { this.comparatorType = comparatorType; this.keyIndexFieldData = keyIndexFieldData; this.valueIndexFieldData = valueIndexFieldData; - histoProc = new HistogramProc(interval); + this.interval = interval; + this.entries = CacheRecycler.popLongObjectMap(); } @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, histoProc); + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getDoubleValues(); - histoProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + public Post post() { + return null; } @Override - public Facet facet() { - return new InternalFullHistogramFacet(facetName, comparatorType, histoProc.entries, true); + public InternalFacet buildFacet(String facetName) { + return new InternalFullHistogramFacet(facetName, comparatorType, entries, true); + } + + class Collector extends FacetExecutor.Collector { + + private final HistogramProc histoProc; + private DoubleValues keyValues; + + public Collector() { + this.histoProc = new HistogramProc(interval, entries); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getDoubleValues(); + histoProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + keyValues.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } } public static class HistogramProc implements DoubleValues.ValueInDocProc { final long interval; - - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); + final ExtTLongObjectHashMap entries; DoubleValues valueValues; final ValueAggregator valueAggregator = new ValueAggregator(); - public HistogramProc(long interval) { + public HistogramProc(long interval, ExtTLongObjectHashMap entries) { this.interval = interval; + this.entries = entries; } @Override @@ -89,7 +110,7 @@ public class ValueHistogramFacetCollector extends AbstractFacetCollector { @Override public void onValue(int docId, double value) { - long bucket = FullHistogramFacetCollector.bucket(value, interval); + long bucket = FullHistogramFacetExecutor.bucket(value, interval); InternalFullHistogramFacet.FullEntry entry = entries.get(bucket); if (entry == null) { entry = new InternalFullHistogramFacet.FullEntry(bucket, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0, 0); diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ValueScriptHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/ValueScriptHistogramFacetExecutor.java similarity index 64% rename from src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ValueScriptHistogramFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/histogram/ValueScriptHistogramFacetExecutor.java index c4bc8f3a68c..9687bde1bb4 100644 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ValueScriptHistogramFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/histogram/ValueScriptHistogramFacetExecutor.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.search.facet.histogram.unbounded; +package org.elasticsearch.search.facet.histogram; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.search.Scorer; @@ -26,9 +26,8 @@ import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -38,60 +37,85 @@ import java.util.Map; * A histogram facet collector that uses the same field as the key as well as the * value. */ -public class ValueScriptHistogramFacetCollector extends AbstractFacetCollector { +public class ValueScriptHistogramFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private final HistogramFacet.ComparatorType comparatorType; + final SearchScript valueScript; + final long interval; - private DoubleValues values; - private final SearchScript valueScript; - private final HistogramProc histoProc; + final ExtTLongObjectHashMap entries; - public ValueScriptHistogramFacetCollector(String facetName, IndexNumericFieldData indexFieldData, String scriptLang, String valueScript, Map params, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public ValueScriptHistogramFacetExecutor(IndexNumericFieldData indexFieldData, String scriptLang, String valueScript, Map params, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { this.comparatorType = comparatorType; this.indexFieldData = indexFieldData; + this.interval = interval; this.valueScript = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); - histoProc = new HistogramProc(interval, this.valueScript); + + this.entries = CacheRecycler.popLongObjectMap(); } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, histoProc); + public Collector collector() { + return new Collector(); } @Override - public void setScorer(Scorer scorer) throws IOException { - valueScript.setScorer(scorer); + public Post post() { + return null; } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getDoubleValues(); - valueScript.setNextReader(context); - } - - @Override - public Facet facet() { - return new InternalFullHistogramFacet(facetName, comparatorType, histoProc.entries, true); + public InternalFacet buildFacet(String facetName) { + return new InternalFullHistogramFacet(facetName, comparatorType, entries, true); } public static long bucket(double value, long interval) { return (((long) (value / interval)) * interval); } + class Collector extends FacetExecutor.Collector { + + private DoubleValues values; + private final HistogramProc histoProc; + + public Collector() { + histoProc = new HistogramProc(interval, valueScript, entries); + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + valueScript.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getDoubleValues(); + valueScript.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, histoProc); + } + + @Override + public void postCollection() { + } + } + public static class HistogramProc implements DoubleValues.ValueInDocProc { private final long interval; private final SearchScript valueScript; - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); + final ExtTLongObjectHashMap entries; - public HistogramProc(long interval, SearchScript valueScript) { + public HistogramProc(long interval, SearchScript valueScript, ExtTLongObjectHashMap entries) { this.interval = interval; this.valueScript = valueScript; + this.entries = entries; } @Override diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedCountHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedCountHistogramFacetCollector.java deleted file mode 100644 index 659232db31b..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedCountHistogramFacetCollector.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.histogram.bounded; - -import org.apache.lucene.index.AtomicReaderContext; -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.index.fielddata.LongValues; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; - -public class BoundedCountHistogramFacetCollector extends AbstractFacetCollector { - - private final IndexNumericFieldData indexFieldData; - - private final HistogramFacet.ComparatorType comparatorType; - - private LongValues values; - - private final HistogramProc histoProc; - - public BoundedCountHistogramFacetCollector(String facetName, IndexNumericFieldData indexFieldData, long interval, long from, long to, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); - this.comparatorType = comparatorType; - this.indexFieldData = indexFieldData; - long normalizedFrom = (((long) ((double) from / interval)) * interval); - long normalizedTo = (((long) ((double) to / interval)) * interval); - if ((to % interval) != 0) { - normalizedTo += interval; - } - long offset = -normalizedFrom; - int size = (int) ((normalizedTo - normalizedFrom) / interval); - - histoProc = new HistogramProc(from, to, interval, offset, size); - } - - @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, histoProc); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getLongValues(); - } - - @Override - public Facet facet() { - return new InternalBoundedCountHistogramFacet(facetName, comparatorType, histoProc.interval, -histoProc.offset, histoProc.size, histoProc.counts, true); - } - - public static class HistogramProc implements LongValues.ValueInDocProc { - - final long from; - final long to; - - final long interval; - - final long offset; - - final int size; - - final int[] counts; - - public HistogramProc(long from, long to, long interval, long offset, int size) { - this.from = from; - this.to = to; - this.interval = interval; - this.offset = offset; - this.size = size; - this.counts = CacheRecycler.popIntArray(size); - } - - @Override - public void onMissing(int docId) { - } - - @Override - public void onValue(int docId, long value) { - if (value <= from || value > to) { // bounds check - return; - } - counts[((int) ((value + offset) / interval))]++; - } - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedValueHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedValueHistogramFacetCollector.java deleted file mode 100644 index c61ad3b11ca..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedValueHistogramFacetCollector.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.histogram.bounded; - -import org.apache.lucene.index.AtomicReaderContext; -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.index.fielddata.DoubleValues; -import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.index.fielddata.LongValues; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; - -/** - * - */ -public class BoundedValueHistogramFacetCollector extends AbstractFacetCollector { - - private final IndexNumericFieldData keyIndexFieldData; - private final IndexNumericFieldData valueIndexFieldData; - - private final long interval; - - private final HistogramFacet.ComparatorType comparatorType; - - private LongValues keyValues; - - private final HistogramProc histoProc; - - public BoundedValueHistogramFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, long interval, long from, long to, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); - this.interval = interval; - this.comparatorType = comparatorType; - this.keyIndexFieldData = keyIndexFieldData; - this.valueIndexFieldData = valueIndexFieldData; - - long normalizedFrom = (((long) ((double) from / interval)) * interval); - long normalizedTo = (((long) ((double) to / interval)) * interval); - if ((to % interval) != 0) { - normalizedTo += interval; - } - long offset = -normalizedFrom; - int size = (int) ((normalizedTo - normalizedFrom) / interval); - - histoProc = new HistogramProc(from, to, interval, offset, size); - } - - @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, histoProc); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getLongValues(); - histoProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); - } - - @Override - public Facet facet() { - return new InternalBoundedFullHistogramFacet(facetName, comparatorType, interval, -histoProc.offset, histoProc.size, histoProc.entries, true); - } - - public static class HistogramProc implements LongValues.ValueInDocProc { - - final long from; - final long to; - - final long interval; - - final long offset; - - final int size; - - final Object[] entries; - - DoubleValues valueValues; - - final ValueAggregator valueAggregator = new ValueAggregator(); - - public HistogramProc(long from, long to, long interval, long offset, int size) { - this.from = from; - this.to = to; - this.interval = interval; - this.offset = offset; - this.size = size; - this.entries = CacheRecycler.popObjectArray(size); - } - - @Override - public void onMissing(int docId) { - } - - @Override - public void onValue(int docId, long value) { - if (value <= from || value > to) { // bounds check - return; - } - int index = ((int) ((value + offset) / interval)); - InternalBoundedFullHistogramFacet.FullEntry entry = (InternalBoundedFullHistogramFacet.FullEntry) entries[index]; - if (entry == null) { - entry = new InternalBoundedFullHistogramFacet.FullEntry(index, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0, 0); - entries[index] = entry; - } - entry.count++; - valueAggregator.entry = entry; - valueValues.forEachValueInDoc(docId, valueAggregator); - } - - - public static class ValueAggregator implements DoubleValues.ValueInDocProc { - - InternalBoundedFullHistogramFacet.FullEntry entry; - - @Override - public void onMissing(int docId) { - } - - @Override - public void onValue(int docId, double value) { - entry.totalCount++; - entry.total += value; - if (value < entry.min) { - entry.min = value; - } - if (value > entry.max) { - entry.max = value; - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedValueScriptHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedValueScriptHistogramFacetCollector.java deleted file mode 100644 index 2c3e0940c69..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/BoundedValueScriptHistogramFacetCollector.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.histogram.bounded; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Scorer; -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.index.fielddata.LongValues; -import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; -import java.util.Map; - -/** - * - */ -public class BoundedValueScriptHistogramFacetCollector extends AbstractFacetCollector { - - private final IndexNumericFieldData indexFieldData; - - private final HistogramFacet.ComparatorType comparatorType; - - private LongValues keyValues; - - private final SearchScript valueScript; - - private final HistogramProc histoProc; - - public BoundedValueScriptHistogramFacetCollector(String facetName, IndexNumericFieldData indexFieldData, String scriptLang, String valueScript, Map params, long interval, long from, long to, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); - this.comparatorType = comparatorType; - this.indexFieldData = indexFieldData; - - this.valueScript = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); - - long normalizedFrom = (((long) ((double) from / interval)) * interval); - long normalizedTo = (((long) ((double) to / interval)) * interval); - if ((to % interval) != 0) { - normalizedTo += interval; - } - long offset = -normalizedFrom; - int size = (int) ((normalizedTo - normalizedFrom) / interval); - - histoProc = new HistogramProc(from, to, interval, offset, size, this.valueScript); - } - - @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, histoProc); - } - - @Override - public void setScorer(Scorer scorer) throws IOException { - valueScript.setScorer(scorer); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = indexFieldData.load(context).getLongValues(); - valueScript.setNextReader(context); - } - - @Override - public Facet facet() { - return new InternalBoundedFullHistogramFacet(facetName, comparatorType, histoProc.interval, -histoProc.offset, histoProc.size, histoProc.entries, true); - } - - public static long bucket(double value, long interval) { - return (((long) (value / interval)) * interval); - } - - public static class HistogramProc implements LongValues.ValueInDocProc { - - final long from; - final long to; - - final long interval; - - final long offset; - - final int size; - - final Object[] entries; - - private final SearchScript valueScript; - - public HistogramProc(long from, long to, long interval, long offset, int size, SearchScript valueScript) { - this.from = from; - this.to = to; - this.interval = interval; - this.offset = offset; - this.size = size; - this.entries = CacheRecycler.popObjectArray(size); - this.valueScript = valueScript; - } - - @Override - public void onMissing(int docId) { - } - - @Override - public void onValue(int docId, long value) { - if (value <= from || value > to) { // bounds check - return; - } - int index = ((int) ((value + offset) / interval)); - - valueScript.setNextDocId(docId); - double scriptValue = valueScript.runAsDouble(); - - InternalBoundedFullHistogramFacet.FullEntry entry = (InternalBoundedFullHistogramFacet.FullEntry) entries[index]; - if (entry == null) { - entries[index] = new InternalBoundedFullHistogramFacet.FullEntry(index, 1, scriptValue, scriptValue, 1, scriptValue); - } else { - entry.count++; - entry.totalCount++; - entry.total += scriptValue; - if (scriptValue < entry.min) { - entry.min = scriptValue; - } - if (scriptValue > entry.max) { - entry.max = scriptValue; - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/InternalBoundedCountHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/histogram/bounded/InternalBoundedCountHistogramFacet.java deleted file mode 100644 index 95e1869cc05..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/InternalBoundedCountHistogramFacet.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.histogram.bounded; - -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentBuilderString; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.facet.histogram.InternalHistogramFacet; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -/** - * - */ -public class InternalBoundedCountHistogramFacet extends InternalHistogramFacet { - - private static final String STREAM_TYPE = "cBdHistogram"; - - public static void registerStreams() { - Streams.registerStream(STREAM, STREAM_TYPE); - } - - static Stream STREAM = new Stream() { - @Override - public Facet readFacet(String type, StreamInput in) throws IOException { - return readHistogramFacet(in); - } - }; - - @Override - public String streamType() { - return STREAM_TYPE; - } - - - /** - * A histogram entry representing a single entry within the result of a histogram facet. - */ - public static class CountEntry implements Entry { - private final long key; - private final long count; - - public CountEntry(long key, long count) { - this.key = key; - this.count = count; - } - - @Override - public long key() { - return key; - } - - @Override - public long getKey() { - return key(); - } - - @Override - public long count() { - return count; - } - - @Override - public long getCount() { - return count(); - } - - @Override - public double total() { - return Double.NaN; - } - - @Override - public double getTotal() { - return total(); - } - - @Override - public long totalCount() { - return 0; - } - - @Override - public long getTotalCount() { - return 0; - } - - @Override - public double mean() { - return Double.NaN; - } - - @Override - public double getMean() { - return mean(); - } - - @Override - public double min() { - return Double.NaN; - } - - @Override - public double getMin() { - return Double.NaN; - } - - @Override - public double max() { - return Double.NaN; - } - - @Override - public double getMax() { - return Double.NaN; - } - } - - private String name; - - ComparatorType comparatorType; - - boolean cachedCounts; - int[] counts; - int size; - long interval; - long offset; - - CountEntry[] entries = null; - - private InternalBoundedCountHistogramFacet() { - } - - public InternalBoundedCountHistogramFacet(String name, ComparatorType comparatorType, long interval, long offset, int size, int[] counts, boolean cachedCounts) { - this.name = name; - this.comparatorType = comparatorType; - this.interval = interval; - this.offset = offset; - this.counts = counts; - this.size = size; - this.cachedCounts = cachedCounts; - } - - @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { - return Arrays.asList(computeEntries()); - } - - @Override - public List getEntries() { - return entries(); - } - - @Override - public Iterator iterator() { - return (Iterator) entries().iterator(); - } - - private CountEntry[] computeEntries() { - if (entries != null) { - return entries; - } - entries = new CountEntry[size]; - for (int i = 0; i < size; i++) { - entries[i] = new CountEntry((i * interval) + offset, counts[i]); - } - releaseCache(); - return entries; - } - - void releaseCache() { - if (cachedCounts) { - cachedCounts = false; - CacheRecycler.pushIntArray(counts); - counts = null; - } - } - - @Override - public Facet reduce(List facets) { - if (facets.size() == 1) { - InternalBoundedCountHistogramFacet firstHistoFacet = (InternalBoundedCountHistogramFacet) facets.get(0); - if (comparatorType != ComparatorType.KEY) { - Arrays.sort(firstHistoFacet.entries, comparatorType.comparator()); - } - return facets.get(0); - } - InternalBoundedCountHistogramFacet firstHistoFacet = (InternalBoundedCountHistogramFacet) facets.get(0); - for (int i = 1; i < facets.size(); i++) { - InternalBoundedCountHistogramFacet histoFacet = (InternalBoundedCountHistogramFacet) facets.get(i); - for (int j = 0; j < firstHistoFacet.size; j++) { - firstHistoFacet.counts[j] += histoFacet.counts[j]; - } - histoFacet.releaseCache(); - } - if (comparatorType != ComparatorType.KEY) { - Arrays.sort(firstHistoFacet.entries, comparatorType.comparator()); - } - - return firstHistoFacet; - } - - static final class Fields { - static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); - static final XContentBuilderString ENTRIES = new XContentBuilderString("entries"); - static final XContentBuilderString KEY = new XContentBuilderString("key"); - static final XContentBuilderString COUNT = new XContentBuilderString("count"); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); - builder.field(Fields._TYPE, HistogramFacet.TYPE); - builder.startArray(Fields.ENTRIES); - for (int i = 0; i < size; i++) { - builder.startObject(); - builder.field(Fields.KEY, (i * interval) + offset); - builder.field(Fields.COUNT, counts[i]); - builder.endObject(); - } - builder.endArray(); - builder.endObject(); - releaseCache(); - return builder; - } - - public static InternalBoundedCountHistogramFacet readHistogramFacet(StreamInput in) throws IOException { - InternalBoundedCountHistogramFacet facet = new InternalBoundedCountHistogramFacet(); - facet.readFrom(in); - return facet; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - name = in.readString(); - comparatorType = ComparatorType.fromId(in.readByte()); - offset = in.readLong(); - interval = in.readVLong(); - size = in.readVInt(); - counts = CacheRecycler.popIntArray(size); - cachedCounts = true; - for (int i = 0; i < size; i++) { - counts[i] = in.readVInt(); - } - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); - out.writeByte(comparatorType.id()); - out.writeLong(offset); - out.writeVLong(interval); - out.writeVInt(size); - for (int i = 0; i < size; i++) { - out.writeVInt(counts[i]); - } - releaseCache(); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/InternalBoundedFullHistogramFacet.java b/src/main/java/org/elasticsearch/search/facet/histogram/bounded/InternalBoundedFullHistogramFacet.java deleted file mode 100644 index e949ef4ff11..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/histogram/bounded/InternalBoundedFullHistogramFacet.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.histogram.bounded; - -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentBuilderString; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.facet.histogram.InternalHistogramFacet; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -/** - * - */ -public class InternalBoundedFullHistogramFacet extends InternalHistogramFacet { - - private static final String STREAM_TYPE = "fBdHistogram"; - - public static void registerStreams() { - Streams.registerStream(STREAM, STREAM_TYPE); - } - - static Stream STREAM = new Stream() { - @Override - public Facet readFacet(String type, StreamInput in) throws IOException { - return readHistogramFacet(in); - } - }; - - @Override - public String streamType() { - return STREAM_TYPE; - } - - - /** - * A histogram entry representing a single entry within the result of a histogram facet. - */ - public static class FullEntry implements Entry { - long key; - long count; - long totalCount; - double total; - double min = Double.POSITIVE_INFINITY; - double max = Double.NEGATIVE_INFINITY; - - public FullEntry(long key, long count, double min, double max, long totalCount, double total) { - this.key = key; - this.count = count; - this.min = min; - this.max = max; - this.totalCount = totalCount; - this.total = total; - } - - @Override - public long key() { - return key; - } - - @Override - public long getKey() { - return key(); - } - - @Override - public long count() { - return count; - } - - @Override - public long getCount() { - return count(); - } - - @Override - public double total() { - return total; - } - - @Override - public double getTotal() { - return total(); - } - - @Override - public long totalCount() { - return totalCount; - } - - @Override - public long getTotalCount() { - return this.totalCount; - } - - @Override - public double mean() { - if (totalCount == 0) { - return 0; - } - return total / totalCount; - } - - @Override - public double getMean() { - return total / totalCount; - } - - @Override - public double min() { - return this.min; - } - - @Override - public double getMin() { - return this.min; - } - - @Override - public double max() { - return this.max; - } - - @Override - public double getMax() { - return this.max; - } - } - - private String name; - - private ComparatorType comparatorType; - - Object[] entries; - List entriesList; - boolean cachedEntries; - int size; - long interval; - long offset; - boolean normalized; - - private InternalBoundedFullHistogramFacet() { - } - - public InternalBoundedFullHistogramFacet(String name, ComparatorType comparatorType, long interval, long offset, int size, Object[] entries, boolean cachedEntries) { - this.name = name; - this.comparatorType = comparatorType; - this.interval = interval; - this.offset = offset; - this.size = size; - this.entries = entries; - this.cachedEntries = cachedEntries; - } - - @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { - normalize(); - if (entriesList == null) { - Object[] newEntries = new Object[size]; - System.arraycopy(entries, 0, newEntries, 0, size); - entriesList = Arrays.asList(newEntries); - } - releaseCache(); - return (List) entriesList; - } - - @Override - public List getEntries() { - return entries(); - } - - @Override - public Iterator iterator() { - return (Iterator) entries().iterator(); - } - - private void releaseCache() { - if (cachedEntries) { - cachedEntries = false; - CacheRecycler.pushObjectArray(entries); - } - } - - @Override - public Facet reduce(List facets) { - if (facets.size() == 1) { - // we need to sort it - InternalBoundedFullHistogramFacet internalFacet = (InternalBoundedFullHistogramFacet) facets.get(0); - if (comparatorType != ComparatorType.KEY) { - Arrays.sort(internalFacet.entries, (Comparator) comparatorType.comparator()); - } - return internalFacet; - } - - InternalBoundedFullHistogramFacet first = (InternalBoundedFullHistogramFacet) facets.get(0); - - for (int f = 1; f < facets.size(); f++) { - InternalBoundedFullHistogramFacet internalFacet = (InternalBoundedFullHistogramFacet) facets.get(f); - for (int i = 0; i < size; i++) { - FullEntry aggEntry = (FullEntry) first.entries[i]; - FullEntry entry = (FullEntry) internalFacet.entries[i]; - if (aggEntry == null) { - first.entries[i] = entry; - } else if (entry != null) { - aggEntry.count += entry.count; - aggEntry.totalCount += entry.totalCount; - aggEntry.total += entry.total; - if (entry.min < aggEntry.min) { - aggEntry.min = entry.min; - } - if (entry.max > aggEntry.max) { - aggEntry.max = entry.max; - } - } - } - internalFacet.releaseCache(); - } - - if (comparatorType != ComparatorType.KEY) { - Arrays.sort(first.entries, (Comparator) comparatorType.comparator()); - } - - return first; - } - - private void normalize() { - if (normalized) { - return; - } - normalized = true; - for (int i = 0; i < size; i++) { - FullEntry entry = (FullEntry) entries[i]; - if (entry == null) { - entries[i] = new FullEntry((i * interval) + offset, 0, Double.NaN, Double.NaN, 0, 0); - } else { - entry.key = (i * interval) + offset; - } - } - } - - static final class Fields { - static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); - static final XContentBuilderString ENTRIES = new XContentBuilderString("entries"); - static final XContentBuilderString KEY = new XContentBuilderString("key"); - static final XContentBuilderString COUNT = new XContentBuilderString("count"); - static final XContentBuilderString TOTAL = new XContentBuilderString("total"); - static final XContentBuilderString TOTAL_COUNT = new XContentBuilderString("total_count"); - static final XContentBuilderString MEAN = new XContentBuilderString("mean"); - static final XContentBuilderString MIN = new XContentBuilderString("min"); - static final XContentBuilderString MAX = new XContentBuilderString("max"); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); - builder.field(Fields._TYPE, HistogramFacet.TYPE); - builder.startArray(Fields.ENTRIES); - for (int i = 0; i < size; i++) { - FullEntry entry = (FullEntry) entries[i]; - builder.startObject(); - if (normalized) { - builder.field(Fields.KEY, entry.key()); - } else { - builder.field(Fields.KEY, (i * interval) + offset); - } - if (entry == null) { - builder.field(Fields.COUNT, 0); - builder.field(Fields.TOTAL, 0); - builder.field(Fields.TOTAL_COUNT, 0); - } else { - builder.field(Fields.COUNT, entry.count()); - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.MEAN, entry.mean()); - } - builder.endObject(); - } - builder.endArray(); - builder.endObject(); - releaseCache(); - return builder; - } - - public static InternalBoundedFullHistogramFacet readHistogramFacet(StreamInput in) throws IOException { - InternalBoundedFullHistogramFacet facet = new InternalBoundedFullHistogramFacet(); - facet.readFrom(in); - return facet; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - name = in.readString(); - comparatorType = ComparatorType.fromId(in.readByte()); - - offset = in.readLong(); - interval = in.readVLong(); - size = in.readVInt(); - entries = CacheRecycler.popObjectArray(size); - cachedEntries = true; - for (int i = 0; i < size; i++) { - if (in.readBoolean()) { - entries[i] = new FullEntry(i, in.readVLong(), in.readDouble(), in.readDouble(), in.readVLong(), in.readDouble()); - } - } - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); - out.writeByte(comparatorType.id()); - out.writeLong(offset); - out.writeVLong(interval); - out.writeVInt(size); - for (int i = 0; i < size; i++) { - FullEntry entry = (FullEntry) entries[i]; - if (entry == null) { - out.writeBoolean(false); - } else { - out.writeBoolean(true); -// out.writeLong(entry.key); - out.writeVLong(entry.count); - out.writeDouble(entry.min); - out.writeDouble(entry.max); - out.writeVLong(entry.totalCount); - out.writeDouble(entry.total); - } - } - releaseCache(); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ScriptHistogramFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ScriptHistogramFacetCollector.java deleted file mode 100644 index c050fde3e1d..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/histogram/unbounded/ScriptHistogramFacetCollector.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.histogram.unbounded; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Scorer; -import org.elasticsearch.common.CacheRecycler; -import org.elasticsearch.common.trove.ExtTLongObjectHashMap; -import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.histogram.HistogramFacet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; -import java.util.Map; - -/** - * - */ -public class ScriptHistogramFacetCollector extends AbstractFacetCollector { - - private final SearchScript keyScript; - - private final SearchScript valueScript; - - private final long interval; - - private final HistogramFacet.ComparatorType comparatorType; - - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); - - public ScriptHistogramFacetCollector(String facetName, String scriptLang, String keyScript, String valueScript, Map params, long interval, HistogramFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); - this.keyScript = context.scriptService().search(context.lookup(), scriptLang, keyScript, params); - this.valueScript = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); - this.interval = interval > 0 ? interval : 0; - this.comparatorType = comparatorType; - } - - @Override - protected void doCollect(int doc) throws IOException { - keyScript.setNextDocId(doc); - valueScript.setNextDocId(doc); - long bucket; - if (interval == 0) { - bucket = keyScript.runAsLong(); - } else { - bucket = bucket(keyScript.runAsDouble(), interval); - } - double value = valueScript.runAsDouble(); - - InternalFullHistogramFacet.FullEntry entry = entries.get(bucket); - if (entry == null) { - entry = new InternalFullHistogramFacet.FullEntry(bucket, 1, value, value, 1, value); - entries.put(bucket, entry); - } else { - entry.count++; - entry.totalCount++; - entry.total += value; - if (value < entry.min) { - entry.min = value; - } - if (value > entry.max) { - entry.max = value; - } - } - } - - @Override - public void setScorer(Scorer scorer) throws IOException { - keyScript.setScorer(scorer); - valueScript.setScorer(scorer); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyScript.setNextReader(context); - valueScript.setNextReader(context); - } - - @Override - public Facet facet() { - return new InternalFullHistogramFacet(facetName, comparatorType, entries, true); - } - - public static long bucket(double value, long interval) { - return (((long) (value / interval)) * interval); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/nested/NestedFacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/nested/NestedFacetExecutor.java new file mode 100644 index 00000000000..d5c8ae97ab9 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/nested/NestedFacetExecutor.java @@ -0,0 +1,204 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet.nested; + +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.DocIdSet; +import org.apache.lucene.search.DocIdSetIterator; +import org.apache.lucene.search.Filter; +import org.apache.lucene.search.Scorer; +import org.apache.lucene.util.Bits; +import org.apache.lucene.util.FixedBitSet; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; +import org.elasticsearch.common.lucene.docset.DocIdSets; +import org.elasticsearch.common.lucene.search.XCollector; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.mapper.object.ObjectMapper; +import org.elasticsearch.index.search.nested.NonNestedDocsFilter; +import org.elasticsearch.search.SearchParseException; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; +import org.elasticsearch.search.internal.SearchContext; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + */ +public class NestedFacetExecutor extends FacetExecutor { + + private final FacetExecutor facetExecutor; + private final Filter parentFilter; + private final Filter childFilter; + + public NestedFacetExecutor(FacetExecutor facetExecutor, SearchContext context, String nestedPath) { + this.facetExecutor = facetExecutor; + MapperService.SmartNameObjectMapper mapper = context.smartNameObjectMapper(nestedPath); + if (mapper == null) { + throw new SearchParseException(context, "facet nested path [" + nestedPath + "] not found"); + } + ObjectMapper objectMapper = mapper.mapper(); + if (objectMapper == null) { + throw new SearchParseException(context, "facet nested path [" + nestedPath + "] not found"); + } + if (!objectMapper.nested().isNested()) { + throw new SearchParseException(context, "facet nested path [" + nestedPath + "] is not nested"); + } + parentFilter = context.filterCache().cache(NonNestedDocsFilter.INSTANCE); + childFilter = context.filterCache().cache(objectMapper.nestedTypeFilter()); + } + + @Override + public InternalFacet buildFacet(String facetName) { + return facetExecutor.buildFacet(facetName); + } + + @Override + public Collector collector() { + XCollector collector = facetExecutor.collector(); + if (collector == null) { + return null; + } + return new Collector(collector, parentFilter, childFilter); + } + + @Override + public Post post() { + FacetExecutor.Post post = facetExecutor.post(); + if (post == null) { + return null; + } + return new Post(post, parentFilter, childFilter); + } + + public static class Post extends FacetExecutor.Post { + + private final FacetExecutor.Post post; + private final Filter parentFilter; + private final Filter childFilter; + + public Post(FacetExecutor.Post post, Filter parentFilter, Filter childFilter) { + this.post = post; + this.parentFilter = parentFilter; + this.childFilter = childFilter; + } + + @Override + public void executePost(List docSets) throws IOException { + List nestedEntries = new ArrayList(docSets.size()); + for (int i = 0; i < docSets.size(); i++) { + ContextDocIdSet entry = docSets.get(i); + AtomicReaderContext context = entry.context; + // Can use null as acceptedDocs here, since only live doc ids are being pushed to collect method. + DocIdSet docIdSet = parentFilter.getDocIdSet(context, null); + if (DocIdSets.isEmpty(docIdSet)) { + continue; + } + // Im ES if parent is deleted, then also the children are deleted. Therefore acceptedDocs can also null here. + Bits childDocs = DocIdSets.toSafeBits(context.reader(), childFilter.getDocIdSet(context, null)); + FixedBitSet parentDocs = (FixedBitSet) docIdSet; + + DocIdSetIterator iter = entry.docSet.iterator(); + int parentDoc = iter.nextDoc(); + if (parentDoc == DocIdSetIterator.NO_MORE_DOCS) { + continue; + } + if (parentDoc == 0) { + parentDoc = iter.nextDoc(); + } + if (parentDoc == DocIdSetIterator.NO_MORE_DOCS) { + continue; + } + FixedBitSet childSet = new FixedBitSet(context.reader().maxDoc()); + do { + int prevParentDoc = parentDocs.prevSetBit(parentDoc - 1); + for (int childDocId = (parentDoc - 1); childDocId > prevParentDoc; childDocId--) { + if (childDocs.get(childDocId)) { + childSet.set(childDocId); + } + } + } while ((parentDoc = iter.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS); + nestedEntries.add(new ContextDocIdSet(entry.context, childSet)); + } + post.executePost(nestedEntries); + } + } + + + public static class Collector extends FacetExecutor.Collector { + + private final org.apache.lucene.search.Collector collector; + private final Filter parentFilter; + private final Filter childFilter; + private Bits childDocs; + private FixedBitSet parentDocs; + + public Collector(org.apache.lucene.search.Collector collector, Filter parentFilter, Filter childFilter) { + this.collector = collector; + this.parentFilter = parentFilter; + this.childFilter = childFilter; + } + + @Override + public void postCollection() { + if (collector instanceof XCollector) { + ((XCollector) collector).postCollection(); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + collector.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + collector.setNextReader(context); + // Can use null as acceptedDocs here, since only live doc ids are being pushed to collect method. + DocIdSet docIdSet = parentFilter.getDocIdSet(context, null); + // Im ES if parent is deleted, then also the children are deleted. Therefore acceptedDocs can also null here. + childDocs = DocIdSets.toSafeBits(context.reader(), childFilter.getDocIdSet(context, null)); + if (DocIdSets.isEmpty(docIdSet)) { + parentDocs = null; + } else { + parentDocs = (FixedBitSet) docIdSet; + } + } + + @Override + public boolean acceptsDocsOutOfOrder() { + return collector.acceptsDocsOutOfOrder(); + } + + @Override + public void collect(int parentDoc) throws IOException { + if (parentDoc == 0 || parentDocs == null) { + return; + } + int prevParentDoc = parentDocs.prevSetBit(parentDoc - 1); + for (int i = (parentDoc - 1); i > prevParentDoc; i--) { + if (childDocs.get(i)) { + collector.collect(i); + } + } + } + } +} diff --git a/src/main/java/org/elasticsearch/search/facet/query/InternalQueryFacet.java b/src/main/java/org/elasticsearch/search/facet/query/InternalQueryFacet.java index 8e776a910f9..dfa4b623fac 100644 --- a/src/main/java/org/elasticsearch/search/facet/query/InternalQueryFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/query/InternalQueryFacet.java @@ -32,7 +32,7 @@ import java.util.List; /** * */ -public class InternalQueryFacet implements QueryFacet, InternalFacet { +public class InternalQueryFacet extends InternalFacet implements QueryFacet { private static final String STREAM_TYPE = "query"; @@ -52,8 +52,6 @@ public class InternalQueryFacet implements QueryFacet, InternalFacet { return STREAM_TYPE; } - private String name; - private long count; private InternalQueryFacet() { @@ -61,42 +59,15 @@ public class InternalQueryFacet implements QueryFacet, InternalFacet { } public InternalQueryFacet(String name, long count) { - this.name = name; + super(name); this.count = count; } - @Override - public String type() { - return TYPE; - } - @Override public String getType() { return TYPE; } - /** - * The "logical" name of the facet. - */ - public String name() { - return name; - } - - @Override - public String getName() { - return name(); - } - - /** - * The count of the facet. - */ - public long count() { - return count; - } - - /** - * The count of the facet. - */ public long getCount() { return count; } @@ -108,11 +79,9 @@ public class InternalQueryFacet implements QueryFacet, InternalFacet { } int count = 0; for (Facet facet : facets) { - if (facet.name().equals(name)) { - count += ((QueryFacet) facet).count(); - } + count += ((QueryFacet) facet).getCount(); } - return new InternalQueryFacet(name, count); + return new InternalQueryFacet(getName(), count); } static final class Fields { @@ -122,7 +91,7 @@ public class InternalQueryFacet implements QueryFacet, InternalFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, QueryFacet.TYPE); builder.field(Fields.COUNT, count); builder.endObject(); @@ -137,13 +106,13 @@ public class InternalQueryFacet implements QueryFacet, InternalFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); count = in.readVLong(); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeVLong(count); } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/query/QueryFacet.java b/src/main/java/org/elasticsearch/search/facet/query/QueryFacet.java index e8b7925eeca..34b80dbef51 100644 --- a/src/main/java/org/elasticsearch/search/facet/query/QueryFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/query/QueryFacet.java @@ -23,8 +23,6 @@ import org.elasticsearch.search.facet.Facet; /** * A query facets returns the count (number of hits) for a facet based on a query. - * - * */ public interface QueryFacet extends Facet { @@ -33,11 +31,6 @@ public interface QueryFacet extends Facet { */ public static final String TYPE = "query"; - /** - * The count of the facet. - */ - long count(); - /** * The count of the facet. */ diff --git a/src/main/java/org/elasticsearch/search/facet/query/QueryFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/query/QueryFacetBuilder.java index 68ffccec08b..a5ee94c3150 100644 --- a/src/main/java/org/elasticsearch/search/facet/query/QueryFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/query/QueryFacetBuilder.java @@ -23,14 +23,14 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; /** * */ -public class QueryFacetBuilder extends AbstractFacetBuilder { +public class QueryFacetBuilder extends FacetBuilder { private QueryBuilder query; diff --git a/src/main/java/org/elasticsearch/search/facet/query/QueryFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/query/QueryFacetExecutor.java similarity index 56% rename from src/main/java/org/elasticsearch/search/facet/query/QueryFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/query/QueryFacetExecutor.java index dbce495b344..920d3ffb988 100644 --- a/src/main/java/org/elasticsearch/search/facet/query/QueryFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/query/QueryFacetExecutor.java @@ -22,33 +22,30 @@ package org.elasticsearch.search.facet.query; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.search.*; import org.apache.lucene.util.Bits; +import org.elasticsearch.common.lucene.docset.AndDocIdSet; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; import org.elasticsearch.common.lucene.docset.DocIdSets; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.lucene.search.XConstantScoreQuery; import org.elasticsearch.common.lucene.search.XFilteredQuery; -import org.elasticsearch.index.cache.filter.FilterCache; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.facet.OptimizeGlobalFacetCollector; -import org.elasticsearch.search.internal.SearchContext; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import java.io.IOException; +import java.util.List; /** * */ -public class QueryFacetCollector extends AbstractFacetCollector implements OptimizeGlobalFacetCollector { +public class QueryFacetExecutor extends FacetExecutor { private final Query query; - private final Filter filter; - private Bits bits; + // default to not initialized + int count = -1; - private int count = 0; - - public QueryFacetCollector(String facetName, Query query, FilterCache filterCache) { - super(facetName); + public QueryFacetExecutor(Query query) { this.query = query; Filter possibleFilter = extractFilterIfApplicable(query); if (possibleFilter != null) { @@ -59,37 +56,63 @@ public class QueryFacetCollector extends AbstractFacetCollector implements Optim } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - bits = DocIdSets.toSafeBits(context.reader(), filter.getDocIdSet(context, context.reader().getLiveDocs())); + public Collector collector() { + return new Collector(); } @Override - protected void doCollect(int doc) throws IOException { - if (bits.get(doc)) { - count++; - } + public Post post() { + return new Post(); } @Override - public void optimizedGlobalExecution(SearchContext searchContext) throws IOException { - Query query = this.query; - if (super.filter != null) { - query = new XFilteredQuery(query, super.filter); - } - Filter searchFilter = searchContext.mapperService().searchFilter(searchContext.types()); - if (searchFilter != null) { - query = new XFilteredQuery(query, searchContext.filterCache().cache(searchFilter)); - } - TotalHitCountCollector collector = new TotalHitCountCollector(); - searchContext.searcher().search(query, collector); - count = collector.getTotalHits(); - } - - @Override - public Facet facet() { + public InternalFacet buildFacet(String facetName) { return new InternalQueryFacet(facetName, count); } + class Post extends FacetExecutor.Post { + + @Override + public void executePost(List docSets) throws IOException { + int count = 0; + for (ContextDocIdSet entry : docSets) { + DocIdSet filteredDocIdSet = filter.getDocIdSet(entry.context, entry.context.reader().getLiveDocs()); + if (filteredDocIdSet == null || entry.docSet == null) { + continue; + } + DocIdSetIterator iter = new AndDocIdSet(new DocIdSet[]{entry.docSet, filteredDocIdSet}).iterator(); + while (iter.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { + count++; + } + } + QueryFacetExecutor.this.count = count; + } + } + + class Collector extends FacetExecutor.Collector { + + private int count = 0; + private Bits bits; + + @Override + public void collect(int doc) throws IOException { + if (bits.get(doc)) { + count++; + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + bits = DocIdSets.toSafeBits(context.reader(), filter.getDocIdSet(context, context.reader().getLiveDocs())); + } + + @Override + public void postCollection() { + bits = null; + QueryFacetExecutor.this.count = count; + } + } + /** * If its a filtered query with a match all, then we just need the inner filter. */ diff --git a/src/main/java/org/elasticsearch/search/facet/query/QueryFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/query/QueryFacetParser.java similarity index 70% rename from src/main/java/org/elasticsearch/search/facet/query/QueryFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/query/QueryFacetParser.java index 0b38476dbf2..77481f0ce64 100644 --- a/src/main/java/org/elasticsearch/search/facet/query/QueryFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/query/QueryFacetParser.java @@ -24,8 +24,8 @@ import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.search.facet.FacetCollector; -import org.elasticsearch.search.facet.FacetProcessor; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -33,10 +33,10 @@ import java.io.IOException; /** * */ -public class QueryFacetProcessor extends AbstractComponent implements FacetProcessor { +public class QueryFacetParser extends AbstractComponent implements FacetParser { @Inject - public QueryFacetProcessor(Settings settings) { + public QueryFacetParser(Settings settings) { super(settings); InternalQueryFacet.registerStreams(); } @@ -47,8 +47,18 @@ public class QueryFacetProcessor extends AbstractComponent implements FacetProce } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.POST; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { Query facetQuery = context.queryParserService().parse(parser).query(); - return new QueryFacetCollector(facetName, facetQuery, context.filterCache()); + return new QueryFacetExecutor(facetQuery); } } diff --git a/src/main/java/org/elasticsearch/search/facet/range/InternalRangeFacet.java b/src/main/java/org/elasticsearch/search/facet/range/InternalRangeFacet.java index 444caa69157..56f5bc1d979 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/InternalRangeFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/range/InternalRangeFacet.java @@ -34,7 +34,7 @@ import java.util.List; /** * */ -public class InternalRangeFacet implements RangeFacet, InternalFacet { +public class InternalRangeFacet extends InternalFacet implements RangeFacet { private static final String STREAM_TYPE = "range"; @@ -54,51 +54,29 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet { return STREAM_TYPE; } - private String name; - Entry[] entries; InternalRangeFacet() { } public InternalRangeFacet(String name, Entry[] entries) { - this.name = name; + super(name); this.entries = entries; } - @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return RangeFacet.TYPE; - } - @Override public String getType() { return RangeFacet.TYPE; } @Override - public List entries() { + public List getEntries() { return ImmutableList.copyOf(entries); } - @Override - public List getEntries() { - return entries(); - } - @Override public Iterator iterator() { - return entries().iterator(); + return getEntries().iterator(); } @Override @@ -138,7 +116,7 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); entries = new Entry[in.readVInt()]; for (int i = 0; i < entries.length; i++) { Entry entry = new Entry(); @@ -161,7 +139,7 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeVInt(entries.length); for (Entry entry : entries) { out.writeDouble(entry.from); @@ -203,7 +181,7 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, "range"); builder.startArray(Fields.RANGES); for (Entry entry : entries) { @@ -220,15 +198,15 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet { if (entry.toAsString != null) { builder.field(Fields.TO_STR, entry.toAsString); } - builder.field(Fields.COUNT, entry.count()); + builder.field(Fields.COUNT, entry.getCount()); // only output min and max if there are actually documents matching this range... - if (entry.totalCount() > 0) { - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); + if (entry.getTotalCount() > 0) { + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); } - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); diff --git a/src/main/java/org/elasticsearch/search/facet/range/KeyValueRangeFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/range/KeyValueRangeFacetExecutor.java similarity index 72% rename from src/main/java/org/elasticsearch/search/facet/range/KeyValueRangeFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/range/KeyValueRangeFacetExecutor.java index 1817bd93393..4ca1e359a80 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/KeyValueRangeFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/range/KeyValueRangeFacetExecutor.java @@ -22,8 +22,8 @@ package org.elasticsearch.search.facet.range; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -31,43 +31,62 @@ import java.io.IOException; /** * */ -public class KeyValueRangeFacetCollector extends AbstractFacetCollector { +public class KeyValueRangeFacetExecutor extends FacetExecutor { private final IndexNumericFieldData keyIndexFieldData; private final IndexNumericFieldData valueIndexFieldData; private final RangeFacet.Entry[] entries; - private final RangeProc rangeProc; - private DoubleValues keyValues; - - public KeyValueRangeFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, RangeFacet.Entry[] entries, SearchContext context) { - super(facetName); + public KeyValueRangeFacetExecutor(IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, RangeFacet.Entry[] entries, SearchContext context) { this.entries = entries; this.keyIndexFieldData = keyIndexFieldData; this.valueIndexFieldData = valueIndexFieldData; - this.rangeProc = new RangeProc(entries); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getDoubleValues(); - rangeProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + public Collector collector() { + return new Collector(); } @Override - protected void doCollect(int doc) throws IOException { - for (RangeFacet.Entry entry : entries) { - entry.foundInDoc = false; - } - keyValues.forEachValueInDoc(doc, rangeProc); + public Post post() { + return null; } @Override - public Facet facet() { + public InternalFacet buildFacet(String facetName) { return new InternalRangeFacet(facetName, entries); } + class Collector extends FacetExecutor.Collector { + + private final RangeProc rangeProc; + private DoubleValues keyValues; + + public Collector() { + this.rangeProc = new RangeProc(entries); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getDoubleValues(); + rangeProc.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + for (RangeFacet.Entry entry : entries) { + entry.foundInDoc = false; + } + keyValues.forEachValueInDoc(doc, rangeProc); + } + + @Override + public void postCollection() { + } + } + public static class RangeProc implements DoubleValues.ValueInDocProc { private final RangeFacet.Entry[] entries; diff --git a/src/main/java/org/elasticsearch/search/facet/range/RangeFacet.java b/src/main/java/org/elasticsearch/search/facet/range/RangeFacet.java index b655bd6d591..a8466722192 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/RangeFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/range/RangeFacet.java @@ -33,11 +33,6 @@ public interface RangeFacet extends Facet, Iterable { */ public static final String TYPE = "range"; - /** - * An ordered list of range facet entries. - */ - List entries(); - /** * An ordered list of range facet entries. */ @@ -46,16 +41,11 @@ public interface RangeFacet extends Facet, Iterable { public class Entry { double from = Double.NEGATIVE_INFINITY; - double to = Double.POSITIVE_INFINITY; - String fromAsString; - String toAsString; - long count; long totalCount; - double total; double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; @@ -68,97 +58,54 @@ public interface RangeFacet extends Facet, Iterable { Entry() { } - public double from() { + public double getFrom() { return this.from; } - public double getFrom() { - return from(); - } - - public String fromAsString() { + public String getFromAsString() { if (fromAsString != null) { return fromAsString; } return Double.toString(from); } - public String getFromAsString() { - return fromAsString(); - } - - public double to() { + public double getTo() { return this.to; } - public double getTo() { - return to(); - } - - public String toAsString() { + public String getToAsString() { if (toAsString != null) { return toAsString; } return Double.toString(to); } - public String getToAsString() { - return toAsString(); - } - - public long count() { - return this.count; - } - public long getCount() { - return count(); - } - - public long totalCount() { - return this.totalCount; + return this.count; } public long getTotalCount() { return this.totalCount; } - public double total() { - return this.total; - } - public double getTotal() { - return total(); - } - - /** - * The mean of this facet interval. - */ - public double mean() { - if (totalCount == 0) { - return 0; - } - return total / totalCount; + return this.total; } /** * The mean of this facet interval. */ public double getMean() { - return mean(); - } - - public double min() { - return this.min; + if (totalCount == 0) { + return 0; + } + return total / totalCount; } public double getMin() { return this.min; } - public double max() { - return this.max; - } - public double getMax() { return this.max; } diff --git a/src/main/java/org/elasticsearch/search/facet/range/RangeFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/range/RangeFacetBuilder.java index f124680e26e..db223a032c1 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/RangeFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/range/RangeFacetBuilder.java @@ -23,7 +23,7 @@ import com.google.common.collect.Lists; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.List; @@ -31,7 +31,7 @@ import java.util.List; /** * A facet builder of range facets. */ -public class RangeFacetBuilder extends AbstractFacetBuilder { +public class RangeFacetBuilder extends FacetBuilder { private String keyFieldName; private String valueFieldName; diff --git a/src/main/java/org/elasticsearch/search/facet/range/RangeFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/range/RangeFacetExecutor.java similarity index 67% rename from src/main/java/org/elasticsearch/search/facet/range/RangeFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/range/RangeFacetExecutor.java index b2bcad6e060..cb04ccf923e 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/RangeFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/range/RangeFacetExecutor.java @@ -22,8 +22,8 @@ package org.elasticsearch.search.facet.range; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -31,39 +31,59 @@ import java.io.IOException; /** * */ -public class RangeFacetCollector extends AbstractFacetCollector { +public class RangeFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private DoubleValues values; private final RangeFacet.Entry[] entries; - private final RangeProc rangeProc; - public RangeFacetCollector(String facetName, IndexNumericFieldData indexFieldData, RangeFacet.Entry[] entries, SearchContext context) { - super(facetName); + public RangeFacetExecutor(IndexNumericFieldData indexFieldData, RangeFacet.Entry[] entries, SearchContext context) { this.indexFieldData = indexFieldData; this.entries = entries; - rangeProc = new RangeProc(entries); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getDoubleValues(); + public Collector collector() { + return new Collector(); } @Override - protected void doCollect(int doc) throws IOException { - for (RangeFacet.Entry entry : entries) { - entry.foundInDoc = false; - } - values.forEachValueInDoc(doc, rangeProc); + public Post post() { + return null; } @Override - public Facet facet() { + public InternalFacet buildFacet(String facetName) { return new InternalRangeFacet(facetName, entries); } + class Collector extends FacetExecutor.Collector { + + private final RangeProc rangeProc; + private DoubleValues values; + + public Collector() { + rangeProc = new RangeProc(entries); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + for (RangeFacet.Entry entry : entries) { + entry.foundInDoc = false; + } + values.forEachValueInDoc(doc, rangeProc); + } + + @Override + public void postCollection() { + } + } + public static class RangeProc implements DoubleValues.ValueInDocProc { private final RangeFacet.Entry[] entries; diff --git a/src/main/java/org/elasticsearch/search/facet/range/RangeFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/range/RangeFacetParser.java similarity index 87% rename from src/main/java/org/elasticsearch/search/facet/range/RangeFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/range/RangeFacetParser.java index f885c5b7f86..5d4cf1d3d45 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/RangeFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/range/RangeFacetParser.java @@ -26,9 +26,9 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.mapper.FieldMapper; -import org.elasticsearch.search.facet.FacetCollector; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.facet.FacetPhaseExecutionException; -import org.elasticsearch.search.facet.FacetProcessor; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -38,10 +38,10 @@ import java.util.Map; /** * */ -public class RangeFacetProcessor extends AbstractComponent implements FacetProcessor { +public class RangeFacetParser extends AbstractComponent implements FacetParser { @Inject - public RangeFacetProcessor(Settings settings) { + public RangeFacetParser(Settings settings) { super(settings); InternalRangeFacet.registerStreams(); } @@ -52,7 +52,17 @@ public class RangeFacetProcessor extends AbstractComponent implements FacetProce } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { String keyField = null; String valueField = null; String scriptLang = null; @@ -120,7 +130,7 @@ public class RangeFacetProcessor extends AbstractComponent implements FacetProce RangeFacet.Entry[] rangeEntries = entries.toArray(new RangeFacet.Entry[entries.size()]); if (keyScript != null && valueScript != null) { - return new ScriptRangeFacetCollector(facetName, scriptLang, keyScript, valueScript, params, rangeEntries, context); + return new ScriptRangeFacetExecutor(scriptLang, keyScript, valueScript, params, rangeEntries, context); } if (keyField == null) { @@ -144,7 +154,7 @@ public class RangeFacetProcessor extends AbstractComponent implements FacetProce IndexNumericFieldData keyIndexFieldData = context.fieldData().getForField(keyFieldMapper); if (valueField == null || keyField.equals(valueField)) { - return new RangeFacetCollector(facetName, keyIndexFieldData, rangeEntries, context); + return new RangeFacetExecutor(keyIndexFieldData, rangeEntries, context); } else { FieldMapper valueFieldMapper = context.smartNameFieldMapper(valueField); if (valueFieldMapper == null) { @@ -152,7 +162,7 @@ public class RangeFacetProcessor extends AbstractComponent implements FacetProce } IndexNumericFieldData valueIndexFieldData = context.fieldData().getForField(valueFieldMapper); // we have a value field, and its different than the key - return new KeyValueRangeFacetCollector(facetName, keyIndexFieldData, valueIndexFieldData, rangeEntries, context); + return new KeyValueRangeFacetExecutor(keyIndexFieldData, valueIndexFieldData, rangeEntries, context); } } } diff --git a/src/main/java/org/elasticsearch/search/facet/range/RangeScriptFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/range/RangeScriptFacetBuilder.java index 762decf2bd9..27c8223ee5c 100644 --- a/src/main/java/org/elasticsearch/search/facet/range/RangeScriptFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/range/RangeScriptFacetBuilder.java @@ -24,7 +24,7 @@ import com.google.common.collect.Maps; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.List; @@ -33,7 +33,7 @@ import java.util.Map; /** * */ -public class RangeScriptFacetBuilder extends AbstractFacetBuilder { +public class RangeScriptFacetBuilder extends FacetBuilder { private String lang; private String keyScript; diff --git a/src/main/java/org/elasticsearch/search/facet/range/ScriptRangeFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/range/ScriptRangeFacetCollector.java deleted file mode 100644 index a8902350e46..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/range/ScriptRangeFacetCollector.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.range; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Scorer; -import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; -import java.util.Map; - -/** - * - */ -public class ScriptRangeFacetCollector extends AbstractFacetCollector { - - private final SearchScript keyScript; - - private final SearchScript valueScript; - - private final RangeFacet.Entry[] entries; - - public ScriptRangeFacetCollector(String facetName, String scriptLang, String keyScript, String valueScript, Map params, RangeFacet.Entry[] entries, SearchContext context) { - super(facetName); - this.keyScript = context.scriptService().search(context.lookup(), scriptLang, keyScript, params); - this.valueScript = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); - this.entries = entries; - } - - @Override - public void setScorer(Scorer scorer) throws IOException { - keyScript.setScorer(scorer); - valueScript.setScorer(scorer); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyScript.setNextReader(context); - valueScript.setNextReader(context); - } - - @Override - protected void doCollect(int doc) throws IOException { - keyScript.setNextDocId(doc); - valueScript.setNextDocId(doc); - double key = keyScript.runAsDouble(); - double value = valueScript.runAsDouble(); - - for (RangeFacet.Entry entry : entries) { - if (key >= entry.getFrom() && key < entry.getTo()) { - entry.count++; - entry.totalCount++; - entry.total += value; - if (value < entry.min) { - entry.min = value; - } - if (value > entry.max) { - entry.max = value; - } - } - } - } - - @Override - public Facet facet() { - return new InternalRangeFacet(facetName, entries); - } -} diff --git a/src/main/java/org/elasticsearch/search/facet/range/ScriptRangeFacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/range/ScriptRangeFacetExecutor.java new file mode 100644 index 00000000000..f2d5607cbda --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/range/ScriptRangeFacetExecutor.java @@ -0,0 +1,103 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet.range; + +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.Scorer; +import org.elasticsearch.script.SearchScript; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; +import org.elasticsearch.search.internal.SearchContext; + +import java.io.IOException; +import java.util.Map; + +/** + * + */ +public class ScriptRangeFacetExecutor extends FacetExecutor { + + final SearchScript keyScript; + final SearchScript valueScript; + + private final RangeFacet.Entry[] entries; + + public ScriptRangeFacetExecutor(String scriptLang, String keyScript, String valueScript, Map params, RangeFacet.Entry[] entries, SearchContext context) { + this.keyScript = context.scriptService().search(context.lookup(), scriptLang, keyScript, params); + this.valueScript = context.scriptService().search(context.lookup(), scriptLang, valueScript, params); + this.entries = entries; + } + + @Override + public Collector collector() { + return new Collector(); + } + + @Override + public Post post() { + return null; + } + + @Override + public InternalFacet buildFacet(String facetName) { + return new InternalRangeFacet(facetName, entries); + } + + class Collector extends FacetExecutor.Collector { + + @Override + public void setScorer(Scorer scorer) throws IOException { + keyScript.setScorer(scorer); + valueScript.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyScript.setNextReader(context); + valueScript.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + keyScript.setNextDocId(doc); + valueScript.setNextDocId(doc); + double key = keyScript.runAsDouble(); + double value = valueScript.runAsDouble(); + + for (RangeFacet.Entry entry : entries) { + if (key >= entry.getFrom() && key < entry.getTo()) { + entry.count++; + entry.totalCount++; + entry.total += value; + if (value < entry.min) { + entry.min = value; + } + if (value > entry.max) { + entry.max = value; + } + } + } + } + + @Override + public void postCollection() { + } + } +} diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/InternalStatisticalFacet.java b/src/main/java/org/elasticsearch/search/facet/statistical/InternalStatisticalFacet.java index 520242ad3ac..a9de385b5c7 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/InternalStatisticalFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/InternalStatisticalFacet.java @@ -32,7 +32,7 @@ import java.util.List; /** * */ -public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet { +public class InternalStatisticalFacet extends InternalFacet implements StatisticalFacet { private static final String STREAM_TYPE = "statistical"; @@ -52,23 +52,17 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet return STREAM_TYPE; } - private String name; - private double min; - private double max; - private double total; - private double sumOfSquares; - private long count; private InternalStatisticalFacet() { } public InternalStatisticalFacet(String name, double min, double max, double total, double sumOfSquares, long count) { - this.name = name; + super(name); this.min = min; this.max = max; this.total = total; @@ -76,58 +70,28 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet this.count = count; } - @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return name(); - } - - @Override - public String type() { - return TYPE; - } - @Override public String getType() { return TYPE; } @Override - public long count() { + public long getCount() { return this.count; } @Override - public long getCount() { - return count(); - } - - @Override - public double total() { + public double getTotal() { return this.total; } @Override - public double getTotal() { - return total(); - } - - @Override - public double sumOfSquares() { + public double getSumOfSquares() { return this.sumOfSquares; } @Override - public double getSumOfSquares() { - return sumOfSquares(); - } - - @Override - public double mean() { + public double getMean() { if (count == 0) { return 0; } @@ -135,44 +99,21 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet } @Override - public double getMean() { - return mean(); - } - - @Override - public double min() { + public double getMin() { return this.min; } @Override - public double getMin() { - return min(); - } - - @Override - public double max() { + public double getMax() { return this.max; } - @Override - public double getMax() { - return max(); - } - - public double variance() { + public double getVariance() { return (sumOfSquares - ((total * total) / count)) / count; } - public double getVariance() { - return variance(); - } - - public double stdDeviation() { - return Math.sqrt(variance()); - } - public double getStdDeviation() { - return stdDeviation(); + return Math.sqrt(getVariance()); } @Override @@ -187,22 +128,19 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet long count = 0; for (Facet facet : facets) { - if (!facet.name().equals(name)) { - continue; - } InternalStatisticalFacet statsFacet = (InternalStatisticalFacet) facet; - if (statsFacet.min() < min || Double.isNaN(min)) { - min = statsFacet.min(); + if (statsFacet.getMin() < min || Double.isNaN(min)) { + min = statsFacet.getMin(); } - if (statsFacet.max() > max || Double.isNaN(max)) { - max = statsFacet.max(); + if (statsFacet.getMax() > max || Double.isNaN(max)) { + max = statsFacet.getMax(); } - total += statsFacet.total(); - sumOfSquares += statsFacet.sumOfSquares(); - count += statsFacet.count(); + total += statsFacet.getTotal(); + sumOfSquares += statsFacet.getSumOfSquares(); + count += statsFacet.getCount(); } - return new InternalStatisticalFacet(name, min, max, total, sumOfSquares, count); + return new InternalStatisticalFacet(getName(), min, max, total, sumOfSquares, count); } static final class Fields { @@ -219,16 +157,16 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, StatisticalFacet.TYPE); - builder.field(Fields.COUNT, count()); - builder.field(Fields.TOTAL, total()); - builder.field(Fields.MIN, min()); - builder.field(Fields.MAX, max()); - builder.field(Fields.MEAN, mean()); - builder.field(Fields.SUM_OF_SQUARES, sumOfSquares()); - builder.field(Fields.VARIANCE, variance()); - builder.field(Fields.STD_DEVIATION, stdDeviation()); + builder.field(Fields.COUNT, getCount()); + builder.field(Fields.TOTAL, getTotal()); + builder.field(Fields.MIN, getMin()); + builder.field(Fields.MAX, getMax()); + builder.field(Fields.MEAN, getMean()); + builder.field(Fields.SUM_OF_SQUARES, getSumOfSquares()); + builder.field(Fields.VARIANCE, getVariance()); + builder.field(Fields.STD_DEVIATION, getStdDeviation()); builder.endObject(); return builder; } @@ -241,7 +179,7 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); count = in.readVLong(); total = in.readDouble(); min = in.readDouble(); @@ -251,7 +189,7 @@ public class InternalStatisticalFacet implements StatisticalFacet, InternalFacet @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeVLong(count); out.writeDouble(total); out.writeDouble(min); diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/ScriptStatisticalFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/statistical/ScriptStatisticalFacetCollector.java deleted file mode 100644 index 9a97f6caef2..00000000000 --- a/src/main/java/org/elasticsearch/search/facet/statistical/ScriptStatisticalFacetCollector.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to ElasticSearch and Shay Banon under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. ElasticSearch licenses this - * file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.search.facet.statistical; - -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.search.Scorer; -import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; -import java.util.Map; - -/** - * - */ -public class ScriptStatisticalFacetCollector extends AbstractFacetCollector { - - private final SearchScript script; - private double min = Double.POSITIVE_INFINITY; - private double max = Double.NEGATIVE_INFINITY; - private double total = 0; - private double sumOfSquares = 0.0; - private long count; - - public ScriptStatisticalFacetCollector(String facetName, String scriptLang, String script, Map params, SearchContext context) { - super(facetName); - this.script = context.scriptService().search(context.lookup(), scriptLang, script, params); - } - - @Override - protected void doCollect(int doc) throws IOException { - script.setNextDocId(doc); - double value = script.runAsDouble(); - if (value < min) { - min = value; - } - if (value > max) { - max = value; - } - sumOfSquares += value * value; - total += value; - count++; - } - - @Override - public void setScorer(Scorer scorer) throws IOException { - script.setScorer(scorer); - } - - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - script.setNextReader(context); - } - - @Override - public Facet facet() { - return new InternalStatisticalFacet(facetName, min, max, total, sumOfSquares, count); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/ScriptStatisticalFacetExecutor.java b/src/main/java/org/elasticsearch/search/facet/statistical/ScriptStatisticalFacetExecutor.java new file mode 100644 index 00000000000..5535d504197 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/facet/statistical/ScriptStatisticalFacetExecutor.java @@ -0,0 +1,106 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.facet.statistical; + +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.Scorer; +import org.elasticsearch.script.SearchScript; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; +import org.elasticsearch.search.internal.SearchContext; + +import java.io.IOException; +import java.util.Map; + +/** + * + */ +public class ScriptStatisticalFacetExecutor extends FacetExecutor { + + private final SearchScript script; + + private double min = Double.POSITIVE_INFINITY; + private double max = Double.NEGATIVE_INFINITY; + private double total = 0; + private double sumOfSquares = 0.0; + private long count; + + public ScriptStatisticalFacetExecutor(String scriptLang, String script, Map params, SearchContext context) { + this.script = context.scriptService().search(context.lookup(), scriptLang, script, params); + } + + @Override + public Collector collector() { + return new Collector(); + } + + @Override + public Post post() { + return null; + } + + @Override + public InternalFacet buildFacet(String facetName) { + return new InternalStatisticalFacet(facetName, min, max, total, sumOfSquares, count); + } + + class Collector extends FacetExecutor.Collector { + + private double min = Double.POSITIVE_INFINITY; + private double max = Double.NEGATIVE_INFINITY; + private double total = 0; + private double sumOfSquares = 0.0; + private long count; + + @Override + public void setScorer(Scorer scorer) throws IOException { + script.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + script.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + script.setNextDocId(doc); + double value = script.runAsDouble(); + if (value < min) { + min = value; + } + if (value > max) { + max = value; + } + sumOfSquares += value * value; + total += value; + count++; + } + + @Override + public void postCollection() { + ScriptStatisticalFacetExecutor.this.min = min; + ScriptStatisticalFacetExecutor.this.max = max; + ScriptStatisticalFacetExecutor.this.total = total; + ScriptStatisticalFacetExecutor.this.sumOfSquares = sumOfSquares; + ScriptStatisticalFacetExecutor.this.count = count; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacet.java b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacet.java index 525042c4ebf..ab5ae21c02a 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacet.java @@ -23,8 +23,6 @@ import org.elasticsearch.search.facet.Facet; /** * Numeric statistical information. - * - * */ public interface StatisticalFacet extends Facet { @@ -33,81 +31,41 @@ public interface StatisticalFacet extends Facet { */ public static final String TYPE = "statistical"; - /** - * The number of values counted. - */ - long count(); - /** * The number of values counted. */ long getCount(); - /** - * The total (sum) of values. - */ - double total(); - /** * The total (sum) of values. */ double getTotal(); - /** - * The sum of squares of the values. - */ - double sumOfSquares(); - /** * The sum of squares of the values. */ double getSumOfSquares(); - /** - * The mean (average) of the values. - */ - double mean(); - /** * The mean (average) of the values. */ double getMean(); - /** - * The minimum value. - */ - double min(); - /** * The minimum value. */ double getMin(); - /** - * The maximum value. - */ - double max(); - /** * The maximum value. */ double getMax(); - /** - * Variance of the values. - */ - double variance(); - /** * Variance of the values. */ double getVariance(); - /** - * Standard deviation of the values. - */ - double stdDeviation(); - /** * Standard deviation of the values. */ diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetBuilder.java index 46a4fe883a3..819bf470c0b 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetBuilder.java @@ -22,14 +22,14 @@ package org.elasticsearch.search.facet.statistical; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; /** * */ -public class StatisticalFacetBuilder extends AbstractFacetBuilder { +public class StatisticalFacetBuilder extends FacetBuilder { private String[] fieldsNames; private String fieldName; diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetExecutor.java similarity index 58% rename from src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetExecutor.java index 23f094ad787..83049cdfee2 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetExecutor.java @@ -22,8 +22,8 @@ package org.elasticsearch.search.facet.statistical; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -31,46 +31,69 @@ import java.io.IOException; /** * */ -public class StatisticalFacetCollector extends AbstractFacetCollector { +public class StatisticalFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private DoubleValues values; + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + double total = 0; + double sumOfSquares = 0.0; + long count; + int missing; - private final StatsProc statsProc = new StatsProc(); - - public StatisticalFacetCollector(String facetName, IndexNumericFieldData indexFieldData, SearchContext context) { - super(facetName); + public StatisticalFacetExecutor(IndexNumericFieldData indexFieldData, SearchContext context) { this.indexFieldData = indexFieldData; } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, statsProc); + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getDoubleValues(); + public Post post() { + return null; } @Override - public Facet facet() { - return new InternalStatisticalFacet(facetName, statsProc.min(), statsProc.max(), statsProc.total(), statsProc.sumOfSquares(), statsProc.count()); + public InternalFacet buildFacet(String facetName) { + return new InternalStatisticalFacet(facetName, min, max, total, sumOfSquares, count); + } + + class Collector extends FacetExecutor.Collector { + + private final StatsProc statsProc = new StatsProc(); + private DoubleValues values; + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getDoubleValues(); + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, statsProc); + } + + @Override + public void postCollection() { + StatisticalFacetExecutor.this.min = statsProc.min; + StatisticalFacetExecutor.this.max = statsProc.max; + StatisticalFacetExecutor.this.total = statsProc.total; + StatisticalFacetExecutor.this.sumOfSquares = statsProc.sumOfSquares; + StatisticalFacetExecutor.this.count = statsProc.count; + StatisticalFacetExecutor.this.missing = statsProc.missing; + } } public static class StatsProc implements DoubleValues.ValueInDocProc { double min = Double.POSITIVE_INFINITY; - double max = Double.NEGATIVE_INFINITY; - double total = 0; - double sumOfSquares = 0.0; - long count; - int missing; @Override diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetParser.java similarity index 83% rename from src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetParser.java index 65ed0240a99..e4be4db33e2 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFacetParser.java @@ -26,9 +26,9 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.mapper.FieldMapper; -import org.elasticsearch.search.facet.FacetCollector; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.facet.FacetPhaseExecutionException; -import org.elasticsearch.search.facet.FacetProcessor; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -38,10 +38,10 @@ import java.util.Map; /** * */ -public class StatisticalFacetProcessor extends AbstractComponent implements FacetProcessor { +public class StatisticalFacetParser extends AbstractComponent implements FacetParser { @Inject - public StatisticalFacetProcessor(Settings settings) { + public StatisticalFacetParser(Settings settings) { super(settings); InternalStatisticalFacet.registerStreams(); } @@ -52,7 +52,17 @@ public class StatisticalFacetProcessor extends AbstractComponent implements Face } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { String field = null; String[] fieldsNames = null; @@ -96,7 +106,7 @@ public class StatisticalFacetProcessor extends AbstractComponent implements Face } indexFieldDatas[i] = context.fieldData().getForField(fieldMapper); } - return new StatisticalFieldsFacetCollector(facetName, indexFieldDatas, context); + return new StatisticalFieldsFacetExecutor(indexFieldDatas, context); } if (script == null && field == null) { throw new FacetPhaseExecutionException(facetName, "statistical facet requires either [script] or [field] to be set"); @@ -107,9 +117,9 @@ public class StatisticalFacetProcessor extends AbstractComponent implements Face throw new FacetPhaseExecutionException(facetName, "No mapping found for field [" + field + "]"); } IndexNumericFieldData indexFieldData = context.fieldData().getForField(fieldMapper); - return new StatisticalFacetCollector(facetName, indexFieldData, context); + return new StatisticalFacetExecutor(indexFieldData, context); } else { - return new ScriptStatisticalFacetCollector(facetName, scriptLang, script, params, context); + return new ScriptStatisticalFacetExecutor(scriptLang, script, params, context); } } } diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFieldsFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFieldsFacetExecutor.java similarity index 55% rename from src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFieldsFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFieldsFacetExecutor.java index df95b0b2987..f69ac23fe75 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFieldsFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalFieldsFacetExecutor.java @@ -22,8 +22,8 @@ package org.elasticsearch.search.facet.statistical; import org.apache.lucene.index.AtomicReaderContext; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -31,37 +31,68 @@ import java.io.IOException; /** * */ -public class StatisticalFieldsFacetCollector extends AbstractFacetCollector { +public class StatisticalFieldsFacetExecutor extends FacetExecutor { private final IndexNumericFieldData[] indexFieldDatas; - private DoubleValues[] values; + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + double total = 0; + double sumOfSquares = 0.0; + long count; + int missing; - private final StatsProc statsProc = new StatsProc(); - - public StatisticalFieldsFacetCollector(String facetName, IndexNumericFieldData[] indexFieldDatas, SearchContext context) { - super(facetName); + public StatisticalFieldsFacetExecutor(IndexNumericFieldData[] indexFieldDatas, SearchContext context) { this.indexFieldDatas = indexFieldDatas; - this.values = new DoubleValues[indexFieldDatas.length]; } @Override - protected void doCollect(int doc) throws IOException { - for (DoubleValues value : values) { - value.forEachValueInDoc(doc, statsProc); + public Collector collector() { + return new Collector(); + } + + @Override + public Post post() { + return null; + } + + @Override + public InternalFacet buildFacet(String facetName) { + return new InternalStatisticalFacet(facetName, min, max, total, sumOfSquares, count); + } + + class Collector extends FacetExecutor.Collector { + + private final StatsProc statsProc = new StatsProc(); + private DoubleValues[] values; + + public Collector() { + this.values = new DoubleValues[indexFieldDatas.length]; } - } - @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - for (int i = 0; i < indexFieldDatas.length; i++) { - values[i] = indexFieldDatas[i].load(context).getDoubleValues(); + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + for (int i = 0; i < indexFieldDatas.length; i++) { + values[i] = indexFieldDatas[i].load(context).getDoubleValues(); + } } - } - @Override - public Facet facet() { - return new InternalStatisticalFacet(facetName, statsProc.min(), statsProc.max(), statsProc.total(), statsProc.sumOfSquares(), statsProc.count()); + @Override + public void collect(int doc) throws IOException { + for (DoubleValues value : values) { + value.forEachValueInDoc(doc, statsProc); + } + } + + @Override + public void postCollection() { + StatisticalFieldsFacetExecutor.this.min = statsProc.min; + StatisticalFieldsFacetExecutor.this.max = statsProc.max; + StatisticalFieldsFacetExecutor.this.total = statsProc.total; + StatisticalFieldsFacetExecutor.this.sumOfSquares = statsProc.sumOfSquares; + StatisticalFieldsFacetExecutor.this.count = statsProc.count; + StatisticalFieldsFacetExecutor.this.missing = statsProc.missing; + } } public static class StatsProc implements DoubleValues.ValueInDocProc { diff --git a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalScriptFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalScriptFacetBuilder.java index 59e51742c31..59b4a4d1976 100644 --- a/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalScriptFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/statistical/StatisticalScriptFacetBuilder.java @@ -23,7 +23,7 @@ import com.google.common.collect.Maps; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.Map; @@ -31,7 +31,7 @@ import java.util.Map; /** * */ -public class StatisticalScriptFacetBuilder extends AbstractFacetBuilder { +public class StatisticalScriptFacetBuilder extends FacetBuilder { private String lang; private String script; private Map params; diff --git a/src/main/java/org/elasticsearch/search/facet/terms/InternalTermsFacet.java b/src/main/java/org/elasticsearch/search/facet/terms/InternalTermsFacet.java index 018e4767704..75fac548e19 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/InternalTermsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/InternalTermsFacet.java @@ -27,11 +27,23 @@ import org.elasticsearch.search.facet.terms.strings.InternalStringTermsFacet; /** * */ -public abstract class InternalTermsFacet implements TermsFacet, InternalFacet { +public abstract class InternalTermsFacet extends InternalFacet implements TermsFacet { public static void registerStreams() { InternalStringTermsFacet.registerStream(); InternalLongTermsFacet.registerStream(); InternalDoubleTermsFacet.registerStream(); } + + protected InternalTermsFacet() { + } + + protected InternalTermsFacet(String facetName) { + super(facetName); + } + + @Override + public final String getType() { + return TYPE; + } } diff --git a/src/main/java/org/elasticsearch/search/facet/terms/TermsFacet.java b/src/main/java/org/elasticsearch/search/facet/terms/TermsFacet.java index 07e5d9ced08..6fdbdd8dda8 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/TermsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/TermsFacet.java @@ -19,9 +19,7 @@ package org.elasticsearch.search.facet.terms; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticSearchIllegalArgumentException; -import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.text.Text; import org.elasticsearch.search.facet.Facet; @@ -30,8 +28,6 @@ import java.util.List; /** * Terms facet allows to return facets of the most popular terms within the search query. - * - * */ public interface TermsFacet extends Facet, Iterable { @@ -42,16 +38,10 @@ public interface TermsFacet extends Facet, Iterable { public interface Entry extends Comparable { - Text term(); - Text getTerm(); - Number termAsNumber(); - Number getTermAsNumber(); - int count(); - int getCount(); } @@ -66,7 +56,7 @@ public interface TermsFacet extends Facet, Iterable { @Override public int compare(Entry o1, Entry o2) { - int i = o2.count() - o1.count(); + int i = o2.getCount() - o1.getCount(); if (i == 0) { i = o2.compareTo(o1); if (i == 0) { @@ -151,41 +141,21 @@ public interface TermsFacet extends Facet, Iterable { } } - /** - * The number of docs missing a value. - */ - long missingCount(); - /** * The number of docs missing a value. */ long getMissingCount(); - /** - * The total count of terms. - */ - long totalCount(); - /** * The total count of terms. */ long getTotalCount(); - /** - * The count of terms other than the one provided by the entries. - */ - long otherCount(); - /** * The count of terms other than the one provided by the entries. */ long getOtherCount(); - /** - * The terms and counts. - */ - List entries(); - /** * The terms and counts. */ diff --git a/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetBuilder.java index 19ce936d88b..302f6988949 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetBuilder.java @@ -24,7 +24,7 @@ import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.Map; @@ -32,7 +32,7 @@ import java.util.Map; /** * Term facets allow to collect frequency of terms within one (or more) field. */ -public class TermsFacetBuilder extends AbstractFacetBuilder { +public class TermsFacetBuilder extends FacetBuilder { private String fieldName; private String[] fieldsNames; private int size = 10; diff --git a/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetParser.java similarity index 78% rename from src/main/java/org/elasticsearch/search/facet/terms/TermsFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/terms/TermsFacetParser.java index 7a7e22f082f..25cac946126 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/TermsFacetParser.java @@ -31,16 +31,16 @@ import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.FacetCollector; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.facet.FacetPhaseExecutionException; -import org.elasticsearch.search.facet.FacetProcessor; -import org.elasticsearch.search.facet.terms.doubles.TermsDoubleFacetCollector; -import org.elasticsearch.search.facet.terms.index.IndexNameFacetCollector; -import org.elasticsearch.search.facet.terms.longs.TermsLongFacetCollector; -import org.elasticsearch.search.facet.terms.strings.FieldsTermsStringFacetCollector; -import org.elasticsearch.search.facet.terms.strings.ScriptTermsStringFieldFacetCollector; -import org.elasticsearch.search.facet.terms.strings.TermsStringFacetCollector; -import org.elasticsearch.search.facet.terms.strings.TermsStringOrdinalsFacetCollector; +import org.elasticsearch.search.facet.terms.doubles.TermsDoubleFacetExecutor; +import org.elasticsearch.search.facet.terms.index.IndexNameFacetExecutor; +import org.elasticsearch.search.facet.terms.longs.TermsLongFacetExecutor; +import org.elasticsearch.search.facet.terms.strings.FieldsTermsStringFacetExecutor; +import org.elasticsearch.search.facet.terms.strings.ScriptTermsStringFieldFacetExecutor; +import org.elasticsearch.search.facet.terms.strings.TermsStringFacetExecutor; +import org.elasticsearch.search.facet.terms.strings.TermsStringOrdinalsFacetExecutor; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; @@ -51,10 +51,10 @@ import java.util.regex.Pattern; /** * */ -public class TermsFacetProcessor extends AbstractComponent implements FacetProcessor { +public class TermsFacetParser extends AbstractComponent implements FacetParser { @Inject - public TermsFacetProcessor(Settings settings) { + public TermsFacetParser(Settings settings) { super(settings); InternalTermsFacet.registerStreams(); } @@ -65,7 +65,17 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { String field = null; int size = 10; @@ -129,7 +139,7 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce } if ("_index".equals(field)) { - return new IndexNameFacetCollector(facetName, context.shardTarget().index(), comparatorType, size); + return new IndexNameFacetExecutor(context.shardTarget().index(), comparatorType, size); } Pattern pattern = null; @@ -143,10 +153,10 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce } if (fieldsNames != null) { - return new FieldsTermsStringFacetCollector(facetName, fieldsNames, size, comparatorType, allTerms, context, excluded, pattern, searchScript); + return new FieldsTermsStringFacetExecutor(facetName, fieldsNames, size, comparatorType, allTerms, context, excluded, pattern, searchScript); } if (field == null && fieldsNames == null && script != null) { - return new ScriptTermsStringFieldFacetCollector(facetName, size, comparatorType, context, excluded, pattern, scriptLang, script, params); + return new ScriptTermsStringFieldFacetExecutor(size, comparatorType, context, excluded, pattern, scriptLang, script, params); } FieldMapper fieldMapper = context.smartNameFieldMapper(field); @@ -158,17 +168,17 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce if (indexFieldData instanceof IndexNumericFieldData) { IndexNumericFieldData indexNumericFieldData = (IndexNumericFieldData) indexFieldData; if (indexNumericFieldData.getNumericType().isFloatingPoint()) { - return new TermsDoubleFacetCollector(facetName, indexNumericFieldData, size, comparatorType, allTerms, context, excluded, searchScript); + return new TermsDoubleFacetExecutor(indexNumericFieldData, size, comparatorType, allTerms, context, excluded, searchScript); } else { - return new TermsLongFacetCollector(facetName, indexNumericFieldData, size, comparatorType, allTerms, context, excluded, searchScript); + return new TermsLongFacetExecutor(indexNumericFieldData, size, comparatorType, allTerms, context, excluded, searchScript); } } else { if (script != null || "map".equals(executionHint)) { - return new TermsStringFacetCollector(facetName, indexFieldData, size, comparatorType, allTerms, context, excluded, pattern, searchScript); + return new TermsStringFacetExecutor(indexFieldData, size, comparatorType, allTerms, context, excluded, pattern, searchScript); } else if (indexFieldData instanceof IndexFieldData.WithOrdinals) { - return new TermsStringOrdinalsFacetCollector(facetName, (IndexFieldData.WithOrdinals) indexFieldData, size, comparatorType, allTerms, context, excluded, pattern); + return new TermsStringOrdinalsFacetExecutor((IndexFieldData.WithOrdinals) indexFieldData, size, comparatorType, allTerms, context, excluded, pattern); } else { - return new TermsStringFacetCollector(facetName, indexFieldData, size, comparatorType, allTerms, context, excluded, pattern, searchScript); + return new TermsStringFacetExecutor(indexFieldData, size, comparatorType, allTerms, context, excluded, pattern, searchScript); } } } diff --git a/src/main/java/org/elasticsearch/search/facet/terms/doubles/InternalDoubleTermsFacet.java b/src/main/java/org/elasticsearch/search/facet/terms/doubles/InternalDoubleTermsFacet.java index 7dbe22bd9d5..2cfaa41d906 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/doubles/InternalDoubleTermsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/doubles/InternalDoubleTermsFacet.java @@ -73,30 +73,18 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { this.count = count; } - public Text term() { - return new StringText(Double.toString(term)); - } - public Text getTerm() { - return term(); - } - - @Override - public Number termAsNumber() { - return term; + return new StringText(Double.toString(term)); } @Override public Number getTermAsNumber() { - return termAsNumber(); - } - - public int count() { - return count; + return term; } + @Override public int getCount() { - return count(); + return count; } @Override @@ -106,7 +94,7 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { return -1; } if (term == anotherVal) { - int i = count - o.count(); + int i = count - o.getCount(); if (i == 0) { i = System.identityHashCode(this) - System.identityHashCode(o); } @@ -116,22 +104,17 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { } } - private String name; - int requiredSize; - long missing; long total; - Collection entries = ImmutableList.of(); - ComparatorType comparatorType; InternalDoubleTermsFacet() { } public InternalDoubleTermsFacet(String name, ComparatorType comparatorType, int requiredSize, Collection entries, long missing, long total) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.requiredSize = requiredSize; this.entries = entries; @@ -140,38 +123,13 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = ImmutableList.copyOf(entries); } return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @SuppressWarnings({"unchecked"}) @Override public Iterator iterator() { @@ -179,39 +137,24 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { } @Override - public long missingCount() { + public long getMissingCount() { return this.missing; } @Override - public long getMissingCount() { - return missingCount(); - } - - @Override - public long totalCount() { + public long getTotalCount() { return this.total; } @Override - public long getTotalCount() { - return totalCount(); - } - - @Override - public long otherCount() { + public long getOtherCount() { long other = total; for (Entry entry : entries) { - other -= entry.count(); + other -= entry.getCount(); } return other; } - @Override - public long getOtherCount() { - return otherCount(); - } - @Override public Facet reduce(List facets) { if (facets.size() == 1) { @@ -223,10 +166,10 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { long total = 0; for (Facet facet : facets) { InternalDoubleTermsFacet mFacet = (InternalDoubleTermsFacet) facet; - missing += mFacet.missingCount(); - total += mFacet.totalCount(); + missing += mFacet.getMissingCount(); + total += mFacet.getTotalCount(); for (DoubleEntry entry : mFacet.entries) { - aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); + aggregated.adjustOrPutValue(entry.term, entry.getCount(), entry.getCount()); } } @@ -256,16 +199,16 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields.MISSING, missing); builder.field(Fields.TOTAL, total); - builder.field(Fields.OTHER, otherCount()); + builder.field(Fields.OTHER, getOtherCount()); builder.startArray(Fields.TERMS); for (DoubleEntry entry : entries) { builder.startObject(); builder.field(Fields.TERM, entry.term); - builder.field(Fields.COUNT, entry.count()); + builder.field(Fields.COUNT, entry.getCount()); builder.endObject(); } builder.endArray(); @@ -281,7 +224,7 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); requiredSize = in.readVInt(); missing = in.readVLong(); @@ -296,7 +239,7 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(requiredSize); out.writeVLong(missing); @@ -305,7 +248,7 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet { out.writeVInt(entries.size()); for (DoubleEntry entry : entries) { out.writeDouble(entry.term); - out.writeVInt(entry.count()); + out.writeVInt(entry.getCount()); } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/terms/doubles/TermsDoubleFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/doubles/TermsDoubleFacetExecutor.java similarity index 75% rename from src/main/java/org/elasticsearch/search/facet/terms/doubles/TermsDoubleFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/doubles/TermsDoubleFacetExecutor.java index dfc1663a87b..559aca2ba65 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/doubles/TermsDoubleFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/doubles/TermsDoubleFacetExecutor.java @@ -32,8 +32,8 @@ import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.support.EntryPriorityQueue; import org.elasticsearch.search.internal.SearchContext; @@ -45,36 +45,29 @@ import java.util.Set; /** * */ -public class TermsDoubleFacetCollector extends AbstractFacetCollector { +public class TermsDoubleFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private final TermsFacet.ComparatorType comparatorType; - private final int size; - private final int numberOfShards; - - private DoubleValues values; - - private final StaticAggregatorValueProc aggregator; - private final SearchScript script; + private final ImmutableSet excluded; - public TermsDoubleFacetCollector(String facetName, IndexNumericFieldData indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, - ImmutableSet excluded, SearchScript script) { - super(facetName); + final TDoubleIntHashMap facets; + long missing; + long total; + + public TermsDoubleFacetExecutor(IndexNumericFieldData indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, + ImmutableSet excluded, SearchScript script) { this.indexFieldData = indexFieldData; this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); this.script = script; + this.excluded = excluded; - if (this.script == null && excluded.isEmpty()) { - aggregator = new StaticAggregatorValueProc(CacheRecycler.popDoubleIntMap()); - } else { - aggregator = new AggregatorValueProc(CacheRecycler.popDoubleIntMap(), excluded, this.script); - } + this.facets = CacheRecycler.popDoubleIntMap(); // TODO: we need to support this with the new field data.... // if (allTerms) { @@ -90,31 +83,20 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector { } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getDoubleValues(); - if (script != null) { - script.setNextReader(context); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, aggregator); - } - - @Override - public Facet facet() { - TDoubleIntHashMap facets = aggregator.facets(); + public InternalFacet buildFacet(String facetName) { if (facets.isEmpty()) { CacheRecycler.pushDoubleIntMap(facets); - return new InternalDoubleTermsFacet(facetName, comparatorType, size, ImmutableList.of(), aggregator.missing(), aggregator.total()); + return new InternalDoubleTermsFacet(facetName, comparatorType, size, ImmutableList.of(), missing, total); } else { if (size < EntryPriorityQueue.LIMIT) { EntryPriorityQueue ordered = new EntryPriorityQueue(size, comparatorType.comparator()); @@ -127,7 +109,7 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector { list[i] = (InternalDoubleTermsFacet.DoubleEntry) ordered.pop(); } CacheRecycler.pushDoubleIntMap(facets); - return new InternalDoubleTermsFacet(facetName, comparatorType, size, Arrays.asList(list), aggregator.missing(), aggregator.total()); + return new InternalDoubleTermsFacet(facetName, comparatorType, size, Arrays.asList(list), missing, total); } else { BoundedTreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size); for (TDoubleIntIterator it = facets.iterator(); it.hasNext(); ) { @@ -135,11 +117,51 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector { ordered.add(new InternalDoubleTermsFacet.DoubleEntry(it.key(), it.value())); } CacheRecycler.pushDoubleIntMap(facets); - return new InternalDoubleTermsFacet(facetName, comparatorType, size, ordered, aggregator.missing(), aggregator.total()); + return new InternalDoubleTermsFacet(facetName, comparatorType, size, ordered, missing, total); } } } + class Collector extends FacetExecutor.Collector { + + private final StaticAggregatorValueProc aggregator; + private DoubleValues values; + + public Collector() { + if (script == null && excluded.isEmpty()) { + aggregator = new StaticAggregatorValueProc(facets); + } else { + aggregator = new AggregatorValueProc(facets, excluded, script); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getDoubleValues(); + if (script != null) { + script.setNextReader(context); + } + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, aggregator); + } + + @Override + public void postCollection() { + TermsDoubleFacetExecutor.this.missing = aggregator.missing(); + TermsDoubleFacetExecutor.this.total = aggregator.total(); + } + } + public static class AggregatorValueProc extends StaticAggregatorValueProc { private final SearchScript script; diff --git a/src/main/java/org/elasticsearch/search/facet/terms/index/IndexNameFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/index/IndexNameFacetExecutor.java similarity index 65% rename from src/main/java/org/elasticsearch/search/facet/terms/index/IndexNameFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/index/IndexNameFacetExecutor.java index c1cccdddd4b..2c457706961 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/index/IndexNameFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/index/IndexNameFacetExecutor.java @@ -21,8 +21,8 @@ package org.elasticsearch.search.facet.terms.index; import com.google.common.collect.Sets; import org.apache.lucene.index.AtomicReaderContext; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.strings.InternalStringTermsFacet; @@ -31,34 +31,51 @@ import java.io.IOException; /** * */ -public class IndexNameFacetCollector extends AbstractFacetCollector { +public class IndexNameFacetExecutor extends FacetExecutor { private final String indexName; - private final InternalStringTermsFacet.ComparatorType comparatorType; - private final int size; private int count = 0; - public IndexNameFacetCollector(String facetName, String indexName, TermsFacet.ComparatorType comparatorType, int size) { - super(facetName); + public IndexNameFacetExecutor(String indexName, TermsFacet.ComparatorType comparatorType, int size) { this.indexName = indexName; this.comparatorType = comparatorType; this.size = size; } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { + public Collector collector() { + return new Collector(); } @Override - protected void doCollect(int doc) throws IOException { - count++; + public Post post() { + return null; } @Override - public Facet facet() { + public InternalFacet buildFacet(String facetName) { return new InternalStringTermsFacet(facetName, comparatorType, size, Sets.newHashSet(new InternalStringTermsFacet.TermEntry(indexName, count)), 0, count); } + + class Collector extends FacetExecutor.Collector { + + private int count; + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + } + + @Override + public void collect(int doc) throws IOException { + count++; + } + + @Override + public void postCollection() { + IndexNameFacetExecutor.this.count = count; + } + } } diff --git a/src/main/java/org/elasticsearch/search/facet/terms/longs/InternalLongTermsFacet.java b/src/main/java/org/elasticsearch/search/facet/terms/longs/InternalLongTermsFacet.java index a0d44d00dcf..471a4625679 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/longs/InternalLongTermsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/longs/InternalLongTermsFacet.java @@ -73,30 +73,19 @@ public class InternalLongTermsFacet extends InternalTermsFacet { this.count = count; } - public Text term() { - return new StringText(Long.toString(term)); - } - - public Text getTerm() { - return term(); - } - @Override - public Number termAsNumber() { - return term; + public Text getTerm() { + return new StringText(Long.toString(term)); } @Override public Number getTermAsNumber() { - return termAsNumber(); - } - - public int count() { - return count; + return term; } + @Override public int getCount() { - return count(); + return count; } @Override @@ -106,7 +95,7 @@ public class InternalLongTermsFacet extends InternalTermsFacet { return -1; } if (term == anotherVal) { - int i = count - o.count(); + int i = count - o.getCount(); if (i == 0) { i = System.identityHashCode(this) - System.identityHashCode(o); } @@ -116,22 +105,17 @@ public class InternalLongTermsFacet extends InternalTermsFacet { } } - private String name; - int requiredSize; - long missing; long total; - Collection entries = ImmutableList.of(); - ComparatorType comparatorType; InternalLongTermsFacet() { } public InternalLongTermsFacet(String name, ComparatorType comparatorType, int requiredSize, Collection entries, long missing, long total) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.requiredSize = requiredSize; this.entries = entries; @@ -140,38 +124,13 @@ public class InternalLongTermsFacet extends InternalTermsFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = ImmutableList.copyOf(entries); } return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @SuppressWarnings({"unchecked"}) @Override public Iterator iterator() { @@ -179,39 +138,24 @@ public class InternalLongTermsFacet extends InternalTermsFacet { } @Override - public long missingCount() { + public long getMissingCount() { return this.missing; } @Override - public long getMissingCount() { - return missingCount(); - } - - @Override - public long totalCount() { + public long getTotalCount() { return this.total; } @Override - public long getTotalCount() { - return totalCount(); - } - - @Override - public long otherCount() { + public long getOtherCount() { long other = total; for (Entry entry : entries) { - other -= entry.count(); + other -= entry.getCount(); } return other; } - @Override - public long getOtherCount() { - return otherCount(); - } - @Override public Facet reduce(List facets) { if (facets.size() == 1) { @@ -223,10 +167,10 @@ public class InternalLongTermsFacet extends InternalTermsFacet { long total = 0; for (Facet facet : facets) { InternalLongTermsFacet mFacet = (InternalLongTermsFacet) facet; - missing += mFacet.missingCount(); - total += mFacet.totalCount(); + missing += mFacet.getMissingCount(); + total += mFacet.getTotalCount(); for (LongEntry entry : mFacet.entries) { - aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); + aggregated.adjustOrPutValue(entry.term, entry.getCount(), entry.getCount()); } } @@ -256,16 +200,16 @@ public class InternalLongTermsFacet extends InternalTermsFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields.MISSING, missing); builder.field(Fields.TOTAL, total); - builder.field(Fields.OTHER, otherCount()); + builder.field(Fields.OTHER, getOtherCount()); builder.startArray(Fields.TERMS); for (LongEntry entry : entries) { builder.startObject(); builder.field(Fields.TERM, entry.term); - builder.field(Fields.COUNT, entry.count()); + builder.field(Fields.COUNT, entry.getCount()); builder.endObject(); } builder.endArray(); @@ -281,7 +225,7 @@ public class InternalLongTermsFacet extends InternalTermsFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); requiredSize = in.readVInt(); missing = in.readVLong(); @@ -296,7 +240,7 @@ public class InternalLongTermsFacet extends InternalTermsFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(requiredSize); out.writeVLong(missing); @@ -305,7 +249,7 @@ public class InternalLongTermsFacet extends InternalTermsFacet { out.writeVInt(entries.size()); for (LongEntry entry : entries) { out.writeLong(entry.term); - out.writeVInt(entry.count()); + out.writeVInt(entry.getCount()); } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/terms/longs/TermsLongFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/longs/TermsLongFacetExecutor.java similarity index 76% rename from src/main/java/org/elasticsearch/search/facet/terms/longs/TermsLongFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/longs/TermsLongFacetExecutor.java index 929ade5d3f6..248eced469b 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/longs/TermsLongFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/longs/TermsLongFacetExecutor.java @@ -32,8 +32,8 @@ import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.LongValues; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.support.EntryPriorityQueue; import org.elasticsearch.search.internal.SearchContext; @@ -45,36 +45,29 @@ import java.util.Set; /** * */ -public class TermsLongFacetCollector extends AbstractFacetCollector { +public class TermsLongFacetExecutor extends FacetExecutor { private final IndexNumericFieldData indexFieldData; - private final TermsFacet.ComparatorType comparatorType; - private final int size; - private final int numberOfShards; - - private LongValues values; - - private final StaticAggregatorValueProc aggregator; - private final SearchScript script; + private final ImmutableSet excluded; - public TermsLongFacetCollector(String facetName, IndexNumericFieldData indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, - ImmutableSet excluded, SearchScript script) { - super(facetName); + final TLongIntHashMap facets; + long missing; + long total; + + public TermsLongFacetExecutor(IndexNumericFieldData indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, + ImmutableSet excluded, SearchScript script) { this.indexFieldData = indexFieldData; this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); this.script = script; + this.excluded = excluded; - if (this.script == null && excluded.isEmpty()) { - aggregator = new StaticAggregatorValueProc(CacheRecycler.popLongIntMap()); - } else { - aggregator = new AggregatorValueProc(CacheRecycler.popLongIntMap(), excluded, this.script); - } + this.facets = CacheRecycler.popLongIntMap(); // TODO: we need to support this with the new field data.... // if (allTerms) { @@ -90,31 +83,20 @@ public class TermsLongFacetCollector extends AbstractFacetCollector { } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getLongValues(); - if (script != null) { - script.setNextReader(context); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, aggregator); - } - - @Override - public Facet facet() { - TLongIntHashMap facets = aggregator.facets(); + public InternalFacet buildFacet(String facetName) { if (facets.isEmpty()) { CacheRecycler.pushLongIntMap(facets); - return new InternalLongTermsFacet(facetName, comparatorType, size, ImmutableList.of(), aggregator.missing(), aggregator.total()); + return new InternalLongTermsFacet(facetName, comparatorType, size, ImmutableList.of(), missing, total); } else { if (size < EntryPriorityQueue.LIMIT) { EntryPriorityQueue ordered = new EntryPriorityQueue(size, comparatorType.comparator()); @@ -127,7 +109,7 @@ public class TermsLongFacetCollector extends AbstractFacetCollector { list[i] = (InternalLongTermsFacet.LongEntry) ordered.pop(); } CacheRecycler.pushLongIntMap(facets); - return new InternalLongTermsFacet(facetName, comparatorType, size, Arrays.asList(list), aggregator.missing(), aggregator.total()); + return new InternalLongTermsFacet(facetName, comparatorType, size, Arrays.asList(list), missing, total); } else { BoundedTreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size); for (TLongIntIterator it = facets.iterator(); it.hasNext(); ) { @@ -135,11 +117,51 @@ public class TermsLongFacetCollector extends AbstractFacetCollector { ordered.add(new InternalLongTermsFacet.LongEntry(it.key(), it.value())); } CacheRecycler.pushLongIntMap(facets); - return new InternalLongTermsFacet(facetName, comparatorType, size, ordered, aggregator.missing(), aggregator.total()); + return new InternalLongTermsFacet(facetName, comparatorType, size, ordered, missing, total); } } } + class Collector extends FacetExecutor.Collector { + + private final StaticAggregatorValueProc aggregator; + private LongValues values; + + public Collector() { + if (script == null && excluded.isEmpty()) { + aggregator = new StaticAggregatorValueProc(facets); + } else { + aggregator = new AggregatorValueProc(facets, excluded, script); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getLongValues(); + if (script != null) { + script.setNextReader(context); + } + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, aggregator); + } + + @Override + public void postCollection() { + TermsLongFacetExecutor.this.missing = aggregator.missing(); + TermsLongFacetExecutor.this.total = aggregator.total(); + } + } + public static class AggregatorValueProc extends StaticAggregatorValueProc { private final SearchScript script; diff --git a/src/main/java/org/elasticsearch/search/facet/terms/strings/FieldsTermsStringFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/strings/FieldsTermsStringFacetExecutor.java similarity index 72% rename from src/main/java/org/elasticsearch/search/facet/terms/strings/FieldsTermsStringFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/strings/FieldsTermsStringFacetExecutor.java index 641914745b1..e314e729ec2 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/strings/FieldsTermsStringFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/strings/FieldsTermsStringFacetExecutor.java @@ -33,9 +33,9 @@ import org.elasticsearch.index.fielddata.HashedBytesValues; import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; import org.elasticsearch.search.facet.FacetPhaseExecutionException; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.support.EntryPriorityQueue; import org.elasticsearch.search.internal.SearchContext; @@ -47,48 +47,42 @@ import java.util.regex.Pattern; /** * */ -public class FieldsTermsStringFacetCollector extends AbstractFacetCollector { +public class FieldsTermsStringFacetExecutor extends FacetExecutor { private final InternalStringTermsFacet.ComparatorType comparatorType; - private final int size; - private final int numberOfShards; - private final IndexFieldData[] indexFieldDatas; - private HashedBytesValues[] values; - - private final StaticAggregatorValueProc[] aggregators; - private final SearchScript script; + private final Pattern pattern; + private final ImmutableSet excluded; - public FieldsTermsStringFacetCollector(String facetName, String[] fieldsNames, int size, InternalStringTermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, - ImmutableSet excluded, Pattern pattern, SearchScript script) { - super(facetName); + TObjectIntHashMap facets; + long missing; + long total; + + + public FieldsTermsStringFacetExecutor(String facetName, String[] fieldsNames, int size, InternalStringTermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, + ImmutableSet excluded, Pattern pattern, SearchScript script) { this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); this.script = script; + this.excluded = excluded; + this.pattern = pattern; - indexFieldDatas = new IndexFieldData[fieldsNames.length]; - values = new HashedBytesValues[fieldsNames.length]; - aggregators = new StaticAggregatorValueProc[fieldsNames.length]; + facets = CacheRecycler.popObjectIntMap(); - TObjectIntHashMap map = CacheRecycler.popObjectIntMap(); + + this.indexFieldDatas = new IndexFieldData[fieldsNames.length]; for (int i = 0; i < fieldsNames.length; i++) { FieldMapper mapper = context.smartNameFieldMapper(fieldsNames[i]); if (mapper == null) { throw new FacetPhaseExecutionException(facetName, "failed to find mapping for [" + fieldsNames[i] + "]"); } indexFieldDatas[i] = context.fieldData().getForField(mapper); - if (excluded.isEmpty() && pattern == null && this.script == null) { - aggregators[i] = new StaticAggregatorValueProc(map); - } else { - aggregators[i] = new AggregatorValueProc(map, excluded, pattern, this.script); - } } - // TODO: we need to support this flag with the new field data... // if (allTerms) { // try { @@ -105,42 +99,20 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector { } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - for (int i = 0; i < indexFieldDatas.length; i++) { - values[i] = indexFieldDatas[i].load(context).getHashedBytesValues(); - aggregators[i].values = values[i]; - } - if (script != null) { - script.setNextReader(context); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - for (int i = 0; i < values.length; i++) { - values[i].forEachValueInDoc(doc, aggregators[i]); - } - } - - @Override - public Facet facet() { - TObjectIntHashMap facets = aggregators[0].facets(); // we share the map between all aggregators - long totalMissing = 0; - long total = 0; - for (StaticAggregatorValueProc aggregator : aggregators) { - totalMissing += aggregator.missing(); - total += aggregator.total(); - } + public InternalFacet buildFacet(String facetName) { if (facets.isEmpty()) { CacheRecycler.pushObjectIntMap(facets); - return new InternalStringTermsFacet(facetName, comparatorType, size, ImmutableList.of(), totalMissing, total); + return new InternalStringTermsFacet(facetName, comparatorType, size, ImmutableList.of(), missing, total); } else { if (size < EntryPriorityQueue.LIMIT) { EntryPriorityQueue ordered = new EntryPriorityQueue(size, comparatorType.comparator()); @@ -153,7 +125,7 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector { list[i] = ((InternalStringTermsFacet.TermEntry) ordered.pop()); } CacheRecycler.pushObjectIntMap(facets); - return new InternalStringTermsFacet(facetName, comparatorType, size, Arrays.asList(list), totalMissing, total); + return new InternalStringTermsFacet(facetName, comparatorType, size, Arrays.asList(list), missing, total); } else { BoundedTreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size); for (TObjectIntIterator it = facets.iterator(); it.hasNext(); ) { @@ -161,11 +133,66 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector { ordered.add(new InternalStringTermsFacet.TermEntry(it.key().bytes, it.value())); } CacheRecycler.pushObjectIntMap(facets); - return new InternalStringTermsFacet(facetName, comparatorType, size, ordered, totalMissing, total); + return new InternalStringTermsFacet(facetName, comparatorType, size, ordered, missing, total); } } } + class Collector extends FacetExecutor.Collector { + + private final StaticAggregatorValueProc[] aggregators; + private HashedBytesValues[] values; + + public Collector() { + values = new HashedBytesValues[indexFieldDatas.length]; + aggregators = new StaticAggregatorValueProc[indexFieldDatas.length]; + for (int i = 0; i < indexFieldDatas.length; i++) { + if (excluded.isEmpty() && pattern == null && script == null) { + aggregators[i] = new StaticAggregatorValueProc(facets); + } else { + aggregators[i] = new AggregatorValueProc(facets, excluded, pattern, script); + } + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + for (int i = 0; i < indexFieldDatas.length; i++) { + values[i] = indexFieldDatas[i].load(context).getHashedBytesValues(); + aggregators[i].values = values[i]; + } + if (script != null) { + script.setNextReader(context); + } + } + + @Override + public void collect(int doc) throws IOException { + for (int i = 0; i < values.length; i++) { + values[i].forEachValueInDoc(doc, aggregators[i]); + } + } + + @Override + public void postCollection() { + long missing = 0; + long total = 0; + for (StaticAggregatorValueProc aggregator : aggregators) { + missing += aggregator.missing(); + total += aggregator.total(); + } + FieldsTermsStringFacetExecutor.this.missing = missing; + FieldsTermsStringFacetExecutor.this.total = total; + } + } + public static class AggregatorValueProc extends StaticAggregatorValueProc { private final ImmutableSet excluded; diff --git a/src/main/java/org/elasticsearch/search/facet/terms/strings/InternalStringTermsFacet.java b/src/main/java/org/elasticsearch/search/facet/terms/strings/InternalStringTermsFacet.java index c98003ca554..491421d9a96 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/strings/InternalStringTermsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/strings/InternalStringTermsFacet.java @@ -86,38 +86,26 @@ public class InternalStringTermsFacet extends InternalTermsFacet { this.count = count; } - public Text term() { - return term; - } - + @Override public Text getTerm() { return term; } @Override - public Number termAsNumber() { - // LUCENE 4 UPGRADE: better way? + public Number getTermAsNumber() { return Double.parseDouble(term.string()); } @Override - public Number getTermAsNumber() { - return termAsNumber(); - } - - public int count() { - return count; - } - public int getCount() { - return count(); + return count; } @Override public int compareTo(Entry o) { - int i = this.term.compareTo(o.term()); + int i = this.term.compareTo(o.getTerm()); if (i == 0) { - i = count - o.count(); + i = count - o.getCount(); if (i == 0) { i = System.identityHashCode(this) - System.identityHashCode(o); } @@ -126,23 +114,17 @@ public class InternalStringTermsFacet extends InternalTermsFacet { } } - private String name; - int requiredSize; - long missing; - long total; - Collection entries = ImmutableList.of(); - ComparatorType comparatorType; InternalStringTermsFacet() { } public InternalStringTermsFacet(String name, ComparatorType comparatorType, int requiredSize, Collection entries, long missing, long total) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.requiredSize = requiredSize; this.entries = entries; @@ -151,38 +133,13 @@ public class InternalStringTermsFacet extends InternalTermsFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = ImmutableList.copyOf(entries); } return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @SuppressWarnings({"unchecked"}) @Override public Iterator iterator() { @@ -190,39 +147,24 @@ public class InternalStringTermsFacet extends InternalTermsFacet { } @Override - public long missingCount() { + public long getMissingCount() { return this.missing; } @Override - public long getMissingCount() { - return missingCount(); - } - - @Override - public long totalCount() { + public long getTotalCount() { return this.total; } @Override - public long getTotalCount() { - return totalCount(); - } - - @Override - public long otherCount() { + public long getOtherCount() { long other = total; for (Entry entry : entries) { - other -= entry.count(); + other -= entry.getCount(); } return other; } - @Override - public long getOtherCount() { - return otherCount(); - } - @Override public Facet reduce(List facets) { if (facets.size() == 1) { @@ -234,10 +176,10 @@ public class InternalStringTermsFacet extends InternalTermsFacet { long total = 0; for (Facet facet : facets) { InternalStringTermsFacet mFacet = (InternalStringTermsFacet) facet; - missing += mFacet.missingCount(); - total += mFacet.totalCount(); + missing += mFacet.getMissingCount(); + total += mFacet.getTotalCount(); for (TermEntry entry : mFacet.entries) { - aggregated.adjustOrPutValue(entry.term(), entry.count(), entry.count()); + aggregated.adjustOrPutValue(entry.getTerm(), entry.getCount(), entry.getCount()); } } @@ -267,16 +209,16 @@ public class InternalStringTermsFacet extends InternalTermsFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields.MISSING, missing); builder.field(Fields.TOTAL, total); - builder.field(Fields.OTHER, otherCount()); + builder.field(Fields.OTHER, getOtherCount()); builder.startArray(Fields.TERMS); for (Entry entry : entries) { builder.startObject(); - builder.field(Fields.TERM, entry.term()); - builder.field(Fields.COUNT, entry.count()); + builder.field(Fields.TERM, entry.getTerm()); + builder.field(Fields.COUNT, entry.getCount()); builder.endObject(); } builder.endArray(); @@ -292,7 +234,7 @@ public class InternalStringTermsFacet extends InternalTermsFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); requiredSize = in.readVInt(); missing = in.readVLong(); @@ -307,7 +249,7 @@ public class InternalStringTermsFacet extends InternalTermsFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(requiredSize); out.writeVLong(missing); @@ -315,8 +257,8 @@ public class InternalStringTermsFacet extends InternalTermsFacet { out.writeVInt(entries.size()); for (Entry entry : entries) { - out.writeText(entry.term()); - out.writeVInt(entry.count()); + out.writeText(entry.getTerm()); + out.writeVInt(entry.getCount()); } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/terms/strings/ScriptTermsStringFieldFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/strings/ScriptTermsStringFieldFacetExecutor.java similarity index 56% rename from src/main/java/org/elasticsearch/search/facet/terms/strings/ScriptTermsStringFieldFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/strings/ScriptTermsStringFieldFacetExecutor.java index c0fbbe6d403..c339a0862b9 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/strings/ScriptTermsStringFieldFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/strings/ScriptTermsStringFieldFacetExecutor.java @@ -29,8 +29,8 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.CacheRecycler; import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.support.EntryPriorityQueue; import org.elasticsearch.search.internal.SearchContext; @@ -43,28 +43,21 @@ import java.util.regex.Pattern; /** * */ -public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector { +public class ScriptTermsStringFieldFacetExecutor extends FacetExecutor { private final InternalStringTermsFacet.ComparatorType comparatorType; - private final int size; - + private final SearchScript script; + private final Matcher matcher; + private final ImmutableSet excluded; private final int numberOfShards; - private final SearchScript script; + final TObjectIntHashMap facets; + long missing; + long total; - private final Matcher matcher; - - private final ImmutableSet excluded; - - private final TObjectIntHashMap facets; - - private int missing; - private int total; - - public ScriptTermsStringFieldFacetCollector(String facetName, int size, InternalStringTermsFacet.ComparatorType comparatorType, SearchContext context, - ImmutableSet excluded, Pattern pattern, String scriptLang, String script, Map params) { - super(facetName); + public ScriptTermsStringFieldFacetExecutor(int size, InternalStringTermsFacet.ComparatorType comparatorType, SearchContext context, + ImmutableSet excluded, Pattern pattern, String scriptLang, String script, Map params) { this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); @@ -77,75 +70,17 @@ public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector } @Override - public void setScorer(Scorer scorer) throws IOException { - script.setScorer(scorer); + public Collector collector() { + return new Collector(matcher, excluded, script, facets); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - script.setNextReader(context); + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - script.setNextDocId(doc); - Object o = script.run(); - if (o == null) { - missing++; - return; - } - if (o instanceof Iterable) { - boolean found = false; - for (Object o1 : ((Iterable) o)) { - String value = o1.toString(); - if (match(value)) { - found = true; - // LUCENE 4 UPGRADE: should be possible to convert directly to BR - facets.adjustOrPutValue(new BytesRef(value), 1, 1); - total++; - } - } - if (!found) { - missing++; - } - } else if (o instanceof Object[]) { - boolean found = false; - for (Object o1 : ((Object[]) o)) { - String value = o1.toString(); - if (match(value)) { - found = true; - // LUCENE 4 UPGRADE: should be possible to convert directly to BR - facets.adjustOrPutValue(new BytesRef(value), 1, 1); - total++; - } - } - if (!found) { - missing++; - } - } else { - String value = o.toString(); - if (match(value)) { - // LUCENE 4 UPGRADE: should be possible to convert directly to BR - facets.adjustOrPutValue(new BytesRef(value), 1, 1); - total++; - } else { - missing++; - } - } - } - - private boolean match(String value) { - if (excluded != null && excluded.contains(new BytesRef(value))) { - return false; - } - if (matcher != null && !matcher.reset(value).matches()) { - return false; - } - return true; - } - - @Override - public Facet facet() { + public InternalFacet buildFacet(String facetName) { if (facets.isEmpty()) { CacheRecycler.pushObjectIntMap(facets); return new InternalStringTermsFacet(facetName, comparatorType, size, ImmutableList.of(), missing, total); @@ -173,4 +108,96 @@ public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector } } } + + class Collector extends FacetExecutor.Collector { + + private final Matcher matcher; + private final ImmutableSet excluded; + private final SearchScript script; + private final TObjectIntHashMap facets; + + long missing; + long total; + + Collector(Matcher matcher, ImmutableSet excluded, SearchScript script, TObjectIntHashMap facets) { + this.matcher = matcher; + this.excluded = excluded; + this.script = script; + this.facets = facets; + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + script.setScorer(scorer); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + script.setNextReader(context); + } + + @Override + public void collect(int doc) throws IOException { + script.setNextDocId(doc); + Object o = script.run(); + if (o == null) { + missing++; + return; + } + if (o instanceof Iterable) { + boolean found = false; + for (Object o1 : ((Iterable) o)) { + String value = o1.toString(); + if (match(value)) { + found = true; + // LUCENE 4 UPGRADE: should be possible to convert directly to BR + facets.adjustOrPutValue(new BytesRef(value), 1, 1); + total++; + } + } + if (!found) { + missing++; + } + } else if (o instanceof Object[]) { + boolean found = false; + for (Object o1 : ((Object[]) o)) { + String value = o1.toString(); + if (match(value)) { + found = true; + // LUCENE 4 UPGRADE: should be possible to convert directly to BR + facets.adjustOrPutValue(new BytesRef(value), 1, 1); + total++; + } + } + if (!found) { + missing++; + } + } else { + String value = o.toString(); + if (match(value)) { + // LUCENE 4 UPGRADE: should be possible to convert directly to BR + facets.adjustOrPutValue(new BytesRef(value), 1, 1); + total++; + } else { + missing++; + } + } + } + + @Override + public void postCollection() { + ScriptTermsStringFieldFacetExecutor.this.missing = missing; + ScriptTermsStringFieldFacetExecutor.this.total = missing; + } + + private boolean match(String value) { + if (excluded != null && excluded.contains(new BytesRef(value))) { + return false; + } + if (matcher != null && !matcher.reset(value).matches()) { + return false; + } + return true; + } + } } diff --git a/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringFacetExecutor.java similarity index 76% rename from src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringFacetExecutor.java index 7ca6c127eba..b958bedbc23 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringFacetExecutor.java @@ -32,8 +32,8 @@ import org.elasticsearch.common.lucene.HashedBytesRef; import org.elasticsearch.index.fielddata.HashedBytesValues; import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.support.EntryPriorityQueue; import org.elasticsearch.search.internal.SearchContext; @@ -46,36 +46,33 @@ import java.util.regex.Pattern; /** * */ -public class TermsStringFacetCollector extends AbstractFacetCollector { +public class TermsStringFacetExecutor extends FacetExecutor { private final IndexFieldData indexFieldData; - private final TermsFacet.ComparatorType comparatorType; - - private final int size; - - private final int numberOfShards; - - private HashedBytesValues values; - - private final StaticAggregatorValueProc aggregator; - + private final ImmutableSet excluded; + private final Pattern pattern; private final SearchScript script; - public TermsStringFacetCollector(String facetName, IndexFieldData indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, - ImmutableSet excluded, Pattern pattern, SearchScript script) { - super(facetName); + private final int size; + private final int numberOfShards; + + // the aggregation map + TObjectIntHashMap facets; + long missing; + long total; + + public TermsStringFacetExecutor(IndexFieldData indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, + ImmutableSet excluded, Pattern pattern, SearchScript script) { this.indexFieldData = indexFieldData; this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); this.script = script; + this.excluded = excluded; + this.pattern = pattern; - if (excluded.isEmpty() && pattern == null && this.script == null) { - aggregator = new StaticAggregatorValueProc(CacheRecycler.popObjectIntMap()); - } else { - aggregator = new AggregatorValueProc(CacheRecycler.popObjectIntMap(), excluded, pattern, this.script); - } + this.facets = CacheRecycler.popObjectIntMap(); if (allTerms) { // TODO: we need to support this back with the new field data! @@ -91,32 +88,20 @@ public class TermsStringFacetCollector extends AbstractFacetCollector { } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - values = indexFieldData.load(context).getHashedBytesValues(); - aggregator.values = values; - if (script != null) { - script.setNextReader(context); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - values.forEachValueInDoc(doc, aggregator); - } - - @Override - public Facet facet() { - TObjectIntHashMap facets = aggregator.facets(); + public InternalFacet buildFacet(String facetName) { if (facets.isEmpty()) { CacheRecycler.pushObjectIntMap(facets); - return new InternalStringTermsFacet(facetName, comparatorType, size, ImmutableList.of(), aggregator.missing(), aggregator.total()); + return new InternalStringTermsFacet(facetName, comparatorType, size, ImmutableList.of(), missing, total); } else { if (size < EntryPriorityQueue.LIMIT) { EntryPriorityQueue ordered = new EntryPriorityQueue(size, comparatorType.comparator()); @@ -129,7 +114,7 @@ public class TermsStringFacetCollector extends AbstractFacetCollector { list[i] = ((InternalStringTermsFacet.TermEntry) ordered.pop()); } CacheRecycler.pushObjectIntMap(facets); - return new InternalStringTermsFacet(facetName, comparatorType, size, Arrays.asList(list), aggregator.missing(), aggregator.total()); + return new InternalStringTermsFacet(facetName, comparatorType, size, Arrays.asList(list), missing, total); } else { BoundedTreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size); for (TObjectIntIterator it = facets.iterator(); it.hasNext(); ) { @@ -137,17 +122,56 @@ public class TermsStringFacetCollector extends AbstractFacetCollector { ordered.add(new InternalStringTermsFacet.TermEntry(it.key().bytes, it.value())); } CacheRecycler.pushObjectIntMap(facets); - return new InternalStringTermsFacet(facetName, comparatorType, size, ordered, aggregator.missing(), aggregator.total()); + return new InternalStringTermsFacet(facetName, comparatorType, size, ordered, missing, total); } } } + class Collector extends FacetExecutor.Collector { + + private final StaticAggregatorValueProc aggregator; + private HashedBytesValues values; + + Collector() { + if (excluded.isEmpty() && pattern == null && script == null) { + aggregator = new StaticAggregatorValueProc(facets); + } else { + aggregator = new AggregatorValueProc(facets, excluded, pattern, script); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + values = indexFieldData.load(context).getHashedBytesValues(); + aggregator.values = values; + if (script != null) { + script.setNextReader(context); + } + } + + @Override + public void collect(int doc) throws IOException { + values.forEachValueInDoc(doc, aggregator); + } + + @Override + public void postCollection() { + TermsStringFacetExecutor.this.missing = aggregator.missing(); + TermsStringFacetExecutor.this.total = aggregator.total(); + } + } + public static class AggregatorValueProc extends StaticAggregatorValueProc { private final ImmutableSet excluded; - private final Matcher matcher; - private final SearchScript script; public AggregatorValueProc(TObjectIntHashMap facets, ImmutableSet excluded, Pattern pattern, SearchScript script) { diff --git a/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringOrdinalsFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringOrdinalsFacetExecutor.java similarity index 79% rename from src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringOrdinalsFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringOrdinalsFacetExecutor.java index a272d20b510..ff3f3928f2f 100644 --- a/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringOrdinalsFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/terms/strings/TermsStringOrdinalsFacetExecutor.java @@ -28,8 +28,8 @@ import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.index.fielddata.BytesValues; import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.ordinals.Ordinals; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.support.EntryPriorityQueue; import org.elasticsearch.search.internal.SearchContext; @@ -44,34 +44,23 @@ import java.util.regex.Pattern; /** * */ -public class TermsStringOrdinalsFacetCollector extends AbstractFacetCollector { +public class TermsStringOrdinalsFacetExecutor extends FacetExecutor { private final IndexFieldData.WithOrdinals indexFieldData; private final TermsFacet.ComparatorType comparatorType; - private final int size; - private final int numberOfShards; - private final int minCount; + private final ImmutableSet excluded; + private final Matcher matcher; - private BytesValues.WithOrdinals values; - - private final List aggregators; - - private ReaderAggregator current; - + final List aggregators; long missing; long total; - private final ImmutableSet excluded; - - private final Matcher matcher; - - public TermsStringOrdinalsFacetCollector(String facetName, IndexFieldData.WithOrdinals indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, - ImmutableSet excluded, Pattern pattern) { - super(facetName); + public TermsStringOrdinalsFacetExecutor(IndexFieldData.WithOrdinals indexFieldData, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context, + ImmutableSet excluded, Pattern pattern) { this.indexFieldData = indexFieldData; this.size = size; this.comparatorType = comparatorType; @@ -95,34 +84,17 @@ public class TermsStringOrdinalsFacetCollector extends AbstractFacetCollector { } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - if (current != null) { - missing += current.counts[0]; - total += current.total - current.counts[0]; - if (current.values.ordinals().getNumOrds() > 0) { - aggregators.add(current); - } - } - values = indexFieldData.load(context).getBytesValues(); - current = new ReaderAggregator(values); + public Collector collector() { + return new Collector(); } @Override - protected void doCollect(int doc) throws IOException { - values.ordinals().forEachOrdinalInDoc(doc, current); + public Post post() { + return null; } @Override - public Facet facet() { - if (current != null) { - missing += current.counts[0]; - total += current.total - current.counts[0]; - // if we have values for this one, add it - if (current.values.ordinals().getNumOrds() > 0) { - aggregators.add(current); - } - } - + public InternalFacet buildFacet(String facetName) { AggregatorPriorityQueue queue = new AggregatorPriorityQueue(aggregators.size()); for (ReaderAggregator aggregator : aggregators) { @@ -213,6 +185,47 @@ public class TermsStringOrdinalsFacetCollector extends AbstractFacetCollector { return new InternalStringTermsFacet(facetName, comparatorType, size, ordered, missing, total); } + class Collector extends FacetExecutor.Collector { + + private long missing; + private long total; + private BytesValues.WithOrdinals values; + private ReaderAggregator current; + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + if (current != null) { + missing += current.counts[0]; + total += current.total - current.counts[0]; + if (current.values.ordinals().getNumOrds() > 0) { + aggregators.add(current); + } + } + values = indexFieldData.load(context).getBytesValues(); + current = new ReaderAggregator(values); + } + + @Override + public void collect(int doc) throws IOException { + values.ordinals().forEachOrdinalInDoc(doc, current); + } + + @Override + public void postCollection() { + if (current != null) { + missing += current.counts[0]; + total += current.total - current.counts[0]; + // if we have values for this one, add it + if (current.values.ordinals().getNumOrds() > 0) { + aggregators.add(current); + } + current = null; + } + TermsStringOrdinalsFacetExecutor.this.missing = missing; + TermsStringOrdinalsFacetExecutor.this.total = total; + } + } + public static class ReaderAggregator implements Ordinals.Docs.OrdinalInDocProc { final BytesValues.WithOrdinals values; diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/InternalTermsStatsFacet.java b/src/main/java/org/elasticsearch/search/facet/termsstats/InternalTermsStatsFacet.java index 6c8f020f075..81cf4fa5eea 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/InternalTermsStatsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/InternalTermsStatsFacet.java @@ -24,11 +24,23 @@ import org.elasticsearch.search.facet.termsstats.doubles.InternalTermsStatsDoubl import org.elasticsearch.search.facet.termsstats.longs.InternalTermsStatsLongFacet; import org.elasticsearch.search.facet.termsstats.strings.InternalTermsStatsStringFacet; -public abstract class InternalTermsStatsFacet implements TermsStatsFacet, InternalFacet { +public abstract class InternalTermsStatsFacet extends InternalFacet implements TermsStatsFacet { public static void registerStreams() { InternalTermsStatsStringFacet.registerStream(); InternalTermsStatsLongFacet.registerStream(); InternalTermsStatsDoubleFacet.registerStream(); } + + protected InternalTermsStatsFacet() { + } + + protected InternalTermsStatsFacet(String facetName) { + super(facetName); + } + + @Override + public final String getType() { + return TYPE; + } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java b/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java index 7eaad2f47e0..960f1667536 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java @@ -19,9 +19,7 @@ package org.elasticsearch.search.facet.termsstats; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticSearchIllegalArgumentException; -import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.text.Text; import org.elasticsearch.search.facet.Facet; @@ -33,21 +31,11 @@ public interface TermsStatsFacet extends Facet, Iterable public static final String TYPE = "terms_stats"; - /** - * The number of docs missing a value. - */ - long missingCount(); - /** * The number of docs missing a value. */ long getMissingCount(); - /** - * The terms and counts. - */ - List entries(); - /** * The terms and counts. */ @@ -74,7 +62,7 @@ public interface TermsStatsFacet extends Facet, Iterable if (o2 == null) { return -1; } - int i = (o2.count() < o1.count() ? -1 : (o1.count() == o2.count() ? 0 : 1)); + int i = (o2.getCount() < o1.getCount() ? -1 : (o1.getCount() == o2.getCount() ? 0 : 1)); if (i == 0) { i = o2.compareTo(o1); } @@ -162,7 +150,7 @@ public interface TermsStatsFacet extends Facet, Iterable if (o2 == null) { return -1; } - int i = -Double.compare(o1.total(), o2.total()); + int i = -Double.compare(o1.getTotal(), o2.getTotal()); if (i == 0) { i = COUNT.comparator().compare(o1, o2); } @@ -206,7 +194,7 @@ public interface TermsStatsFacet extends Facet, Iterable if (o2 == null) { return -1; } - int i = Double.compare(o1.min(), o2.min()); + int i = Double.compare(o1.getMin(), o2.getMin()); if (i == 0) { i = COUNT.comparator().compare(o1, o2); } @@ -248,7 +236,7 @@ public interface TermsStatsFacet extends Facet, Iterable if (o2 == null) { return -1; } - int i = -Double.compare(o1.max(), o2.max()); + int i = -Double.compare(o1.getMax(), o2.getMax()); if (i == 0) { i = COUNT.comparator().compare(o1, o2); } @@ -290,7 +278,7 @@ public interface TermsStatsFacet extends Facet, Iterable if (o2 == null) { return -1; } - int i = -Double.compare(o1.mean(), o2.mean()); + int i = -Double.compare(o1.getMean(), o2.getMean()); if (i == 0) { i = COUNT.comparator().compare(o1, o2); } @@ -358,7 +346,7 @@ public interface TermsStatsFacet extends Facet, Iterable } else if (id == MEAN.id()) { return MEAN; } else if (id == REVERSE_MEAN.id()) { - return REVERSE_MEAN; + return REVERSE_MEAN; } throw new ElasticSearchIllegalArgumentException("No type argument match for terms facet comparator [" + id + "]"); } @@ -395,36 +383,20 @@ public interface TermsStatsFacet extends Facet, Iterable public interface Entry extends Comparable { - Text term(); - Text getTerm(); - Number termAsNumber(); - Number getTermAsNumber(); - long count(); - long getCount(); - long totalCount(); - long getTotalCount(); - double min(); - double getMin(); - double max(); - double getMax(); - double total(); - double getTotal(); - double mean(); - double getMean(); } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetBuilder.java b/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetBuilder.java index 18a9b187fa7..628d1c83f5c 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetBuilder.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetBuilder.java @@ -22,7 +22,7 @@ package org.elasticsearch.search.facet.termsstats; import com.google.common.collect.Maps; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.builder.SearchSourceBuilderException; -import org.elasticsearch.search.facet.AbstractFacetBuilder; +import org.elasticsearch.search.facet.FacetBuilder; import java.io.IOException; import java.util.Map; @@ -30,7 +30,7 @@ import java.util.Map; /** * */ -public class TermsStatsFacetBuilder extends AbstractFacetBuilder { +public class TermsStatsFacetBuilder extends FacetBuilder { private String keyField; private String valueField; diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetProcessor.java b/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetParser.java similarity index 83% rename from src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetProcessor.java rename to src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetParser.java index f92315f9f59..02fee504c4d 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetProcessor.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacetParser.java @@ -27,21 +27,21 @@ import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.FacetCollector; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.FacetParser; import org.elasticsearch.search.facet.FacetPhaseExecutionException; -import org.elasticsearch.search.facet.FacetProcessor; -import org.elasticsearch.search.facet.termsstats.doubles.TermsStatsDoubleFacetCollector; -import org.elasticsearch.search.facet.termsstats.longs.TermsStatsLongFacetCollector; -import org.elasticsearch.search.facet.termsstats.strings.TermsStatsStringFacetCollector; +import org.elasticsearch.search.facet.termsstats.doubles.TermsStatsDoubleFacetExecutor; +import org.elasticsearch.search.facet.termsstats.longs.TermsStatsLongFacetExecutor; +import org.elasticsearch.search.facet.termsstats.strings.TermsStatsStringFacetExecutor; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; import java.util.Map; -public class TermsStatsFacetProcessor extends AbstractComponent implements FacetProcessor { +public class TermsStatsFacetParser extends AbstractComponent implements FacetParser { @Inject - public TermsStatsFacetProcessor(Settings settings) { + public TermsStatsFacetParser(Settings settings) { super(settings); InternalTermsStatsFacet.registerStreams(); } @@ -52,7 +52,17 @@ public class TermsStatsFacetProcessor extends AbstractComponent implements Facet } @Override - public FacetCollector parse(String facetName, XContentParser parser, SearchContext context) throws IOException { + public FacetExecutor.Mode defaultMainMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor.Mode defaultGlobalMode() { + return FacetExecutor.Mode.COLLECTOR; + } + + @Override + public FacetExecutor parse(String facetName, XContentParser parser, SearchContext context) throws IOException { String keyField = null; String valueField = null; int size = 10; @@ -119,11 +129,11 @@ public class TermsStatsFacetProcessor extends AbstractComponent implements Facet if (keyIndexFieldData instanceof IndexNumericFieldData) { IndexNumericFieldData keyIndexNumericFieldData = (IndexNumericFieldData) keyIndexFieldData; if (keyIndexNumericFieldData.getNumericType().isFloatingPoint()) { - return new TermsStatsDoubleFacetCollector(facetName, keyIndexNumericFieldData, valueIndexFieldData, valueScript, size, comparatorType, context); + return new TermsStatsDoubleFacetExecutor(keyIndexNumericFieldData, valueIndexFieldData, valueScript, size, comparatorType, context); } else { - return new TermsStatsLongFacetCollector(facetName, keyIndexNumericFieldData, valueIndexFieldData, valueScript, size, comparatorType, context); + return new TermsStatsLongFacetExecutor(keyIndexNumericFieldData, valueIndexFieldData, valueScript, size, comparatorType, context); } } - return new TermsStatsStringFacetCollector(facetName, keyIndexFieldData, valueIndexFieldData, valueScript, size, comparatorType, context); + return new TermsStatsStringFacetExecutor(keyIndexFieldData, valueIndexFieldData, valueScript, size, comparatorType, context); } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java b/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java index 723d278ee86..8087c5249d0 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java @@ -76,38 +76,18 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { } @Override - public Text term() { + public Text getTerm() { return new StringText(Double.toString(term)); } @Override - public Text getTerm() { - return term(); - } - - @Override - public Number termAsNumber() { + public Number getTermAsNumber() { return term; } - @Override - public Number getTermAsNumber() { - return termAsNumber(); - } - - @Override - public long count() { - return count; - } - @Override public long getCount() { - return count(); - } - - @Override - public long totalCount() { - return this.totalCount; + return count; } @Override @@ -116,48 +96,28 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { } @Override - public double min() { + public double getMin() { return this.min; } @Override - public double getMin() { - return min(); - } - - @Override - public double max() { + public double getMax() { return max; } @Override - public double getMax() { - return max(); - } - - @Override - public double total() { + public double getTotal() { return total; } @Override - public double getTotal() { - return total(); - } - - @Override - public double mean() { + public double getMean() { if (totalCount == 0) { return 0; } return total / totalCount; } - @Override - public double getMean() { - return mean(); - } - @Override public int compareTo(Entry o) { DoubleEntry other = (DoubleEntry) o; @@ -165,18 +125,13 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { } } - private String name; - int requiredSize; - long missing; - Collection entries = ImmutableList.of(); - ComparatorType comparatorType; public InternalTermsStatsDoubleFacet(String name, ComparatorType comparatorType, int requiredSize, Collection entries, long missing) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.requiredSize = requiredSize; this.entries = entries; @@ -184,27 +139,7 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = ImmutableList.copyOf(entries); } @@ -218,25 +153,15 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @SuppressWarnings({"unchecked"}) @Override public Iterator iterator() { return (Iterator) entries.iterator(); } - @Override - public long missingCount() { - return this.missing; - } - @Override public long getMissingCount() { - return missingCount(); + return this.missing; } @Override @@ -281,7 +206,7 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { DoubleEntry[] entries1 = map.values(new DoubleEntry[map.size()]); Arrays.sort(entries1, comparatorType.comparator()); CacheRecycler.pushDoubleObjectMap(map); - return new InternalTermsStatsDoubleFacet(name, comparatorType, requiredSize, Arrays.asList(entries1), missing); + return new InternalTermsStatsDoubleFacet(getName(), comparatorType, requiredSize, Arrays.asList(entries1), missing); } else { Object[] values = map.internalValues(); Arrays.sort(values, (Comparator) comparatorType.comparator()); @@ -294,7 +219,7 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { ordered.add(value); } CacheRecycler.pushDoubleObjectMap(map); - return new InternalTermsStatsDoubleFacet(name, comparatorType, requiredSize, ordered, missing); + return new InternalTermsStatsDoubleFacet(getName(), comparatorType, requiredSize, ordered, missing); } } @@ -313,19 +238,19 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, InternalTermsStatsFacet.TYPE); builder.field(Fields.MISSING, missing); builder.startArray(Fields.TERMS); for (Entry entry : entries) { builder.startObject(); builder.field(Fields.TERM, ((DoubleEntry) entry).term); - builder.field(Fields.COUNT, entry.count()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.COUNT, entry.getCount()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); @@ -341,7 +266,7 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); requiredSize = in.readVInt(); missing = in.readVLong(); @@ -355,7 +280,7 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(requiredSize); out.writeVLong(missing); @@ -363,11 +288,11 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { out.writeVInt(entries.size()); for (Entry entry : entries) { out.writeDouble(((DoubleEntry) entry).term); - out.writeVLong(entry.count()); - out.writeVLong(entry.totalCount()); - out.writeDouble(entry.total()); - out.writeDouble(entry.min()); - out.writeDouble(entry.max()); + out.writeVLong(entry.getCount()); + out.writeVLong(entry.getTotalCount()); + out.writeDouble(entry.getTotal()); + out.writeDouble(entry.getMin()); + out.writeDouble(entry.getMax()); } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetExecutor.java similarity index 66% rename from src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetExecutor.java index 248b2eec0ae..fad6b3cf78c 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetExecutor.java @@ -28,8 +28,8 @@ import org.elasticsearch.common.trove.ExtTDoubleObjectHashMap; import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.termsstats.TermsStatsFacet; import org.elasticsearch.search.internal.SearchContext; @@ -38,24 +38,22 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; -public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { +public class TermsStatsDoubleFacetExecutor extends FacetExecutor { private final TermsStatsFacet.ComparatorType comparatorType; - private final IndexNumericFieldData keyIndexFieldData; - private final IndexNumericFieldData valueIndexFieldData; - private final SearchScript script; + final IndexNumericFieldData keyIndexFieldData; + final IndexNumericFieldData valueIndexFieldData; + final SearchScript script; private final int size; private final int numberOfShards; - private final Aggregator aggregator; + final ExtTDoubleObjectHashMap entries; + long missing; - private DoubleValues keyValues; - - public TermsStatsDoubleFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, SearchScript script, - int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public TermsStatsDoubleFacetExecutor(IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, SearchScript script, + int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context) { this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); @@ -63,45 +61,29 @@ public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { this.valueIndexFieldData = valueIndexFieldData; this.script = script; - if (script == null) { - this.aggregator = new Aggregator(); - } else { - this.aggregator = new ScriptAggregator(this.script); - } + this.entries = CacheRecycler.popDoubleObjectMap(); } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getDoubleValues(); - if (script != null) { - script.setNextReader(context); - } else { - aggregator.valueFieldData = valueIndexFieldData.load(context).getDoubleValues(); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, aggregator); - } - - @Override - public Facet facet() { - if (aggregator.entries.isEmpty()) { - return new InternalTermsStatsDoubleFacet(facetName, comparatorType, size, ImmutableList.of(), aggregator.missing); + public InternalFacet buildFacet(String facetName) { + if (entries.isEmpty()) { + return new InternalTermsStatsDoubleFacet(facetName, comparatorType, size, ImmutableList.of(), missing); } if (size == 0) { // all terms // all terms, just return the collection, we will sort it on the way back - return new InternalTermsStatsDoubleFacet(facetName, comparatorType, 0 /* indicates all terms*/, aggregator.entries.valueCollection(), aggregator.missing); + return new InternalTermsStatsDoubleFacet(facetName, comparatorType, 0 /* indicates all terms*/, entries.valueCollection(), missing); } - Object[] values = aggregator.entries.internalValues(); + Object[] values = entries.internalValues(); Arrays.sort(values, (Comparator) comparatorType.comparator()); int limit = size; @@ -114,19 +96,62 @@ public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { ordered.add(value); } - CacheRecycler.pushDoubleObjectMap(aggregator.entries); - return new InternalTermsStatsDoubleFacet(facetName, comparatorType, size, ordered, aggregator.missing); + CacheRecycler.pushDoubleObjectMap(entries); + return new InternalTermsStatsDoubleFacet(facetName, comparatorType, size, ordered, missing); + } + + class Collector extends FacetExecutor.Collector { + + private final Aggregator aggregator; + private DoubleValues keyValues; + + public Collector() { + if (script == null) { + this.aggregator = new Aggregator(entries); + } else { + this.aggregator = new ScriptAggregator(entries, script); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getDoubleValues(); + if (script != null) { + script.setNextReader(context); + } else { + aggregator.valueFieldData = valueIndexFieldData.load(context).getDoubleValues(); + } + } + + @Override + public void collect(int doc) throws IOException { + keyValues.forEachValueInDoc(doc, aggregator); + } + + @Override + public void postCollection() { + TermsStatsDoubleFacetExecutor.this.missing = aggregator.missing; + } } public static class Aggregator implements DoubleValues.ValueInDocProc { - final ExtTDoubleObjectHashMap entries = CacheRecycler.popDoubleObjectMap(); + final ExtTDoubleObjectHashMap entries; int missing; - DoubleValues valueFieldData; - final ValueAggregator valueAggregator = new ValueAggregator(); + public Aggregator(ExtTDoubleObjectHashMap entries) { + this.entries = entries; + } + @Override public void onValue(int docId, double value) { InternalTermsStatsDoubleFacet.DoubleEntry doubleEntry = entries.get(value); @@ -170,7 +195,8 @@ public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { private final SearchScript script; - public ScriptAggregator(SearchScript script) { + public ScriptAggregator(ExtTDoubleObjectHashMap entries, SearchScript script) { + super(entries); this.script = script; } diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java b/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java index 53561a5307d..096c38e40cf 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java @@ -76,38 +76,18 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { } @Override - public Text term() { + public Text getTerm() { return new StringText(Long.toString(term)); } @Override - public Text getTerm() { - return term(); - } - - @Override - public Number termAsNumber() { + public Number getTermAsNumber() { return term; } - @Override - public Number getTermAsNumber() { - return termAsNumber(); - } - - @Override - public long count() { - return count; - } - @Override public long getCount() { - return count(); - } - - @Override - public long totalCount() { - return this.totalCount; + return count; } @Override @@ -116,48 +96,28 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { } @Override - public double min() { + public double getMin() { return this.min; } @Override - public double getMin() { - return min(); - } - - @Override - public double max() { + public double getMax() { return max; } @Override - public double getMax() { - return max(); - } - - @Override - public double total() { + public double getTotal() { return total; } @Override - public double getTotal() { - return total(); - } - - @Override - public double mean() { + public double getMean() { if (totalCount == 0) { return 0; } return total / totalCount; } - @Override - public double getMean() { - return mean(); - } - @Override public int compareTo(Entry o) { LongEntry other = (LongEntry) o; @@ -165,18 +125,13 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { } } - private String name; - int requiredSize; - long missing; - Collection entries = ImmutableList.of(); - ComparatorType comparatorType; public InternalTermsStatsLongFacet(String name, ComparatorType comparatorType, int requiredSize, Collection entries, long missing) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.requiredSize = requiredSize; this.entries = entries; @@ -184,27 +139,7 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = ImmutableList.copyOf(entries); } @@ -218,25 +153,15 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @SuppressWarnings({"unchecked"}) @Override public Iterator iterator() { return (Iterator) entries.iterator(); } - @Override - public long missingCount() { - return this.missing; - } - @Override public long getMissingCount() { - return missingCount(); + return this.missing; } @Override @@ -281,7 +206,7 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { LongEntry[] entries1 = map.values(new LongEntry[map.size()]); Arrays.sort(entries1, comparatorType.comparator()); CacheRecycler.pushLongObjectMap(map); - return new InternalTermsStatsLongFacet(name, comparatorType, requiredSize, Arrays.asList(entries1), missing); + return new InternalTermsStatsLongFacet(getName(), comparatorType, requiredSize, Arrays.asList(entries1), missing); } else { Object[] values = map.internalValues(); Arrays.sort(values, (Comparator) comparatorType.comparator()); @@ -294,7 +219,7 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { ordered.add(value); } CacheRecycler.pushLongObjectMap(map); - return new InternalTermsStatsLongFacet(name, comparatorType, requiredSize, ordered, missing); + return new InternalTermsStatsLongFacet(getName(), comparatorType, requiredSize, ordered, missing); } } @@ -313,19 +238,19 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, InternalTermsStatsFacet.TYPE); builder.field(Fields.MISSING, missing); builder.startArray(Fields.TERMS); for (Entry entry : entries) { builder.startObject(); builder.field(Fields.TERM, ((LongEntry) entry).term); - builder.field(Fields.COUNT, entry.count()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.COUNT, entry.getCount()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); @@ -341,7 +266,7 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); requiredSize = in.readVInt(); missing = in.readVLong(); @@ -355,7 +280,7 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(requiredSize); out.writeVLong(missing); @@ -363,11 +288,11 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { out.writeVInt(entries.size()); for (Entry entry : entries) { out.writeLong(((LongEntry) entry).term); - out.writeVLong(entry.count()); - out.writeVLong(entry.totalCount()); - out.writeDouble(entry.total()); - out.writeDouble(entry.min()); - out.writeDouble(entry.max()); + out.writeVLong(entry.getCount()); + out.writeVLong(entry.getTotalCount()); + out.writeDouble(entry.getTotal()); + out.writeDouble(entry.getMin()); + out.writeDouble(entry.getMax()); } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetExecutor.java similarity index 67% rename from src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetExecutor.java index 2dfab251d1b..c5088ff04a2 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetExecutor.java @@ -29,8 +29,8 @@ import org.elasticsearch.index.fielddata.DoubleValues; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.LongValues; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.termsstats.TermsStatsFacet; import org.elasticsearch.search.internal.SearchContext; @@ -39,24 +39,21 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; -public class TermsStatsLongFacetCollector extends AbstractFacetCollector { +public class TermsStatsLongFacetExecutor extends FacetExecutor { private final TermsStatsFacet.ComparatorType comparatorType; - - private final IndexNumericFieldData keyIndexFieldData; - private final IndexNumericFieldData valueIndexFieldData; - private final SearchScript script; + final IndexNumericFieldData keyIndexFieldData; + final IndexNumericFieldData valueIndexFieldData; + final SearchScript script; private final int size; private final int numberOfShards; - private final Aggregator aggregator; + final ExtTLongObjectHashMap entries; + long missing; - private LongValues keyValues; - - public TermsStatsLongFacetCollector(String facetName, IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, SearchScript script, - int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public TermsStatsLongFacetExecutor(IndexNumericFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, SearchScript script, + int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context) { this.size = size; this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); @@ -64,47 +61,31 @@ public class TermsStatsLongFacetCollector extends AbstractFacetCollector { this.valueIndexFieldData = valueIndexFieldData; this.script = script; - if (script == null) { - this.aggregator = new Aggregator(); - } else { - this.aggregator = new ScriptAggregator(this.script); - } + this.entries = CacheRecycler.popLongObjectMap(); } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getLongValues(); - if (script != null) { - script.setNextReader(context); - } else { - aggregator.valueValues = valueIndexFieldData.load(context).getDoubleValues(); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, aggregator); - } - - @Override - public Facet facet() { - if (aggregator.entries.isEmpty()) { - return new InternalTermsStatsLongFacet(facetName, comparatorType, size, ImmutableList.of(), aggregator.missing); + public InternalFacet buildFacet(String facetName) { + if (entries.isEmpty()) { + return new InternalTermsStatsLongFacet(facetName, comparatorType, size, ImmutableList.of(), missing); } if (size == 0) { // all terms // all terms, just return the collection, we will sort it on the way back - return new InternalTermsStatsLongFacet(facetName, comparatorType, 0 /* indicates all terms*/, aggregator.entries.valueCollection(), aggregator.missing); + return new InternalTermsStatsLongFacet(facetName, comparatorType, 0 /* indicates all terms*/, entries.valueCollection(), missing); } // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards - Object[] values = aggregator.entries.internalValues(); + Object[] values = entries.internalValues(); Arrays.sort(values, (Comparator) comparatorType.comparator()); int limit = size; @@ -116,20 +97,62 @@ public class TermsStatsLongFacetCollector extends AbstractFacetCollector { } ordered.add(value); } - CacheRecycler.pushLongObjectMap(aggregator.entries); - return new InternalTermsStatsLongFacet(facetName, comparatorType, size, ordered, aggregator.missing); + CacheRecycler.pushLongObjectMap(entries); + return new InternalTermsStatsLongFacet(facetName, comparatorType, size, ordered, missing); + } + + class Collector extends FacetExecutor.Collector { + + private final Aggregator aggregator; + private LongValues keyValues; + + public Collector() { + if (script == null) { + this.aggregator = new Aggregator(entries); + } else { + this.aggregator = new ScriptAggregator(entries, script); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getLongValues(); + if (script != null) { + script.setNextReader(context); + } else { + aggregator.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + } + } + + @Override + public void collect(int doc) throws IOException { + keyValues.forEachValueInDoc(doc, aggregator); + } + + @Override + public void postCollection() { + TermsStatsLongFacetExecutor.this.missing = aggregator.missing; + } } public static class Aggregator implements LongValues.ValueInDocProc { - final ExtTLongObjectHashMap entries = CacheRecycler.popLongObjectMap(); - + final ExtTLongObjectHashMap entries; int missing; - DoubleValues valueValues; - final ValueAggregator valueAggregator = new ValueAggregator(); + public Aggregator(ExtTLongObjectHashMap entries) { + this.entries = entries; + } + @Override public void onValue(int docId, long value) { InternalTermsStatsLongFacet.LongEntry longEntry = entries.get(value); @@ -173,7 +196,8 @@ public class TermsStatsLongFacetCollector extends AbstractFacetCollector { private final SearchScript script; - public ScriptAggregator(SearchScript script) { + public ScriptAggregator(ExtTLongObjectHashMap entries, SearchScript script) { + super(entries); this.script = script; } diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java b/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java index d7bc9636073..0cc8ce7dec2 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java @@ -82,38 +82,18 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { } @Override - public Text term() { + public Text getTerm() { return term; } @Override - public Text getTerm() { - return term(); - } - - @Override - public Number termAsNumber() { + public Number getTermAsNumber() { return Double.parseDouble(term.string()); } - @Override - public Number getTermAsNumber() { - return termAsNumber(); - } - - @Override - public long count() { - return count; - } - @Override public long getCount() { - return count(); - } - - @Override - public long totalCount() { - return this.totalCount; + return count; } @Override @@ -122,66 +102,41 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { } @Override - public double min() { + public double getMin() { return this.min; } @Override - public double getMin() { - return min(); - } - - @Override - public double max() { + public double getMax() { return this.max; } @Override - public double getMax() { - return max(); - } - - @Override - public double total() { + public double getTotal() { return total; } @Override - public double getTotal() { - return total(); - } - - @Override - public double mean() { + public double getMean() { if (totalCount == 0) { return 0; } return total / totalCount; } - @Override - public double getMean() { - return mean(); - } - @Override public int compareTo(Entry other) { - return term.compareTo(other.term()); + return term.compareTo(other.getTerm()); } } - private String name; - int requiredSize; - long missing; - Collection entries = ImmutableList.of(); - ComparatorType comparatorType; public InternalTermsStatsStringFacet(String name, ComparatorType comparatorType, int requiredSize, Collection entries, long missing) { - this.name = name; + super(name); this.comparatorType = comparatorType; this.requiredSize = requiredSize; this.entries = entries; @@ -189,27 +144,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { } @Override - public String name() { - return this.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String type() { - return TYPE; - } - - @Override - public String getType() { - return type(); - } - - @Override - public List entries() { + public List getEntries() { if (!(entries instanceof List)) { entries = ImmutableList.copyOf(entries); } @@ -223,25 +158,15 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { return (List) entries; } - @Override - public List getEntries() { - return entries(); - } - @SuppressWarnings({"unchecked"}) @Override public Iterator iterator() { return (Iterator) entries.iterator(); } - @Override - public long missingCount() { - return this.missing; - } - @Override public long getMissingCount() { - return missingCount(); + return this.missing; } @Override @@ -264,7 +189,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { missing += tsFacet.missing; for (Entry entry : tsFacet) { StringEntry stringEntry = (StringEntry) entry; - StringEntry current = map.get(stringEntry.term()); + StringEntry current = map.get(stringEntry.getTerm()); if (current != null) { current.count += stringEntry.count; current.totalCount += stringEntry.totalCount; @@ -276,7 +201,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { current.max = stringEntry.max; } } else { - map.put(stringEntry.term(), stringEntry); + map.put(stringEntry.getTerm(), stringEntry); } } } @@ -286,7 +211,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { StringEntry[] entries1 = map.values().toArray(new StringEntry[map.size()]); Arrays.sort(entries1, comparatorType.comparator()); CacheRecycler.pushHashMap(map); - return new InternalTermsStatsStringFacet(name, comparatorType, requiredSize, Arrays.asList(entries1), missing); + return new InternalTermsStatsStringFacet(getName(), comparatorType, requiredSize, Arrays.asList(entries1), missing); } else { Object[] values = map.internalValues(); Arrays.sort(values, (Comparator) comparatorType.comparator()); @@ -299,7 +224,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { ordered.add(value); } CacheRecycler.pushHashMap(map); - return new InternalTermsStatsStringFacet(name, comparatorType, requiredSize, ordered, missing); + return new InternalTermsStatsStringFacet(getName(), comparatorType, requiredSize, ordered, missing); } } @@ -318,19 +243,19 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(name); + builder.startObject(getName()); builder.field(Fields._TYPE, InternalTermsStatsFacet.TYPE); builder.field(Fields.MISSING, missing); builder.startArray(Fields.TERMS); for (Entry entry : entries) { builder.startObject(); - builder.field(Fields.TERM, entry.term()); - builder.field(Fields.COUNT, entry.count()); - builder.field(Fields.TOTAL_COUNT, entry.totalCount()); - builder.field(Fields.MIN, entry.min()); - builder.field(Fields.MAX, entry.max()); - builder.field(Fields.TOTAL, entry.total()); - builder.field(Fields.MEAN, entry.mean()); + builder.field(Fields.TERM, entry.getTerm()); + builder.field(Fields.COUNT, entry.getCount()); + builder.field(Fields.TOTAL_COUNT, entry.getTotalCount()); + builder.field(Fields.MIN, entry.getMin()); + builder.field(Fields.MAX, entry.getMax()); + builder.field(Fields.TOTAL, entry.getTotal()); + builder.field(Fields.MEAN, entry.getMean()); builder.endObject(); } builder.endArray(); @@ -346,7 +271,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { @Override public void readFrom(StreamInput in) throws IOException { - name = in.readString(); + super.readFrom(in); comparatorType = ComparatorType.fromId(in.readByte()); requiredSize = in.readVInt(); missing = in.readVLong(); @@ -360,19 +285,19 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(name); + super.writeTo(out); out.writeByte(comparatorType.id()); out.writeVInt(requiredSize); out.writeVLong(missing); out.writeVInt(entries.size()); for (Entry entry : entries) { - out.writeText(entry.term()); - out.writeVLong(entry.count()); - out.writeVLong(entry.totalCount()); - out.writeDouble(entry.total()); - out.writeDouble(entry.min()); - out.writeDouble(entry.max()); + out.writeText(entry.getTerm()); + out.writeVLong(entry.getCount()); + out.writeVLong(entry.getTotalCount()); + out.writeDouble(entry.getTotal()); + out.writeDouble(entry.getMin()); + out.writeDouble(entry.getMax()); } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java b/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetExecutor.java similarity index 67% rename from src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java rename to src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetExecutor.java index e75d8c5bb3f..f60a02365ec 100644 --- a/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java +++ b/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetExecutor.java @@ -31,8 +31,8 @@ import org.elasticsearch.index.fielddata.HashedBytesValues; import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.facet.AbstractFacetCollector; -import org.elasticsearch.search.facet.Facet; +import org.elasticsearch.search.facet.FacetExecutor; +import org.elasticsearch.search.facet.InternalFacet; import org.elasticsearch.search.facet.termsstats.TermsStatsFacet; import org.elasticsearch.search.internal.SearchContext; @@ -41,24 +41,21 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; -public class TermsStatsStringFacetCollector extends AbstractFacetCollector { +public class TermsStatsStringFacetExecutor extends FacetExecutor { private final TermsStatsFacet.ComparatorType comparatorType; - - private final IndexFieldData keyIndexFieldData; - private final IndexNumericFieldData valueIndexFieldData; - private final SearchScript script; + final IndexFieldData keyIndexFieldData; + final IndexNumericFieldData valueIndexFieldData; + final SearchScript script; private final int size; private final int numberOfShards; - private final Aggregator aggregator; + final ExtTHashMap entries; + long missing; - private HashedBytesValues keyValues; - - public TermsStatsStringFacetCollector(String facetName, IndexFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, SearchScript valueScript, - int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context) { - super(facetName); + public TermsStatsStringFacetExecutor(IndexFieldData keyIndexFieldData, IndexNumericFieldData valueIndexFieldData, SearchScript valueScript, + int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context) { this.keyIndexFieldData = keyIndexFieldData; this.valueIndexFieldData = valueIndexFieldData; this.script = valueScript; @@ -66,46 +63,29 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { this.comparatorType = comparatorType; this.numberOfShards = context.numberOfShards(); - if (script != null) { - this.aggregator = new ScriptAggregator(valueScript); - } else { - this.aggregator = new Aggregator(); - } + this.entries = CacheRecycler.popHashMap(); } @Override - public void setScorer(Scorer scorer) throws IOException { - if (script != null) { - script.setScorer(scorer); - } + public Collector collector() { + return new Collector(); } @Override - protected void doSetNextReader(AtomicReaderContext context) throws IOException { - keyValues = keyIndexFieldData.load(context).getHashedBytesValues(); - aggregator.keyValues = keyValues; - if (script != null) { - script.setNextReader(context); - } else { - aggregator.valueValues = valueIndexFieldData.load(context).getDoubleValues(); - } + public Post post() { + return null; } @Override - protected void doCollect(int doc) throws IOException { - keyValues.forEachValueInDoc(doc, aggregator); - } - - @Override - public Facet facet() { - if (aggregator.entries.isEmpty()) { - return new InternalTermsStatsStringFacet(facetName, comparatorType, size, ImmutableList.of(), aggregator.missing); + public InternalFacet buildFacet(String facetName) { + if (entries.isEmpty()) { + return new InternalTermsStatsStringFacet(facetName, comparatorType, size, ImmutableList.of(), missing); } if (size == 0) { // all terms // all terms, just return the collection, we will sort it on the way back - return new InternalTermsStatsStringFacet(facetName, comparatorType, 0 /* indicates all terms*/, aggregator.entries.values(), aggregator.missing); + return new InternalTermsStatsStringFacet(facetName, comparatorType, 0 /* indicates all terms*/, entries.values(), missing); } - Object[] values = aggregator.entries.internalValues(); + Object[] values = entries.internalValues(); Arrays.sort(values, (Comparator) comparatorType.comparator()); List ordered = Lists.newArrayList(); @@ -118,13 +98,55 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { ordered.add(value); } - CacheRecycler.pushHashMap(aggregator.entries); // fine to push here, we are done with it - return new InternalTermsStatsStringFacet(facetName, comparatorType, size, ordered, aggregator.missing); + CacheRecycler.pushHashMap(entries); // fine to push here, we are done with it + return new InternalTermsStatsStringFacet(facetName, comparatorType, size, ordered, missing); + } + + class Collector extends FacetExecutor.Collector { + + private final Aggregator aggregator; + private HashedBytesValues keyValues; + + public Collector() { + if (script != null) { + this.aggregator = new ScriptAggregator(entries, script); + } else { + this.aggregator = new Aggregator(entries); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + if (script != null) { + script.setScorer(scorer); + } + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + keyValues = keyIndexFieldData.load(context).getHashedBytesValues(); + aggregator.keyValues = keyValues; + if (script != null) { + script.setNextReader(context); + } else { + aggregator.valueValues = valueIndexFieldData.load(context).getDoubleValues(); + } + } + + @Override + public void collect(int doc) throws IOException { + keyValues.forEachValueInDoc(doc, aggregator); + } + + @Override + public void postCollection() { + TermsStatsStringFacetExecutor.this.missing = aggregator.missing; + } } public static class Aggregator implements HashedBytesValues.ValueInDocProc { - final ExtTHashMap entries = CacheRecycler.popHashMap(); + final ExtTHashMap entries; int missing = 0; @@ -133,6 +155,10 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { ValueAggregator valueAggregator = new ValueAggregator(); + public Aggregator(ExtTHashMap entries) { + this.entries = entries; + } + @Override public void onValue(int docId, HashedBytesRef value) { InternalTermsStatsStringFacet.StringEntry stringEntry = entries.get(value); @@ -176,7 +202,8 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { public static class ScriptAggregator extends Aggregator { private final SearchScript script; - public ScriptAggregator(SearchScript script) { + public ScriptAggregator(ExtTHashMap entries, SearchScript script) { + super(entries); this.script = script; } diff --git a/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java b/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java index c60aac25114..0af8ef18bfd 100644 --- a/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java +++ b/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java @@ -26,6 +26,7 @@ import org.elasticsearch.common.lucene.MinimumScoreCollector; import org.elasticsearch.common.lucene.MultiCollector; import org.elasticsearch.common.lucene.search.AndFilter; import org.elasticsearch.common.lucene.search.FilteredCollector; +import org.elasticsearch.common.lucene.search.XCollector; import org.elasticsearch.common.lucene.search.XFilteredQuery; import org.elasticsearch.index.engine.Engine; import org.elasticsearch.search.dfs.CachedDfSource; @@ -53,18 +54,29 @@ public class ContextIndexSearcher extends IndexSearcher { private Stage currentState = Stage.NA; + private boolean enableMainDocIdSetCollector; + private DocIdSetCollector mainDocIdSetCollector; + public ContextIndexSearcher(SearchContext searchContext, Engine.Searcher searcher) { super(searcher.reader()); this.searchContext = searchContext; setSimilarity(searcher.searcher().getSimilarity()); } + public void release() { + if (mainDocIdSetCollector != null) { + mainDocIdSetCollector.release(); + } + } + public void dfSource(CachedDfSource dfSource) { this.dfSource = dfSource; } /** - * Adds a query level collector that runs at {@link Stage#MAIN_QUERY} + * Adds a query level collector that runs at {@link Stage#MAIN_QUERY}. Note, supports + * {@link org.elasticsearch.common.lucene.search.XCollector} allowing for a callback + * when collection is done. */ public void addMainQueryCollector(Collector collector) { if (queryCollectors == null) { @@ -73,6 +85,14 @@ public class ContextIndexSearcher extends IndexSearcher { queryCollectors.add(collector); } + public DocIdSetCollector mainDocIdSetCollector() { + return this.mainDocIdSetCollector; + } + + public void enableMainDocIdSetCollector() { + this.enableMainDocIdSetCollector = true; + } + public void inStage(Stage stage) { this.currentState = stage; } @@ -137,17 +157,21 @@ public class ContextIndexSearcher extends IndexSearcher { @Override public void search(List leaves, Weight weight, Collector collector) throws IOException { - if (searchContext.parsedFilter() != null && currentState == Stage.MAIN_QUERY) { - // this will only get applied to the actual search collector and not - // to any scoped collectors, also, it will only be applied to the main collector - // since that is where the filter should only work - collector = new FilteredCollector(collector, searchContext.parsedFilter()); - } if (searchContext.timeoutInMillis() != -1) { // TODO: change to use our own counter that uses the scheduler in ThreadPool collector = new TimeLimitingCollector(collector, TimeLimitingCollector.getGlobalCounter(), searchContext.timeoutInMillis()); } if (currentState == Stage.MAIN_QUERY) { + if (enableMainDocIdSetCollector) { + // TODO should we create a cache of segment->docIdSets so we won't create one each time? + collector = this.mainDocIdSetCollector = new DocIdSetCollector(searchContext.docSetCache(), collector); + } + if (searchContext.parsedFilter() != null) { + // this will only get applied to the actual search collector and not + // to any scoped collectors, also, it will only be applied to the main collector + // since that is where the filter should only work + collector = new FilteredCollector(collector, searchContext.parsedFilter()); + } if (queryCollectors != null && !queryCollectors.isEmpty()) { collector = new MultiCollector(collector, queryCollectors.toArray(new Collector[queryCollectors.size()])); } @@ -167,6 +191,19 @@ public class ContextIndexSearcher extends IndexSearcher { } else { super.search(leaves, weight, collector); } + if (currentState == Stage.MAIN_QUERY) { + if (enableMainDocIdSetCollector) { + enableMainDocIdSetCollector = false; + mainDocIdSetCollector.postCollection(); + } + if (queryCollectors != null && !queryCollectors.isEmpty()) { + for (Collector queryCollector : queryCollectors) { + if (queryCollector instanceof XCollector) { + ((XCollector) queryCollector).postCollection(); + } + } + } + } } @Override diff --git a/src/main/java/org/elasticsearch/search/internal/DocIdSetCollector.java b/src/main/java/org/elasticsearch/search/internal/DocIdSetCollector.java new file mode 100644 index 00000000000..dcec780486d --- /dev/null +++ b/src/main/java/org/elasticsearch/search/internal/DocIdSetCollector.java @@ -0,0 +1,110 @@ +/* + * Licensed to ElasticSearch and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. ElasticSearch licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.internal; + +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.Collector; +import org.apache.lucene.search.Scorer; +import org.apache.lucene.util.FixedBitSet; +import org.elasticsearch.common.lucene.docset.ContextDocIdSet; +import org.elasticsearch.common.lucene.search.XCollector; +import org.elasticsearch.index.cache.docset.DocSetCache; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + */ +public class DocIdSetCollector extends XCollector { + + private final DocSetCache docSetCache; + private final Collector collector; + + private final List docSets; + private boolean currentHasDocs; + private ContextDocIdSet currentContext; + private FixedBitSet currentSet; + + public DocIdSetCollector(DocSetCache docSetCache, Collector collector) { + this.docSetCache = docSetCache; + this.collector = collector; + this.docSets = new ArrayList(); + } + + public List docSets() { + return docSets; + } + + public void release() { + for (ContextDocIdSet docSet : docSets) { + docSetCache.release(docSet); + } + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + collector.setScorer(scorer); + } + + @Override + public void collect(int doc) throws IOException { + collector.collect(doc); + currentHasDocs = true; + currentSet.set(doc); + } + + @Override + public void setNextReader(AtomicReaderContext context) throws IOException { + collector.setNextReader(context); + if (currentContext != null) { + if (currentHasDocs) { + docSets.add(currentContext); + } else { + docSetCache.release(currentContext); + } + } + currentContext = docSetCache.obtain(context); + currentSet = (FixedBitSet) currentContext.docSet; + currentHasDocs = false; + } + + @Override + public void postCollection() { + if (collector instanceof XCollector) { + ((XCollector) collector).postCollection(); + } + if (currentContext != null) { + if (currentHasDocs) { + docSets.add(currentContext); + } else { + docSetCache.release(currentContext); + } + currentContext = null; + currentSet = null; + currentHasDocs = false; + } + } + + @Override + public boolean acceptsDocsOutOfOrder() { + return true; + } +} diff --git a/src/main/java/org/elasticsearch/search/internal/SearchContext.java b/src/main/java/org/elasticsearch/search/internal/SearchContext.java index bd3a7d9d695..a9004cc5800 100644 --- a/src/main/java/org/elasticsearch/search/internal/SearchContext.java +++ b/src/main/java/org/elasticsearch/search/internal/SearchContext.java @@ -34,6 +34,7 @@ import org.elasticsearch.common.lucene.search.XFilteredQuery; import org.elasticsearch.common.lucene.search.function.BoostScoreFunction; import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; import org.elasticsearch.index.analysis.AnalysisService; +import org.elasticsearch.index.cache.docset.DocSetCache; import org.elasticsearch.index.cache.filter.FilterCache; import org.elasticsearch.index.cache.id.IdCache; import org.elasticsearch.index.engine.Engine; @@ -167,7 +168,7 @@ public class SearchContext implements Releasable { private SearchContextHighlight highlight; private SuggestionSearchContext suggest; - + private RescoreSearchContext rescore; private SearchLookup searchLookup; @@ -212,6 +213,7 @@ public class SearchContext implements Releasable { rewrite.contextClear(); } } + searcher.release(); engineSearcher.release(); return true; } @@ -317,11 +319,11 @@ public class SearchContext implements Releasable { public void suggest(SuggestionSearchContext suggest) { this.suggest = suggest; } - + public RescoreSearchContext rescore() { return this.rescore; } - + public void rescore(RescoreSearchContext rescore) { this.rescore = rescore; } @@ -380,6 +382,10 @@ public class SearchContext implements Releasable { return indexService.cache().filter(); } + public DocSetCache docSetCache() { + return indexService.cache().docSet(); + } + public IndexFieldDataService fieldData() { return indexService.fieldData(); } diff --git a/src/test/java/org/elasticsearch/benchmark/search/facet/HistogramFacetSearchBenchmark.java b/src/test/java/org/elasticsearch/benchmark/search/facet/HistogramFacetSearchBenchmark.java index 4912a791d3e..45d4ccecef1 100644 --- a/src/test/java/org/elasticsearch/benchmark/search/facet/HistogramFacetSearchBenchmark.java +++ b/src/test/java/org/elasticsearch/benchmark/search/facet/HistogramFacetSearchBenchmark.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.SizeValue; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.node.Node; +import org.elasticsearch.search.facet.FacetBuilder; import java.util.Date; @@ -57,11 +58,10 @@ public class HistogramFacetSearchBenchmark { .build(); Node node1 = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "node1")).node(); - Node node2 = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "node2")).node(); - Node clientNode = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "client")).client(true).node(); + //Node clientNode = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "client")).client(true).node(); - Client client = clientNode.client(); + Client client = node1.client(); long COUNT = SizeValue.parseSizeValue("5m").singles(); int BATCH = 500; @@ -76,7 +76,9 @@ public class HistogramFacetSearchBenchmark { Thread.sleep(10000); try { - client.admin().indices().create(createIndexRequest("test")).actionGet(); + client.admin().indices().create(createIndexRequest("test").settings( + settingsBuilder().put("index.number_of_shards", 1).put("index.number_of_replicas", 0))) + .actionGet(); StopWatch stopWatch = new StopWatch().start(); @@ -147,19 +149,6 @@ public class HistogramFacetSearchBenchmark { } System.out.println("--> Histogram Facet (l_value) " + (totalQueryTime / QUERY_COUNT) + "ms"); - totalQueryTime = 0; - for (int j = 0; j < QUERY_COUNT; j++) { - SearchResponse searchResponse = client.prepareSearch() - .setQuery(matchAllQuery()) - .addFacet(histogramFacet("l_value").field("l_value").bounds(0, NUMBER_OF_TERMS + 1).interval(4)) - .execute().actionGet(); - if (searchResponse.hits().totalHits() != COUNT) { - System.err.println("--> mismatch on hits"); - } - totalQueryTime += searchResponse.tookInMillis(); - } - System.out.println("--> Histogram Facet + bounds (l_value) " + (totalQueryTime / QUERY_COUNT) + "ms"); - totalQueryTime = 0; for (int j = 0; j < QUERY_COUNT; j++) { SearchResponse searchResponse = client.prepareSearch() @@ -173,19 +162,6 @@ public class HistogramFacetSearchBenchmark { } System.out.println("--> Histogram Facet (l_value/l_value) " + (totalQueryTime / QUERY_COUNT) + "ms"); - totalQueryTime = 0; - for (int j = 0; j < QUERY_COUNT; j++) { - SearchResponse searchResponse = client.prepareSearch() - .setQuery(matchAllQuery()) - .addFacet(histogramFacet("l_value").field("l_value").valueField("l_value").bounds(0, NUMBER_OF_TERMS + 1).interval(4)) - .execute().actionGet(); - if (searchResponse.hits().totalHits() != COUNT) { - System.err.println("--> mismatch on hits"); - } - totalQueryTime += searchResponse.tookInMillis(); - } - System.out.println("--> Histogram Facet + bounds (l_value/l_value) " + (totalQueryTime / QUERY_COUNT) + "ms"); - totalQueryTime = 0; for (int j = 0; j < QUERY_COUNT; j++) { SearchResponse searchResponse = client.prepareSearch() @@ -217,18 +193,28 @@ public class HistogramFacetSearchBenchmark { for (int j = 0; j < QUERY_COUNT; j++) { SearchResponse searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) - .addFacet(dateHistogramFacet("date").field("date").interval("day")) + .addFacet(dateHistogramFacet("date").field("date").interval("day").mode(FacetBuilder.Mode.COLLECTOR)) .execute().actionGet(); if (searchResponse.hits().totalHits() != COUNT) { System.err.println("--> mismatch on hits"); } totalQueryTime += searchResponse.tookInMillis(); } - System.out.println("--> Date Histogram Facet (date) " + (totalQueryTime / QUERY_COUNT) + "ms"); + System.out.println("--> Date Histogram Facet (mode/collector) (date) " + (totalQueryTime / QUERY_COUNT) + "ms"); - clientNode.close(); + totalQueryTime = 0; + for (int j = 0; j < QUERY_COUNT; j++) { + SearchResponse searchResponse = client.prepareSearch() + .setQuery(matchAllQuery()) + .addFacet(dateHistogramFacet("date").field("date").interval("day").mode(FacetBuilder.Mode.POST)) + .execute().actionGet(); + if (searchResponse.hits().totalHits() != COUNT) { + System.err.println("--> mismatch on hits"); + } + totalQueryTime += searchResponse.tookInMillis(); + } + System.out.println("--> Date Histogram Facet (mode/post) (date) " + (totalQueryTime / QUERY_COUNT) + "ms"); node1.close(); - node2.close(); } } diff --git a/src/test/java/org/elasticsearch/benchmark/search/facet/QueryFilterFacetSearchBenchmark.java b/src/test/java/org/elasticsearch/benchmark/search/facet/QueryFilterFacetSearchBenchmark.java index 0cac33d19cd..0daa14b1dd8 100644 --- a/src/test/java/org/elasticsearch/benchmark/search/facet/QueryFilterFacetSearchBenchmark.java +++ b/src/test/java/org/elasticsearch/benchmark/search/facet/QueryFilterFacetSearchBenchmark.java @@ -32,6 +32,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.SizeValue; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.node.Node; +import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.facet.FacetBuilders; import static org.elasticsearch.client.Requests.createIndexRequest; @@ -61,11 +62,7 @@ public class QueryFilterFacetSearchBenchmark { .build(); Node node1 = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "node1")).node(); - Node node2 = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "node2")).node(); - - Node clientNode = nodeBuilder().settings(settingsBuilder().put(settings).put("name", "client")).client(true).node(); - - client = clientNode.client(); + client = node1.client(); long[] lValues = new long[NUMBER_OF_TERMS]; for (int i = 0; i < NUMBER_OF_TERMS; i++) { @@ -146,10 +143,21 @@ public class QueryFilterFacetSearchBenchmark { SearchResponse searchResponse = client.prepareSearch() .setSearchType(SearchType.COUNT) .setQuery(termQuery("l_value", lValues[0])) - .addFacet(FacetBuilders.queryFacet("query").query(termQuery("l_value", lValues[0])).global(true)) + .addFacet(FacetBuilders.queryFacet("query").query(termQuery("l_value", lValues[0])).global(true).mode(FacetBuilder.Mode.COLLECTOR)) .execute().actionGet(); totalQueryTime += searchResponse.tookInMillis(); } - System.out.println("--> Query facet first l_value (global) " + (totalQueryTime / QUERY_COUNT) + "ms"); + System.out.println("--> Query facet first l_value (global) (mode/collector) " + (totalQueryTime / QUERY_COUNT) + "ms"); + + totalQueryTime = 0; + for (int j = 0; j < QUERY_COUNT; j++) { + SearchResponse searchResponse = client.prepareSearch() + .setSearchType(SearchType.COUNT) + .setQuery(termQuery("l_value", lValues[0])) + .addFacet(FacetBuilders.queryFacet("query").query(termQuery("l_value", lValues[0])).global(true).mode(FacetBuilder.Mode.POST)) + .execute().actionGet(); + totalQueryTime += searchResponse.tookInMillis(); + } + System.out.println("--> Query facet first l_value (global) (mode/post) " + (totalQueryTime / QUERY_COUNT) + "ms"); } } \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/test/integration/nested/SimpleNestedTests.java b/src/test/java/org/elasticsearch/test/integration/nested/SimpleNestedTests.java index d68a6be32ae..45bd962d53c 100644 --- a/src/test/java/org/elasticsearch/test/integration/nested/SimpleNestedTests.java +++ b/src/test/java/org/elasticsearch/test/integration/nested/SimpleNestedTests.java @@ -423,42 +423,42 @@ public class SimpleNestedTests extends AbstractNodesTests { assertThat(searchResponse.hits().totalHits(), equalTo(2l)); TermsStatsFacet termsStatsFacet = searchResponse.facets().facet("facet1"); - assertThat(termsStatsFacet.entries().size(), equalTo(4)); - assertThat(termsStatsFacet.entries().get(0).term().string(), equalTo("blue")); - assertThat(termsStatsFacet.entries().get(0).count(), equalTo(3l)); - assertThat(termsStatsFacet.entries().get(0).total(), equalTo(8d)); - assertThat(termsStatsFacet.entries().get(1).term().string(), equalTo("yellow")); - assertThat(termsStatsFacet.entries().get(1).count(), equalTo(2l)); - assertThat(termsStatsFacet.entries().get(1).total(), equalTo(13d)); - assertThat(termsStatsFacet.entries().get(2).term().string(), equalTo("green")); - assertThat(termsStatsFacet.entries().get(2).count(), equalTo(2l)); - assertThat(termsStatsFacet.entries().get(2).total(), equalTo(14d)); - assertThat(termsStatsFacet.entries().get(3).term().string(), equalTo("red")); - assertThat(termsStatsFacet.entries().get(3).count(), equalTo(1l)); - assertThat(termsStatsFacet.entries().get(3).total(), equalTo(12d)); + assertThat(termsStatsFacet.getEntries().size(), equalTo(4)); + assertThat(termsStatsFacet.getEntries().get(0).getTerm().string(), equalTo("blue")); + assertThat(termsStatsFacet.getEntries().get(0).getCount(), equalTo(3l)); + assertThat(termsStatsFacet.getEntries().get(0).getTotal(), equalTo(8d)); + assertThat(termsStatsFacet.getEntries().get(1).getTerm().string(), equalTo("yellow")); + assertThat(termsStatsFacet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(termsStatsFacet.getEntries().get(1).getTotal(), equalTo(13d)); + assertThat(termsStatsFacet.getEntries().get(2).getTerm().string(), equalTo("green")); + assertThat(termsStatsFacet.getEntries().get(2).getCount(), equalTo(2l)); + assertThat(termsStatsFacet.getEntries().get(2).getTotal(), equalTo(14d)); + assertThat(termsStatsFacet.getEntries().get(3).getTerm().string(), equalTo("red")); + assertThat(termsStatsFacet.getEntries().get(3).getCount(), equalTo(1l)); + assertThat(termsStatsFacet.getEntries().get(3).getTotal(), equalTo(12d)); // test scope ones - searchResponse = client.prepareSearch("test") - .setQuery( - nestedQuery("nested1.nested2", termQuery("nested1.nested2.field2_1", "blue")) - ) - .addFacet( - FacetBuilders.termsStatsFacet("facet1") - .keyField("nested1.nested2.field2_1") - .valueField("nested1.nested2.field2_2") - .nested("nested1.nested2") - .facetFilter(nestedFilter("nested1.nested2", termQuery("nested1.nested2.field2_1", "blue")).join(false)) - ) - .execute().actionGet(); - - assertThat(Arrays.toString(searchResponse.shardFailures()), searchResponse.failedShards(), equalTo(0)); - assertThat(searchResponse.hits().totalHits(), equalTo(2l)); - - termsStatsFacet = searchResponse.facets().facet("facet1"); - assertThat(termsStatsFacet.entries().size(), equalTo(1)); - assertThat(termsStatsFacet.entries().get(0).term().string(), equalTo("blue")); - assertThat(termsStatsFacet.entries().get(0).count(), equalTo(3l)); - assertThat(termsStatsFacet.entries().get(0).total(), equalTo(8d)); +// searchResponse = client.prepareSearch("test") +// .setQuery( +// nestedQuery("nested1.nested2", termQuery("nested1.nested2.field2_1", "blue")) +// ) +// .addFacet( +// FacetBuilders.termsStatsFacet("facet1") +// .keyField("nested1.nested2.field2_1") +// .valueField("nested1.nested2.field2_2") +// .nested("nested1.nested2") +// .facetFilter(nestedFilter("nested1.nested2", termQuery("nested1.nested2.field2_1", "blue")).join(false)) +// ) +// .execute().actionGet(); +// +// assertThat(Arrays.toString(searchResponse.shardFailures()), searchResponse.failedShards(), equalTo(0)); +// assertThat(searchResponse.hits().totalHits(), equalTo(2l)); +// +// termsStatsFacet = searchResponse.facets().facet("facet1"); +// assertThat(termsStatsFacet.getEntries().size(), equalTo(1)); +// assertThat(termsStatsFacet.getEntries().get(0).getTerm().string(), equalTo("blue")); +// assertThat(termsStatsFacet.getEntries().get(0).getCount(), equalTo(3l)); +// assertThat(termsStatsFacet.getEntries().get(0).getTotal(), equalTo(8d)); } @Test diff --git a/src/test/java/org/elasticsearch/test/integration/search/basic/TransportTwoNodesSearchTests.java b/src/test/java/org/elasticsearch/test/integration/search/basic/TransportTwoNodesSearchTests.java index ccc6c4d7ade..944f0dc0d04 100644 --- a/src/test/java/org/elasticsearch/test/integration/search/basic/TransportTwoNodesSearchTests.java +++ b/src/test/java/org/elasticsearch/test/integration/search/basic/TransportTwoNodesSearchTests.java @@ -318,8 +318,8 @@ public class TransportTwoNodesSearchTests extends AbstractNodesTests { assertThat("Failures " + Arrays.toString(searchResponse.shardFailures()), searchResponse.shardFailures().length, equalTo(0)); assertThat(searchResponse.hits().totalHits(), equalTo(100l)); - assertThat(searchResponse.facets().facet(QueryFacet.class, "test1").count(), equalTo(1l)); - assertThat(searchResponse.facets().facet(QueryFacet.class, "all").count(), equalTo(100l)); + assertThat(searchResponse.facets().facet(QueryFacet.class, "test1").getCount(), equalTo(1l)); + assertThat(searchResponse.facets().facet(QueryFacet.class, "all").getCount(), equalTo(100l)); } @Test diff --git a/src/test/java/org/elasticsearch/test/integration/search/child/SimpleChildQuerySearchTests.java b/src/test/java/org/elasticsearch/test/integration/search/child/SimpleChildQuerySearchTests.java index 030b281d1df..c5762007698 100644 --- a/src/test/java/org/elasticsearch/test/integration/search/child/SimpleChildQuerySearchTests.java +++ b/src/test/java/org/elasticsearch/test/integration/search/child/SimpleChildQuerySearchTests.java @@ -599,11 +599,11 @@ public class SimpleChildQuerySearchTests extends AbstractNodesTests { assertThat(searchResponse.facets().facets().size(), equalTo(1)); TermsFacet termsFacet = searchResponse.facets().facet("facet1"); - assertThat(termsFacet.entries().size(), equalTo(2)); - assertThat(termsFacet.entries().get(0).term().string(), equalTo("red")); - assertThat(termsFacet.entries().get(0).count(), equalTo(2)); - assertThat(termsFacet.entries().get(1).term().string(), equalTo("yellow")); - assertThat(termsFacet.entries().get(1).count(), equalTo(1)); + assertThat(termsFacet.getEntries().size(), equalTo(2)); + assertThat(termsFacet.getEntries().get(0).getTerm().string(), equalTo("red")); + assertThat(termsFacet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(termsFacet.getEntries().get(1).getTerm().string(), equalTo("yellow")); + assertThat(termsFacet.getEntries().get(1).getCount(), equalTo(1)); } @Test diff --git a/src/test/java/org/elasticsearch/test/integration/search/facet/SimpleFacetsTests.java b/src/test/java/org/elasticsearch/test/integration/search/facet/SimpleFacetsTests.java index 9a93b6ae0c8..eb31bb20ef6 100644 --- a/src/test/java/org/elasticsearch/test/integration/search/facet/SimpleFacetsTests.java +++ b/src/test/java/org/elasticsearch/test/integration/search/facet/SimpleFacetsTests.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.facet.datehistogram.DateHistogramFacet; import org.elasticsearch.search.facet.filter.FilterFacet; import org.elasticsearch.search.facet.histogram.HistogramFacet; @@ -129,12 +130,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.hits().totalHits(), equalTo(2l)); assertThat(searchResponse.hits().hits().length, equalTo(0)); TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), anyOf(equalTo("green"), equalTo("blue"))); - assertThat(facet.entries().get(0).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("green"), equalTo("blue"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), anyOf(equalTo("green"), equalTo("blue"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("green"), equalTo("blue"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); } } @@ -169,12 +170,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.hits().hits().length, equalTo(2)); TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), anyOf(equalTo("green"), equalTo("blue"))); - assertThat(facet.entries().get(0).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("green"), equalTo("blue"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), anyOf(equalTo("green"), equalTo("blue"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("green"), equalTo("blue"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) @@ -184,12 +185,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.hits().hits().length, equalTo(1)); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), anyOf(equalTo("green"), equalTo("blue"))); - assertThat(facet.entries().get(0).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("green"), equalTo("blue"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), anyOf(equalTo("green"), equalTo("blue"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("green"), equalTo("blue"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); } } @@ -232,10 +233,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.hits().hits().length, equalTo(0)); TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); searchResponse = client.prepareSearch() .setSearchType(SearchType.QUERY_AND_FETCH) @@ -248,10 +249,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.hits().hits().length, equalTo(0)); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); } } @@ -291,12 +292,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("test1")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), equalTo("test2")); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("test1")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("test2")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); } try { @@ -336,11 +337,24 @@ public class SimpleFacetsTests extends AbstractNodesTests { .addFacet(filterFacet("facet1").filter(termFilter("stag", "111"))) .addFacet(filterFacet("facet2").filter(termFilter("tag", "xxx"))) .addFacet(filterFacet("facet3").filter(termFilter("tag", "yyy"))) + .addFacet(filterFacet("facet4").filter(termFilter("tag", "zzz"))) .execute().actionGet(); FilterFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.count(), equalTo(2l)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getCount(), equalTo(2l)); + + facet = searchResponse.facets().facet("facet2"); + assertThat(facet.getName(), equalTo("facet2")); + assertThat(facet.getCount(), equalTo(1l)); + + facet = searchResponse.facets().facet("facet3"); + assertThat(facet.getName(), equalTo("facet3")); + assertThat(facet.getCount(), equalTo(2l)); + + facet = searchResponse.facets().facet("facet4"); + assertThat(facet.getName(), equalTo("facet4")); + assertThat(facet.getCount(), equalTo(1l)); } } @@ -384,7 +398,7 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.missingCount(), equalTo(1l)); + assertThat(facet.getMissingCount(), equalTo(1l)); } } @@ -453,18 +467,18 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); + assertThat(facet.getName(), equalTo("facet1")); assertThat(facet.getTotalCount(), equalTo(2l)); assertThat(facet.getOtherCount(), equalTo(0l)); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); facet = searchResponse.facets().facet("facet2"); - assertThat(facet.name(), equalTo("facet2")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet2")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); // Numeric @@ -477,30 +491,30 @@ public class SimpleFacetsTests extends AbstractNodesTests { facet = searchResponse.facets().facet("facet1"); assertThat(facet, instanceOf(InternalLongTermsFacet.class)); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); facet = searchResponse.facets().facet("facet2"); assertThat(facet, instanceOf(InternalLongTermsFacet.class)); - assertThat(facet.name(), equalTo("facet2")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("2000")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("1000"), equalTo("3000"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); - assertThat(facet.entries().get(2).term().string(), anyOf(equalTo("1000"), equalTo("3000"))); - assertThat(facet.entries().get(2).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet2")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("2000")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("1000"), equalTo("3000"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(2).getTerm().string(), anyOf(equalTo("1000"), equalTo("3000"))); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); facet = searchResponse.facets().facet("facet3"); assertThat(facet, instanceOf(InternalLongTermsFacet.class)); - assertThat(facet.name(), equalTo("facet3")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("2000")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), equalTo("1000")); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet3")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("2000")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("1000")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); searchResponse = client.prepareSearch() .setQuery(termQuery("stag", "111")) @@ -510,21 +524,21 @@ public class SimpleFacetsTests extends AbstractNodesTests { facet = searchResponse.facets().facet("facet1"); assertThat(facet, instanceOf(InternalDoubleTermsFacet.class)); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111.1")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111.1")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); facet = searchResponse.facets().facet("facet2"); assertThat(facet, instanceOf(InternalDoubleTermsFacet.class)); - assertThat(facet.name(), equalTo("facet2")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("2000.1")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("1000.1"), equalTo("3000.1"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); - assertThat(facet.entries().get(2).term().string(), anyOf(equalTo("1000.1"), equalTo("3000.1"))); - assertThat(facet.entries().get(2).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet2")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("2000.1")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("1000.1"), equalTo("3000.1"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(2).getTerm().string(), anyOf(equalTo("1000.1"), equalTo("3000.1"))); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); searchResponse = client.prepareSearch() .setQuery(termQuery("stag", "111")) @@ -532,10 +546,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); searchResponse = client.prepareSearch() .setQuery(termQuery("stag", "111")) @@ -543,10 +557,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); searchResponse = client.prepareSearch() .setQuery(termQuery("stag", "111")) @@ -554,10 +568,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); // Test Facet Filter @@ -567,10 +581,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); // now with global searchResponse = client.prepareSearch() @@ -579,10 +593,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); // Test Facet Filter (with a type) @@ -592,10 +606,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) @@ -603,14 +617,14 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); - assertThat(facet.entries().get(2).term().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); - assertThat(facet.entries().get(2).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(2).getTerm().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); // Bounded Size @@ -620,12 +634,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); // Test Exclude @@ -635,12 +649,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); - assertThat(facet.entries().get(0).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("xxx"), equalTo("zzz"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); // Test Order @@ -650,14 +664,14 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(2)); - assertThat(facet.entries().get(2).term().string(), equalTo("zzz")); - assertThat(facet.entries().get(2).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(2).getTerm().string(), equalTo("zzz")); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) @@ -665,14 +679,14 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(2).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(2).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("zzz")); - assertThat(facet.entries().get(0).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(2).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("zzz")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); // Script @@ -682,14 +696,14 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxxa")); - assertThat(facet.entries().get(0).count(), equalTo(1)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyya")); - assertThat(facet.entries().get(1).count(), equalTo(2)); - assertThat(facet.entries().get(2).term().string(), equalTo("zzza")); - assertThat(facet.entries().get(2).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxxa")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyya")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(2).getTerm().string(), equalTo("zzza")); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) @@ -697,12 +711,12 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), equalTo("zzz")); - assertThat(facet.entries().get(1).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("zzz")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1)); // Fields Facets @@ -712,16 +726,16 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(4)); - assertThat(facet.entries().get(0).term().string(), anyOf(equalTo("111"), equalTo("yyy"))); - assertThat(facet.entries().get(0).count(), equalTo(2)); - assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("111"), equalTo("yyy"))); - assertThat(facet.entries().get(1).count(), equalTo(2)); - assertThat(facet.entries().get(2).term().string(), anyOf(equalTo("zzz"), equalTo("xxx"))); - assertThat(facet.entries().get(2).count(), equalTo(1)); - assertThat(facet.entries().get(3).term().string(), anyOf(equalTo("zzz"), equalTo("xxx"))); - assertThat(facet.entries().get(3).count(), equalTo(1)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(4)); + assertThat(facet.getEntries().get(0).getTerm().string(), anyOf(equalTo("111"), equalTo("yyy"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("111"), equalTo("yyy"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2)); + assertThat(facet.getEntries().get(2).getTerm().string(), anyOf(equalTo("zzz"), equalTo("xxx"))); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1)); + assertThat(facet.getEntries().get(3).getTerm().string(), anyOf(equalTo("zzz"), equalTo("xxx"))); + assertThat(facet.getEntries().get(3).getCount(), equalTo(1)); // TODO: support allTerms with the new field data // searchResponse = client.prepareSearch() @@ -730,14 +744,14 @@ public class SimpleFacetsTests extends AbstractNodesTests { // .execute().actionGet(); // // facet = searchResponse.facets().facet("facet1"); -// assertThat(facet.name(), equalTo("facet1")); -// assertThat(facet.entries().size(), equalTo(3)); -// assertThat(facet.entries().get(0).term().string(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz"))); -// assertThat(facet.entries().get(0).count(), equalTo(0)); -// assertThat(facet.entries().get(1).term().string(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz"))); -// assertThat(facet.entries().get(1).count(), equalTo(0)); -// assertThat(facet.entries().get(2).term().string(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz"))); -// assertThat(facet.entries().get(2).count(), equalTo(0)); +// assertThat(facet.getName(), equalTo("facet1")); +// assertThat(facet.getEntries().size(), equalTo(3)); +// assertThat(facet.getEntries().get(0).getTerm().string(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz"))); +// assertThat(facet.getEntries().get(0).getCount(), equalTo(0)); +// assertThat(facet.getEntries().get(1).getTerm().string(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz"))); +// assertThat(facet.getEntries().get(1).getCount(), equalTo(0)); +// assertThat(facet.getEntries().get(2).getTerm().string(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz"))); +// assertThat(facet.getEntries().get(2).getCount(), equalTo(0)); // Script Field @@ -748,16 +762,16 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).term().string(), equalTo("111")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("111")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); facet = searchResponse.facets().facet("facet2"); - assertThat(facet.name(), equalTo("facet2")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(2)); + assertThat(facet.getName(), equalTo("facet2")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2)); } } @@ -799,11 +813,11 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); TermsFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(3)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(3)); for (int j = 0; j < 3; j++) { - assertThat(facet.entries().get(j).term().string(), anyOf(equalTo("foo"), equalTo("bar"), equalTo("baz"))); - assertThat(facet.entries().get(j).count(), equalTo(10)); + assertThat(facet.getEntries().get(j).getTerm().string(), anyOf(equalTo("foo"), equalTo("bar"), equalTo("baz"))); + assertThat(facet.getEntries().get(j).getCount(), equalTo(10)); } } } @@ -854,30 +868,30 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.failedShards(), equalTo(0)); StatisticalFacet facet = searchResponse.facets().facet("stats1"); - assertThat(facet.name(), equalTo(facet.name())); - assertThat(facet.count(), equalTo(2l)); - assertThat(facet.total(), equalTo(3d)); - assertThat(facet.min(), equalTo(1d)); - assertThat(facet.max(), equalTo(2d)); - assertThat(facet.mean(), equalTo(1.5d)); - assertThat(facet.sumOfSquares(), equalTo(5d)); + assertThat(facet.getName(), equalTo(facet.getName())); + assertThat(facet.getCount(), equalTo(2l)); + assertThat(facet.getTotal(), equalTo(3d)); + assertThat(facet.getMin(), equalTo(1d)); + assertThat(facet.getMax(), equalTo(2d)); + assertThat(facet.getMean(), equalTo(1.5d)); + assertThat(facet.getSumOfSquares(), equalTo(5d)); facet = searchResponse.facets().facet("stats2"); - assertThat(facet.name(), equalTo(facet.name())); - assertThat(facet.count(), equalTo(4l)); - assertThat(facet.total(), equalTo(10d)); - assertThat(facet.min(), equalTo(1d)); - assertThat(facet.max(), equalTo(4d)); - assertThat(facet.mean(), equalTo(2.5d)); + assertThat(facet.getName(), equalTo(facet.getName())); + assertThat(facet.getCount(), equalTo(4l)); + assertThat(facet.getTotal(), equalTo(10d)); + assertThat(facet.getMin(), equalTo(1d)); + assertThat(facet.getMax(), equalTo(4d)); + assertThat(facet.getMean(), equalTo(2.5d)); facet = searchResponse.facets().facet("stats3"); - assertThat(facet.name(), equalTo(facet.name())); - assertThat(facet.count(), equalTo(2l)); - assertThat(facet.total(), equalTo(6d)); - assertThat(facet.min(), equalTo(2d)); - assertThat(facet.max(), equalTo(4d)); - assertThat(facet.mean(), equalTo(3d)); - assertThat(facet.sumOfSquares(), equalTo(20d)); + assertThat(facet.getName(), equalTo(facet.getName())); + assertThat(facet.getCount(), equalTo(2l)); + assertThat(facet.getTotal(), equalTo(6d)); + assertThat(facet.getMin(), equalTo(2d)); + assertThat(facet.getMax(), equalTo(4d)); + assertThat(facet.getMean(), equalTo(3d)); + assertThat(facet.getSumOfSquares(), equalTo(20d)); // test multi field facet searchResponse = client.prepareSearch() @@ -887,13 +901,13 @@ public class SimpleFacetsTests extends AbstractNodesTests { facet = searchResponse.facets().facet("stats"); - assertThat(facet.name(), equalTo(facet.name())); - assertThat(facet.count(), equalTo(6l)); - assertThat(facet.total(), equalTo(13d)); - assertThat(facet.min(), equalTo(1d)); - assertThat(facet.max(), equalTo(4d)); - assertThat(facet.mean(), equalTo(13d / 6d)); - assertThat(facet.sumOfSquares(), equalTo(35d)); + assertThat(facet.getName(), equalTo(facet.getName())); + assertThat(facet.getCount(), equalTo(6l)); + assertThat(facet.getTotal(), equalTo(13d)); + assertThat(facet.getMin(), equalTo(1d)); + assertThat(facet.getMax(), equalTo(4d)); + assertThat(facet.getMean(), equalTo(13d / 6d)); + assertThat(facet.getSumOfSquares(), equalTo(35d)); // test cross field facet using the same facet name... searchResponse = client.prepareSearch() @@ -904,13 +918,13 @@ public class SimpleFacetsTests extends AbstractNodesTests { facet = searchResponse.facets().facet("stats"); - assertThat(facet.name(), equalTo(facet.name())); - assertThat(facet.count(), equalTo(6l)); - assertThat(facet.total(), equalTo(13d)); - assertThat(facet.min(), equalTo(1d)); - assertThat(facet.max(), equalTo(4d)); - assertThat(facet.mean(), equalTo(13d / 6d)); - assertThat(facet.sumOfSquares(), equalTo(35d)); + assertThat(facet.getName(), equalTo(facet.getName())); + assertThat(facet.getCount(), equalTo(6l)); + assertThat(facet.getTotal(), equalTo(13d)); + assertThat(facet.getMin(), equalTo(1d)); + assertThat(facet.getMax(), equalTo(4d)); + assertThat(facet.getMean(), equalTo(13d / 6d)); + assertThat(facet.getSumOfSquares(), equalTo(35d)); } } @@ -953,14 +967,14 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.failedShards(), equalTo(0)); HistogramFacet facet = searchResponse.facets().facet("facet1"); - assertThat(facet.name(), equalTo("facet1")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).key(), equalTo(100l)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(1).key(), equalTo(200l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(2).key(), equalTo(300l)); - assertThat(facet.entries().get(2).count(), equalTo(1l)); + assertThat(facet.getName(), equalTo("facet1")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(100l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(200l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getKey(), equalTo(300l)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); } } @@ -1012,12 +1026,6 @@ public class SimpleFacetsTests extends AbstractNodesTests { .addFacet(histogramScriptFacet("stats6").keyField("num").valueScript("doc['num'].value").interval(100)) .addFacet(histogramFacet("stats7").field("num").interval(100)) .addFacet(histogramScriptFacet("stats8").keyField("num").valueScript("doc.score").interval(100)) - .addFacet(histogramFacet("stats9").field("num").bounds(1000, 1200).interval(100)) - .addFacet(histogramFacet("stats10").field("num").bounds(1000, 1300).interval(100)) // for bounded, we also get 0s - .addFacet(histogramFacet("stats11").field("num").valueField("num").bounds(1000, 1300).interval(100)) // for bounded, we also get 0s - .addFacet(histogramScriptFacet("stats12").keyField("num").valueScript("doc['num'].value").bounds(1000, 1300).interval(100)) // for bounded, we also get 0s - .addFacet(histogramFacet("stats13").field("num").bounds(1056, 1176).interval(100)) - .addFacet(histogramFacet("stats14").field("num").valueField("num").bounds(1056, 1176).interval(100)) .execute().actionGet(); if (searchResponse.failedShards() > 0) { @@ -1031,189 +1039,114 @@ public class SimpleFacetsTests extends AbstractNodesTests { HistogramFacet facet; facet = searchResponse.facets().facet("stats1"); - assertThat(facet.name(), equalTo("stats1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(1055d, 0.000001)); - assertThat(facet.entries().get(0).max(), closeTo(1065d, 0.000001)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(2120d)); - assertThat(facet.entries().get(0).mean(), equalTo(1060d)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(1175d, 0.000001)); - assertThat(facet.entries().get(1).max(), closeTo(1175d, 0.000001)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1175d)); - assertThat(facet.entries().get(1).mean(), equalTo(1175d)); + assertThat(facet.getName(), equalTo("stats1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(1000l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(1055d, 0.000001)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(1065d, 0.000001)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(2120d)); + assertThat(facet.getEntries().get(0).getMean(), equalTo(1060d)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(1100l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(1175d, 0.000001)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(1175d, 0.000001)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(1175d)); + assertThat(facet.getEntries().get(1).getMean(), equalTo(1175d)); facet = searchResponse.facets().facet("stats2"); - assertThat(facet.name(), equalTo("stats2")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).key(), equalTo(10l)); - assertThat(facet.entries().get(0).count(), equalTo(3l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(3l)); - assertThat(facet.entries().get(0).total(), equalTo(45d)); - assertThat(facet.entries().get(0).mean(), equalTo(15d)); - assertThat(facet.entries().get(1).key(), equalTo(20l)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), equalTo(48d)); - assertThat(facet.entries().get(1).mean(), equalTo(24d)); - assertThat(facet.entries().get(2).key(), equalTo(30l)); - assertThat(facet.entries().get(2).count(), equalTo(1l)); - assertThat(facet.entries().get(2).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(2).total(), equalTo(31d)); - assertThat(facet.entries().get(2).mean(), equalTo(31d)); + assertThat(facet.getName(), equalTo("stats2")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(10l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(3l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(3l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(45d)); + assertThat(facet.getEntries().get(0).getMean(), equalTo(15d)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(20l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(48d)); + assertThat(facet.getEntries().get(1).getMean(), equalTo(24d)); + assertThat(facet.getEntries().get(2).getKey(), equalTo(30l)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotal(), equalTo(31d)); + assertThat(facet.getEntries().get(2).getMean(), equalTo(31d)); facet = searchResponse.facets().facet("stats3"); - assertThat(facet.name(), equalTo("stats3")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(4l)); - assertThat(facet.entries().get(0).total(), equalTo(82d)); - assertThat(facet.entries().get(0).mean(), equalTo(20.5d)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), equalTo(42d)); - assertThat(facet.entries().get(1).mean(), equalTo(21d)); + assertThat(facet.getName(), equalTo("stats3")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(1000l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(4l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(82d)); + assertThat(facet.getEntries().get(0).getMean(), equalTo(20.5d)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(1100l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(42d)); + assertThat(facet.getEntries().get(1).getMean(), equalTo(21d)); facet = searchResponse.facets().facet("stats4"); - assertThat(facet.name(), equalTo("stats4")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(0l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(2120d)); - assertThat(facet.entries().get(0).mean(), equalTo(1060d)); - assertThat(facet.entries().get(1).key(), equalTo(2l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1175d)); - assertThat(facet.entries().get(1).mean(), equalTo(1175d)); + assertThat(facet.getName(), equalTo("stats4")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(0l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(2120d)); + assertThat(facet.getEntries().get(0).getMean(), equalTo(1060d)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(1175d)); + assertThat(facet.getEntries().get(1).getMean(), equalTo(1175d)); facet = searchResponse.facets().facet("stats5"); - assertThat(facet.name(), equalTo("stats5")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(0l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(1).key(), equalTo(TimeValue.timeValueMinutes(2).millis())); - assertThat(facet.entries().get(1).count(), equalTo(1l)); + assertThat(facet.getName(), equalTo("stats5")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(0l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(TimeValue.timeValueMinutes(2).millis())); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); facet = searchResponse.facets().facet("stats6"); - assertThat(facet.name(), equalTo("stats6")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(2120d)); - assertThat(facet.entries().get(0).mean(), equalTo(1060d)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1175d)); - assertThat(facet.entries().get(1).mean(), equalTo(1175d)); + assertThat(facet.getName(), equalTo("stats6")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(1000l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(2120d)); + assertThat(facet.getEntries().get(0).getMean(), equalTo(1060d)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(1100l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(1175d)); + assertThat(facet.getEntries().get(1).getMean(), equalTo(1175d)); facet = searchResponse.facets().facet("stats7"); - assertThat(facet.name(), equalTo("stats7")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); + assertThat(facet.getName(), equalTo("stats7")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(1000l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(1100l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); facet = searchResponse.facets().facet("stats8"); - assertThat(facet.name(), equalTo("stats8")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(2d)); - assertThat(facet.entries().get(0).mean(), equalTo(1d)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1d)); - assertThat(facet.entries().get(1).mean(), equalTo(1d)); + assertThat(facet.getName(), equalTo("stats8")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getKey(), equalTo(1000l)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(2d)); + assertThat(facet.getEntries().get(0).getMean(), equalTo(1d)); + assertThat(facet.getEntries().get(1).getKey(), equalTo(1100l)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(1d)); + assertThat(facet.getEntries().get(1).getMean(), equalTo(1d)); - facet = searchResponse.facets().facet("stats9"); - assertThat(facet.name(), equalTo("stats9")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - - facet = searchResponse.facets().facet("stats10"); - assertThat(facet.name(), equalTo("stats10")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(2).key(), equalTo(1200l)); - assertThat(facet.entries().get(2).count(), equalTo(0l)); - - facet = searchResponse.facets().facet("stats11"); - assertThat(facet.name(), equalTo("stats11")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(1055d, 0.000001)); - assertThat(facet.entries().get(0).max(), closeTo(1065d, 0.000001)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(2120d)); - assertThat(facet.entries().get(0).mean(), equalTo(1060d)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(1175d, 0.000001)); - assertThat(facet.entries().get(1).max(), closeTo(1175d, 0.000001)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1175d)); - assertThat(facet.entries().get(1).mean(), equalTo(1175d)); - assertThat(facet.entries().get(2).key(), equalTo(1200l)); - assertThat(facet.entries().get(2).count(), equalTo(0l)); - assertThat(facet.entries().get(2).totalCount(), equalTo(0l)); - - facet = searchResponse.facets().facet("stats12"); - assertThat(facet.name(), equalTo("stats12")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(1055d, 0.000001)); - assertThat(facet.entries().get(0).max(), closeTo(1065d, 0.000001)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(2120d)); - assertThat(facet.entries().get(0).mean(), equalTo(1060d)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(1175d, 0.000001)); - assertThat(facet.entries().get(1).max(), closeTo(1175d, 0.000001)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1175d)); - assertThat(facet.entries().get(1).mean(), equalTo(1175d)); - assertThat(facet.entries().get(2).key(), equalTo(1200l)); - assertThat(facet.entries().get(2).count(), equalTo(0l)); - assertThat(facet.entries().get(2).totalCount(), equalTo(0l)); - - facet = searchResponse.facets().facet("stats13"); - assertThat(facet.name(), equalTo("stats13")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - - facet = searchResponse.facets().facet("stats14"); - assertThat(facet.name(), equalTo("stats14")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).key(), equalTo(1000l)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(1).key(), equalTo(1100l)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); } } @@ -1282,116 +1215,121 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.failedShards(), equalTo(0)); RangeFacet facet = searchResponse.facets().facet("range1"); - assertThat(facet.name(), equalTo("range1")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001)); - assertThat(Double.parseDouble(facet.entries().get(0).toAsString()), closeTo(1056, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(1055, 0.000001)); - assertThat(facet.entries().get(0).min(), closeTo(1055, 0.000001)); - assertThat(facet.entries().get(0).max(), closeTo(1055, 0.000001)); - assertThat(facet.entries().get(1).from(), closeTo(1000, 0.000001)); - assertThat(Double.parseDouble(facet.entries().get(1).fromAsString()), closeTo(1000, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1170, 0.000001)); - assertThat(Double.parseDouble(facet.entries().get(1).toAsString()), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(1055 + 1065, 0.000001)); - assertThat(facet.entries().get(1).min(), closeTo(1055, 0.000001)); - assertThat(facet.entries().get(1).max(), closeTo(1065, 0.000001)); - assertThat(facet.entries().get(2).from(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(1l)); - assertThat(facet.entries().get(2).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(2).total(), closeTo(1175, 0.000001)); - assertThat(facet.entries().get(2).min(), closeTo(1175, 0.000001)); - assertThat(facet.entries().get(2).max(), closeTo(1175, 0.000001)); + assertThat(facet.getName(), equalTo("range1")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(1056, 0.000001)); + assertThat(Double.parseDouble(facet.getEntries().get(0).getToAsString()), closeTo(1056, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(1055, 0.000001)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(1055, 0.000001)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(1055, 0.000001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(1000, 0.000001)); + assertThat(Double.parseDouble(facet.getEntries().get(1).getFromAsString()), closeTo(1000, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1170, 0.000001)); + assertThat(Double.parseDouble(facet.getEntries().get(1).getToAsString()), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(1055 + 1065, 0.000001)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(1055, 0.000001)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(1065, 0.000001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(1175, 0.000001)); + assertThat(facet.getEntries().get(2).getMin(), closeTo(1175, 0.000001)); + assertThat(facet.getEntries().get(2).getMax(), closeTo(1175, 0.000001)); facet = searchResponse.facets().facet("range2"); - assertThat(facet.name(), equalTo("range2")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(1).from(), closeTo(1000, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(3, 0.000001)); - assertThat(facet.entries().get(2).from(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(1l)); - assertThat(facet.entries().get(2).total(), closeTo(3, 0.000001)); + assertThat(facet.getName(), equalTo("range2")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(1056, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(1000, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(3, 0.000001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(3, 0.000001)); facet = searchResponse.facets().facet("range3"); - assertThat(facet.name(), equalTo("range3")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(10 + 11, 0.000001)); - assertThat(facet.entries().get(0).min(), closeTo(10, 0.000001)); - assertThat(facet.entries().get(0).max(), closeTo(11, 0.000001)); - assertThat(facet.entries().get(1).from(), closeTo(1000, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(4l)); - assertThat(facet.entries().get(1).total(), closeTo(62, 0.000001)); - assertThat(facet.entries().get(1).min(), closeTo(10, 0.000001)); - assertThat(facet.entries().get(1).max(), closeTo(21, 0.000001)); - assertThat(facet.entries().get(2).from(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(1l)); - assertThat(facet.entries().get(2).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(2).total(), closeTo(61, 0.000001)); - assertThat(facet.entries().get(2).min(), closeTo(30, 0.000001)); - assertThat(facet.entries().get(2).max(), closeTo(31, 0.000001)); + assertThat(facet.getName(), equalTo("range3")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(1056, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(10 + 11, 0.000001)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(10, 0.000001)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(11, 0.000001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(1000, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(4l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(62, 0.000001)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(10, 0.000001)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(21, 0.000001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(61, 0.000001)); + assertThat(facet.getEntries().get(2).getMin(), closeTo(30, 0.000001)); + assertThat(facet.getEntries().get(2).getMax(), closeTo(31, 0.000001)); facet = searchResponse.facets().facet("range4"); - assertThat(facet.name(), equalTo("range4")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).to(), closeTo(16, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(3, 0.000001)); - assertThat(facet.entries().get(1).from(), closeTo(10, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(26, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(3l)); - assertThat(facet.entries().get(1).total(), closeTo(1 + 2 + 3, 0.000001)); - assertThat(facet.entries().get(2).from(), closeTo(20, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(3l)); - assertThat(facet.entries().get(2).total(), closeTo(1 + 2 + 3, 0.000001)); + assertThat(facet.getName(), equalTo("range4")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(16, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(3, 0.000001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(10, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(26, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(3l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(1 + 2 + 3, 0.000001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(20, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(3l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(1 + 2 + 3, 0.000001)); facet = searchResponse.facets().facet("range5"); - assertThat(facet.name(), equalTo("range5")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(1).from(), closeTo(1000, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(3, 0.000001)); - assertThat(facet.entries().get(2).from(), closeTo(1170, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(1l)); - assertThat(facet.entries().get(2).total(), closeTo(3, 0.000001)); + assertThat(facet.getName(), equalTo("range5")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(1056, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(1000, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(3, 0.000001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(1170, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(3, 0.000001)); facet = searchResponse.facets().facet("range6"); - assertThat(facet.name(), equalTo("range6")); - assertThat(facet.entries().size(), equalTo(3)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).toAsString(), equalTo("1970-01-01T00:00:26")); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).fromAsString(), equalTo("1970-01-01T00:00:15")); - assertThat(facet.entries().get(1).toAsString(), equalTo("1970-01-01T00:00:53")); - assertThat(facet.entries().get(2).count(), equalTo(1l)); - assertThat(facet.entries().get(2).fromAsString(), equalTo("1970-01-01T00:00:26")); + assertThat(facet.getName(), equalTo("range6")); + assertThat(facet.getEntries().size(), equalTo(3)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getToAsString(), equalTo("1970-01-01T00:00:26")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getFromAsString(), equalTo("1970-01-01T00:00:15")); + assertThat(facet.getEntries().get(1).getToAsString(), equalTo("1970-01-01T00:00:53")); + assertThat(facet.getEntries().get(2).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(2).getFromAsString(), equalTo("1970-01-01T00:00:26")); } } @Test - public void testDateHistoFacets() throws Exception { - try { - client.admin().indices().prepareDelete("test").execute().actionGet(); - } catch (Exception e) { - // ignore - } + public void testDateHistoFacetsCollectorMode() throws Exception { + testDateHistoFacets(FacetBuilder.Mode.COLLECTOR); + } + + @Test + public void testDateHistoFacetsPostMode() throws Exception { + testDateHistoFacets(FacetBuilder.Mode.POST); + } + + private void testDateHistoFacets(FacetBuilder.Mode mode) throws Exception { + client.admin().indices().prepareDelete().execute().actionGet(); // TODO: facet shouldn't fail when faceted field is mapped dynamically String mapping = jsonBuilder().startObject().startObject("type1").startObject("properties") .startObject("num").field("type", "integer").endObject() @@ -1422,13 +1360,13 @@ public class SimpleFacetsTests extends AbstractNodesTests { for (int i = 0; i < numberOfRuns(); i++) { SearchResponse searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) - .addFacet(dateHistogramFacet("stats1").field("date").interval("day")) - .addFacet(dateHistogramFacet("stats2").field("date").interval("day").preZone("-02:00")) - .addFacet(dateHistogramFacet("stats3").field("date").valueField("num").interval("day").preZone("-02:00")) - .addFacet(dateHistogramFacet("stats4").field("date").valueScript("doc['num'].value * 2").interval("day").preZone("-02:00")) - .addFacet(dateHistogramFacet("stats5").field("date").interval("24h")) - .addFacet(dateHistogramFacet("stats6").field("date").valueField("num").interval("day").preZone("-02:00").postZone("-02:00")) - .addFacet(dateHistogramFacet("stats7").field("date").interval("quarter")) + .addFacet(dateHistogramFacet("stats1").field("date").interval("day").mode(mode)) + .addFacet(dateHistogramFacet("stats2").field("date").interval("day").preZone("-02:00").mode(mode)) + .addFacet(dateHistogramFacet("stats3").field("date").valueField("num").interval("day").preZone("-02:00").mode(mode)) + .addFacet(dateHistogramFacet("stats4").field("date").valueScript("doc['num'].value * 2").interval("day").preZone("-02:00").mode(mode)) + .addFacet(dateHistogramFacet("stats5").field("date").interval("24h").mode(mode)) + .addFacet(dateHistogramFacet("stats6").field("date").valueField("num").interval("day").preZone("-02:00").postZone("-02:00").mode(mode)) + .addFacet(dateHistogramFacet("stats7").field("date").interval("quarter").mode(mode)) .execute().actionGet(); if (searchResponse.failedShards() > 0) { @@ -1440,66 +1378,66 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.failedShards(), equalTo(0)); DateHistogramFacet facet = searchResponse.facets().facet("stats1"); - assertThat(facet.name(), equalTo("stats1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-06"))); - assertThat(facet.entries().get(1).count(), equalTo(1l)); + assertThat(facet.getName(), equalTo("stats1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-06"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); // time zone causes the dates to shift by 2 facet = searchResponse.facets().facet("stats2"); - assertThat(facet.name(), equalTo("stats2")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-04"))); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(1).count(), equalTo(2l)); + assertThat(facet.getName(), equalTo("stats2")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-04"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); // time zone causes the dates to shift by 2 facet = searchResponse.facets().facet("stats3"); - assertThat(facet.name(), equalTo("stats3")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-04"))); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), equalTo(1d)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), equalTo(5d)); + assertThat(facet.getName(), equalTo("stats3")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-04"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(1d)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(5d)); // time zone causes the dates to shift by 2 facet = searchResponse.facets().facet("stats4"); - assertThat(facet.name(), equalTo("stats4")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-04"))); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), equalTo(2d)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), equalTo(10d)); + assertThat(facet.getName(), equalTo("stats4")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-04"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(2d)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(10d)); facet = searchResponse.facets().facet("stats5"); - assertThat(facet.name(), equalTo("stats5")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-06"))); - assertThat(facet.entries().get(1).count(), equalTo(1l)); + assertThat(facet.getName(), equalTo("stats5")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-06"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); facet = searchResponse.facets().facet("stats6"); - assertThat(facet.name(), equalTo("stats6")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-04") - TimeValue.timeValueHours(2).millis())); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), equalTo(1d)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-05") - TimeValue.timeValueHours(2).millis())); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), equalTo(5d)); + assertThat(facet.getName(), equalTo("stats6")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-04") - TimeValue.timeValueHours(2).millis())); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(1d)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-05") - TimeValue.timeValueHours(2).millis())); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(5d)); facet = searchResponse.facets().facet("stats7"); - assertThat(facet.name(), equalTo("stats7")); - assertThat(facet.entries().size(), equalTo(1)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-01-01"))); + assertThat(facet.getName(), equalTo("stats7")); + assertThat(facet.getEntries().size(), equalTo(1)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-01-01"))); } } @@ -1555,23 +1493,23 @@ public class SimpleFacetsTests extends AbstractNodesTests { // time zone causes the dates to shift by 2:00 DateHistogramFacet facet = searchResponse.facets().facet("stats1"); - assertThat(facet.name(), equalTo("stats1")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-06"))); - assertThat(facet.entries().get(1).count(), equalTo(2l)); + assertThat(facet.getName(), equalTo("stats1")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-06"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); // time zone causes the dates to shift by 1:30 facet = searchResponse.facets().facet("stats2"); - assertThat(facet.name(), equalTo("stats2")); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).time(), equalTo(utcTimeInMillis("2009-03-05"))); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), equalTo(5d)); - assertThat(facet.entries().get(1).time(), equalTo(utcTimeInMillis("2009-03-06"))); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), equalTo(1d)); + assertThat(facet.getName(), equalTo("stats2")); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTime(), equalTo(utcTimeInMillis("2009-03-05"))); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), equalTo(5d)); + assertThat(facet.getEntries().get(1).getTime(), equalTo(utcTimeInMillis("2009-03-06"))); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), equalTo(1d)); } } @@ -1637,131 +1575,131 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.failedShards(), equalTo(0)); TermsStatsFacet facet = searchResponse.facets().facet("stats1"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).totalCount(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(100d, 0.00001d)); - assertThat(facet.entries().get(0).max(), closeTo(200d, 0.00001d)); - assertThat(facet.entries().get(0).total(), closeTo(300d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).totalCount(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).max(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).total(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotalCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(100d, 0.00001d)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(200d, 0.00001d)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotalCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(500d, 0.00001d)); facet = searchResponse.facets().facet("stats2"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(1d, 0.00001d)); - assertThat(facet.entries().get(0).max(), closeTo(3d, 0.00001d)); - assertThat(facet.entries().get(0).total(), closeTo(8d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(5d, 0.00001d)); - assertThat(facet.entries().get(1).max(), closeTo(6d, 0.00001d)); - assertThat(facet.entries().get(1).total(), closeTo(11d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(1d, 0.00001d)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(3d, 0.00001d)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(8d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(5d, 0.00001d)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(6d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(11d, 0.00001d)); facet = searchResponse.facets().facet("stats3"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(300d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(500d, 0.00001d)); facet = searchResponse.facets().facet("stats4"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(8d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(11d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(8d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(11d, 0.00001d)); facet = searchResponse.facets().facet("stats5"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(300d, 0.00001d)); facet = searchResponse.facets().facet("stats6"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(11d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(8d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(11d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(8d, 0.00001d)); facet = searchResponse.facets().facet("stats7"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(300d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(500d, 0.00001d)); facet = searchResponse.facets().facet("stats8"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(8d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(11d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(8d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(11d, 0.00001d)); facet = searchResponse.facets().facet("stats9"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(300d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(500d, 0.00001d)); facet = searchResponse.facets().facet("stats10"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(8d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(11d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(8d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(11d, 0.00001d)); facet = searchResponse.facets().facet("stats11"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(300d, 0.00001d)); facet = searchResponse.facets().facet("stats12"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(0).count(), equalTo(1l)); - assertThat(facet.entries().get(0).total(), closeTo(11d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(8d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(11d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(8d, 0.00001d)); facet = searchResponse.facets().facet("stats13"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("xxx")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).total(), closeTo(600d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("yyy")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).total(), closeTo(1000d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("xxx")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(600d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("yyy")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(1000d, 0.00001d)); } } @@ -1818,30 +1756,30 @@ public class SimpleFacetsTests extends AbstractNodesTests { assertThat(searchResponse.failedShards(), equalTo(0)); TermsStatsFacet facet = searchResponse.facets().facet("stats1"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("100")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(100d, 0.00001d)); - assertThat(facet.entries().get(0).max(), closeTo(200d, 0.00001d)); - assertThat(facet.entries().get(0).total(), closeTo(300d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("200")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).max(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).total(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("100")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(100d, 0.00001d)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(200d, 0.00001d)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("200")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(500d, 0.00001d)); facet = searchResponse.facets().facet("stats2"); - assertThat(facet.entries().size(), equalTo(2)); - assertThat(facet.entries().get(0).term().string(), equalTo("100.1")); - assertThat(facet.entries().get(0).count(), equalTo(2l)); - assertThat(facet.entries().get(0).min(), closeTo(100d, 0.00001d)); - assertThat(facet.entries().get(0).max(), closeTo(200d, 0.00001d)); - assertThat(facet.entries().get(0).total(), closeTo(300d, 0.00001d)); - assertThat(facet.entries().get(1).term().string(), equalTo("200.2")); - assertThat(facet.entries().get(1).count(), equalTo(1l)); - assertThat(facet.entries().get(1).min(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).max(), closeTo(500d, 0.00001d)); - assertThat(facet.entries().get(1).total(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().size(), equalTo(2)); + assertThat(facet.getEntries().get(0).getTerm().string(), equalTo("100.1")); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getMin(), closeTo(100d, 0.00001d)); + assertThat(facet.getEntries().get(0).getMax(), closeTo(200d, 0.00001d)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(300d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTerm().string(), equalTo("200.2")); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getMin(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getMax(), closeTo(500d, 0.00001d)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(500d, 0.00001d)); } } @@ -1879,10 +1817,10 @@ public class SimpleFacetsTests extends AbstractNodesTests { } assertThat(searchResponse.failedShards(), equalTo(0)); TermsStatsFacet facet = searchResponse.facets().facet("stats1"); - assertThat(facet.entries().size(), equalTo(10)); + assertThat(facet.getEntries().size(), equalTo(10)); facet = searchResponse.facets().facet("stats2"); - assertThat(facet.entries().size(), equalTo(10)); + assertThat(facet.getEntries().size(), equalTo(10)); } } @@ -1908,7 +1846,7 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); QueryFacet facet = searchResponse.facets().facet("query"); - assertThat(facet.count(), equalTo(2l)); + assertThat(facet.getCount(), equalTo(2l)); searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) @@ -1916,7 +1854,7 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("query"); - assertThat(facet.count(), equalTo(2l)); + assertThat(facet.getCount(), equalTo(2l)); searchResponse = client.prepareSearch() .setQuery(matchAllQuery()) @@ -1924,7 +1862,7 @@ public class SimpleFacetsTests extends AbstractNodesTests { .execute().actionGet(); facet = searchResponse.facets().facet("query"); - assertThat(facet.count(), equalTo(2l)); + assertThat(facet.getCount(), equalTo(2l)); } } diff --git a/src/test/java/org/elasticsearch/test/integration/search/geo/GeoDistanceFacetTests.java b/src/test/java/org/elasticsearch/test/integration/search/geo/GeoDistanceFacetTests.java index a766c361373..6dff4c0457a 100644 --- a/src/test/java/org/elasticsearch/test/integration/search/geo/GeoDistanceFacetTests.java +++ b/src/test/java/org/elasticsearch/test/integration/search/geo/GeoDistanceFacetTests.java @@ -137,25 +137,25 @@ public class GeoDistanceFacetTests extends AbstractNodesTests { assertThat(searchResponse.hits().totalHits(), equalTo(7l)); GeoDistanceFacet facet = searchResponse.facets().facet("geo1"); - assertThat(facet.entries().size(), equalTo(4)); + assertThat(facet.getEntries().size(), equalTo(4)); - assertThat(facet.entries().get(0).to(), closeTo(2, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(4l)); - assertThat(facet.entries().get(0).total(), not(closeTo(0, 0.00001))); + assertThat(facet.getEntries().get(0).getTo(), closeTo(2, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(4l)); + assertThat(facet.getEntries().get(0).getTotal(), not(closeTo(0, 0.00001))); - assertThat(facet.entries().get(1).from(), closeTo(0, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), not(closeTo(0, 0.00001))); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(0, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), not(closeTo(0, 0.00001))); - assertThat(facet.entries().get(2).from(), closeTo(0.5, 0.000001)); - assertThat(facet.entries().get(2).to(), closeTo(2.5, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(3l)); - assertThat(facet.entries().get(2).total(), not(closeTo(0, 0.00001))); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(0.5, 0.000001)); + assertThat(facet.getEntries().get(2).getTo(), closeTo(2.5, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(3l)); + assertThat(facet.getEntries().get(2).getTotal(), not(closeTo(0, 0.00001))); - assertThat(facet.entries().get(3).from(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(3).count(), equalTo(5l)); - assertThat(facet.entries().get(3).total(), not(closeTo(0, 0.00001))); + assertThat(facet.getEntries().get(3).getFrom(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(3).getCount(), equalTo(5l)); + assertThat(facet.getEntries().get(3).getTotal(), not(closeTo(0, 0.00001))); searchResponse = client.prepareSearch() // from NY @@ -170,25 +170,25 @@ public class GeoDistanceFacetTests extends AbstractNodesTests { assertThat(searchResponse.hits().totalHits(), equalTo(7l)); facet = searchResponse.facets().facet("geo1"); - assertThat(facet.entries().size(), equalTo(4)); + assertThat(facet.getEntries().size(), equalTo(4)); - assertThat(facet.entries().get(0).to(), closeTo(2, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(4l)); - assertThat(facet.entries().get(0).total(), closeTo(13, 0.00001)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(2, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(4l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(13, 0.00001)); - assertThat(facet.entries().get(1).from(), closeTo(0, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(4, 0.00001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(0, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(4, 0.00001)); - assertThat(facet.entries().get(2).from(), closeTo(0.5, 0.000001)); - assertThat(facet.entries().get(2).to(), closeTo(2.5, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(3l)); - assertThat(facet.entries().get(2).total(), closeTo(15, 0.00001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(0.5, 0.000001)); + assertThat(facet.getEntries().get(2).getTo(), closeTo(2.5, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(3l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(15, 0.00001)); - assertThat(facet.entries().get(3).from(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(3).count(), equalTo(5l)); - assertThat(facet.entries().get(3).total(), closeTo(24, 0.00001)); + assertThat(facet.getEntries().get(3).getFrom(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(3).getCount(), equalTo(5l)); + assertThat(facet.getEntries().get(3).getTotal(), closeTo(24, 0.00001)); searchResponse = client.prepareSearch() // from NY .setQuery(matchAllQuery()) @@ -202,25 +202,25 @@ public class GeoDistanceFacetTests extends AbstractNodesTests { assertThat(searchResponse.hits().totalHits(), equalTo(7l)); facet = searchResponse.facets().facet("geo1"); - assertThat(facet.entries().size(), equalTo(4)); + assertThat(facet.getEntries().size(), equalTo(4)); - assertThat(facet.entries().get(0).to(), closeTo(2, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(4l)); - assertThat(facet.entries().get(0).total(), closeTo(13, 0.00001)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(2, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(4l)); + assertThat(facet.getEntries().get(0).getTotal(), closeTo(13, 0.00001)); - assertThat(facet.entries().get(1).from(), closeTo(0, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(2l)); - assertThat(facet.entries().get(1).total(), closeTo(4, 0.00001)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(0, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(2l)); + assertThat(facet.getEntries().get(1).getTotal(), closeTo(4, 0.00001)); - assertThat(facet.entries().get(2).from(), closeTo(0.5, 0.000001)); - assertThat(facet.entries().get(2).to(), closeTo(2.5, 0.000001)); - assertThat(facet.entries().get(2).count(), equalTo(3l)); - assertThat(facet.entries().get(2).total(), closeTo(15, 0.00001)); + assertThat(facet.getEntries().get(2).getFrom(), closeTo(0.5, 0.000001)); + assertThat(facet.getEntries().get(2).getTo(), closeTo(2.5, 0.000001)); + assertThat(facet.getEntries().get(2).getCount(), equalTo(3l)); + assertThat(facet.getEntries().get(2).getTotal(), closeTo(15, 0.00001)); - assertThat(facet.entries().get(3).from(), closeTo(1, 0.000001)); - assertThat(facet.entries().get(3).count(), equalTo(5l)); - assertThat(facet.entries().get(3).total(), closeTo(24, 0.00001)); + assertThat(facet.getEntries().get(3).getFrom(), closeTo(1, 0.000001)); + assertThat(facet.getEntries().get(3).getCount(), equalTo(5l)); + assertThat(facet.getEntries().get(3).getTotal(), closeTo(24, 0.00001)); } @Test @@ -271,14 +271,14 @@ public class GeoDistanceFacetTests extends AbstractNodesTests { assertThat(searchResponse.hits().totalHits(), equalTo(2l)); GeoDistanceFacet facet = searchResponse.facets().facet("geo1"); - assertThat(facet.entries().size(), equalTo(2)); + assertThat(facet.getEntries().size(), equalTo(2)); - assertThat(facet.entries().get(0).from(), closeTo(0, 0.000001)); - assertThat(facet.entries().get(0).to(), closeTo(2, 0.000001)); - assertThat(facet.entries().get(0).count(), equalTo(2l)); + assertThat(facet.getEntries().get(0).getFrom(), closeTo(0, 0.000001)); + assertThat(facet.getEntries().get(0).getTo(), closeTo(2, 0.000001)); + assertThat(facet.getEntries().get(0).getCount(), equalTo(2l)); - assertThat(facet.entries().get(1).from(), closeTo(2, 0.000001)); - assertThat(facet.entries().get(1).to(), closeTo(10, 0.000001)); - assertThat(facet.entries().get(1).count(), equalTo(1l)); + assertThat(facet.getEntries().get(1).getFrom(), closeTo(2, 0.000001)); + assertThat(facet.getEntries().get(1).getTo(), closeTo(10, 0.000001)); + assertThat(facet.getEntries().get(1).getCount(), equalTo(1l)); } }