From 95ecbaba84a323a5f873a0a7ead753bbecbea58d Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 22 Jul 2025 19:22:17 +0200 Subject: [PATCH] HSEARCH-5426 Adjust the count aggregation DSL --- .../impl/ElasticsearchIndexRootBuilder.java | 2 +- ...ElasticsearchCountDocumentAggregation.java | 84 +++++------ .../ElasticsearchCountValuesAggregation.java | 138 ++++++++++++++++++ .../ElasticsearchMetricLongAggregation.java | 110 -------------- .../impl/ElasticsearchRangeAggregation.java | 3 +- .../impl/ElasticsearchTermsAggregation.java | 3 +- ...sticsearchNumericFieldTypeOptionsStep.java | 6 +- ...archTemporalIndexFieldTypeOptionsStep.java | 6 +- ...iIndexSearchIndexCompositeNodeContext.java | 6 + .../impl/LuceneSearchIndexNodeContext.java | 3 + ...neCountDistinctNumericLongAggregation.java | 59 -------- .../impl/LuceneCountDocumentAggregation.java | 68 ++++----- .../LuceneCountNumericLongAggregation.java | 59 -------- .../impl/LuceneCountValuesAggregation.java | 97 ++++++++++++ .../impl/LuceneNumericRangeAggregation.java | 2 +- .../impl/LuceneNumericTermsAggregation.java | 3 +- .../impl/LuceneTextTermsAggregation.java | 2 +- ...uceneNumericIndexFieldTypeOptionsStep.java | 7 +- ...ceneTemporalIndexFieldTypeOptionsStep.java | 7 +- .../src/main/asciidoc/migration/index.adoc | 3 +- .../reference/_search-dsl-aggregation.adoc | 25 ++-- .../search/aggregation/AggregationDslIT.java | 22 +-- .../backend/types/IndexFieldTraits.java | 14 +- .../dsl/CountAggregationKindStep.java | 57 ++++++++ ...untDistinctValuesAggregationFieldStep.java | 5 +- .../dsl/CountValuesAggregationFieldStep.java | 4 +- .../CountValuesAggregationOptionsStep.java | 15 ++ .../dsl/ExtendedSearchAggregationFactory.java | 21 +-- .../dsl/SearchAggregationFactory.java | 54 +------ .../dsl/TypedSearchAggregationFactory.java | 59 +------- ...java => CountAggregationKindStepImpl.java} | 20 ++- ...istinctValuesAggregationFieldStepImpl.java | 9 +- ...tinctValuesAggregationOptionsStepImpl.java | 1 + ...ountDocumentsAggregationFinalStepImpl.java | 8 +- ...CountValuesAggregationOptionsStepImpl.java | 12 +- .../spi/AbstractSearchAggregationFactory.java | 19 +-- .../aggregation/spi/AggregationTypeKeys.java | 12 +- .../spi/CountDocumentAggregationBuilder.java | 4 +- .../spi/CountValuesAggregationBuilder.java | 14 ++ .../aggregation/AnyAggregationReference.java | 3 +- ...va => CountAggregationFieldReference.java} | 2 +- ...stinctValuesAggregationFieldReference.java | 11 -- .../MetricNumericFieldsAggregationsIT.java | 15 +- .../MetricTemporalFieldsAggregationsIT.java | 8 +- .../RangeAggregationSpecificsIT.java | 24 +-- .../TermsAggregationSpecificsIT.java | 2 +- .../MetricAggregationsTestCase.java | 4 +- .../orm/elasticsearch/AggregationTypesIT.java | 4 +- .../orm/lucene/AggregationTypesIT.java | 4 +- .../elasticsearch/AggregationTypesIT.java | 4 +- .../standalone/lucene/AggregationTypesIT.java | 4 +- ...iIndexSearchIndexCompositeNodeContext.java | 6 + .../impl/LuceneSearchIndexNodeContext.java | 3 + ...neCountDistinctNumericLongAggregation.java | 59 -------- .../impl/LuceneCountDocumentAggregation.java | 66 ++++----- .../LuceneCountNumericLongAggregation.java | 59 -------- .../impl/LuceneCountValuesAggregation.java | 97 ++++++++++++ .../impl/LuceneNumericRangeAggregation.java | 4 +- .../impl/LuceneNumericTermsAggregation.java | 3 +- .../impl/LuceneTextTermsAggregation.java | 2 +- ...uceneNumericIndexFieldTypeOptionsStep.java | 7 +- ...ceneTemporalIndexFieldTypeOptionsStep.java | 7 +- .../writer/impl/TraitReferenceMapping.java | 9 +- .../impl/TraitReferenceMappingTest.java | 3 + 64 files changed, 707 insertions(+), 746 deletions(-) create mode 100644 backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountValuesAggregation.java delete mode 100644 backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchMetricLongAggregation.java delete mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java delete mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java create mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java create mode 100644 engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountAggregationKindStep.java rename engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/{CountValuesAggregationFieldStepImpl.java => CountAggregationKindStepImpl.java} (50%) create mode 100644 engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountValuesAggregationBuilder.java rename engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/{CountValuesAggregationFieldReference.java => CountAggregationFieldReference.java} (70%) delete mode 100644 engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountDistinctValuesAggregationFieldReference.java delete mode 100644 lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java delete mode 100644 lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java create mode 100644 lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/document/model/dsl/impl/ElasticsearchIndexRootBuilder.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/document/model/dsl/impl/ElasticsearchIndexRootBuilder.java index 20a55aeeffc..4b989456fb0 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/document/model/dsl/impl/ElasticsearchIndexRootBuilder.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/document/model/dsl/impl/ElasticsearchIndexRootBuilder.java @@ -87,7 +87,7 @@ public ElasticsearchIndexRootBuilder(ElasticsearchIndexFieldTypeFactoryProvider this.defaultDynamicType = DynamicType.create( dynamicMapping ); this.typeBuilder.queryElementFactory( AggregationTypeKeys.COUNT_DOCUMENTS, - ElasticsearchCountDocumentAggregation.factory( false ) ); + ElasticsearchCountDocumentAggregation.factory() ); this.addDefaultImplicitFields(); } diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountDocumentAggregation.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountDocumentAggregation.java index d5ae77fa13e..08f62de442e 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountDocumentAggregation.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountDocumentAggregation.java @@ -7,7 +7,7 @@ import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor; import org.hibernate.search.backend.elasticsearch.logging.impl.ElasticsearchClientLog; import org.hibernate.search.backend.elasticsearch.logging.impl.QueryLog; -import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexCompositeNodeContext; +import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexNodeContext; import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope; import org.hibernate.search.backend.elasticsearch.search.query.impl.ElasticsearchSearchQueryExtractContext; import org.hibernate.search.engine.search.aggregation.AggregationKey; @@ -28,12 +28,6 @@ public class ElasticsearchCountDocumentAggregation extends AbstractElasticsearch private static final JsonAccessor RESPONSE_ROOT_DOC_COUNT_ACCESSOR = JsonAccessor.root().property( "root_doc_count" ).property( "doc_count" ).asLong(); - public static SearchQueryElementFactory, - ElasticsearchSearchIndexCompositeNodeContext> factory(boolean isNested) { - return new ElasticsearchCountDocumentAggregation.Factory( isNested ); - } - private final boolean isNested; private ElasticsearchCountDocumentAggregation(Builder builder) { @@ -41,6 +35,48 @@ private ElasticsearchCountDocumentAggregation(Builder builder) { this.isNested = builder.isNested; } + public static SearchQueryElementFactory, + ElasticsearchSearchIndexNodeContext> factory() { + return new Factory(); + } + + private static class Factory + implements SearchQueryElementFactory, + ElasticsearchSearchIndexNodeContext> { + + @Override + public CountDocumentAggregationBuilder.TypeSelector create(ElasticsearchSearchIndexScope scope, + ElasticsearchSearchIndexNodeContext node) { + return new TypeSelector( scope, node ); + } + + @Override + public void checkCompatibleWith(SearchQueryElementFactory other) { + if ( !getClass().equals( other.getClass() ) ) { + throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() ); + } + } + } + + private static final class TypeSelector implements CountDocumentAggregationBuilder.TypeSelector { + private final ElasticsearchSearchIndexScope scope; + private final ElasticsearchSearchIndexNodeContext node; + + private TypeSelector(ElasticsearchSearchIndexScope scope, + ElasticsearchSearchIndexNodeContext node) { + this.scope = scope; + this.node = node; // doesn't matter in this case + } + + @Override + public CountDocumentAggregationBuilder builder() { + boolean isNested = node.isValueField() && !node.toValueField().nestedPathHierarchy().isEmpty(); + return new ElasticsearchCountDocumentAggregation.Builder( scope, isNested ); + } + } + @Override public Extractor request(AggregationRequestContext context, AggregationKey key, JsonObject jsonAggregations) { return new CountDocumentsExtractor( key, isNested, context.isRootContext() ); @@ -73,40 +109,6 @@ public Long extract(JsonObject aggregationResult, AggregationExtractContext cont } } - private static class Factory - implements - SearchQueryElementFactory, - ElasticsearchSearchIndexCompositeNodeContext> { - private final boolean isNested; - - public Factory(boolean isNested) { - this.isNested = isNested; - } - - @Override - public CountDocumentAggregationBuilder.TypeSelector create(ElasticsearchSearchIndexScope scope, - ElasticsearchSearchIndexCompositeNodeContext node) { - return new ElasticsearchCountDocumentAggregation.TypeSelector( scope, isNested ); - } - - @Override - public void checkCompatibleWith(SearchQueryElementFactory other) { - if ( !getClass().equals( other.getClass() ) ) { - throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() ); - } - } - } - - private record TypeSelector(ElasticsearchSearchIndexScope scope, boolean isNested) - implements CountDocumentAggregationBuilder.TypeSelector { - - @Override - public CountDocumentAggregationBuilder type() { - return new Builder( scope, isNested ); - } - } - private static class Builder extends AbstractBuilder implements CountDocumentAggregationBuilder { private final boolean isNested; diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountValuesAggregation.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountValuesAggregation.java new file mode 100644 index 00000000000..85788611a79 --- /dev/null +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountValuesAggregation.java @@ -0,0 +1,138 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.backend.elasticsearch.search.aggregation.impl; + +import java.util.List; + +import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor; +import org.hibernate.search.backend.elasticsearch.gson.impl.JsonElementTypes; +import org.hibernate.search.backend.elasticsearch.logging.impl.QueryLog; +import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexNodeContext; +import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope; +import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexValueFieldContext; +import org.hibernate.search.backend.elasticsearch.search.predicate.impl.ElasticsearchSearchPredicate; +import org.hibernate.search.engine.search.aggregation.AggregationKey; +import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder; +import org.hibernate.search.engine.search.common.spi.SearchQueryElementFactory; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class ElasticsearchCountValuesAggregation extends AbstractElasticsearchNestableAggregation { + + private static final JsonAccessor COUNT_PROPERTY_ACCESSOR = + JsonAccessor.root().property( "value_count" ).asObject(); + + private static final JsonAccessor COUNT_DISTINCT_PROPERTY_ACCESSOR = + JsonAccessor.root().property( "cardinality" ).asObject(); + + private static final JsonAccessor FIELD_PROPERTY_ACCESSOR = + JsonAccessor.root().property( "field" ).asString(); + + private final String absoluteFieldPath; + private final JsonAccessor operation; + + private ElasticsearchCountValuesAggregation(Builder builder) { + super( builder ); + this.absoluteFieldPath = builder.field.absolutePath(); + this.operation = builder.operation; + } + + public static SearchQueryElementFactory, + ElasticsearchSearchIndexNodeContext> factory() { + return new Factory(); + } + + private static class Factory + implements SearchQueryElementFactory, + ElasticsearchSearchIndexNodeContext> { + + @Override + public CountValuesAggregationBuilder.TypeSelector create(ElasticsearchSearchIndexScope scope, + ElasticsearchSearchIndexNodeContext node) { + return new TypeSelector( scope, node ); + } + + @Override + public void checkCompatibleWith(SearchQueryElementFactory other) { + if ( !getClass().equals( other.getClass() ) ) { + throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() ); + } + } + } + + private static final class TypeSelector implements CountValuesAggregationBuilder.TypeSelector { + private final ElasticsearchSearchIndexScope scope; + private final ElasticsearchSearchIndexNodeContext node; + + private TypeSelector(ElasticsearchSearchIndexScope scope, + ElasticsearchSearchIndexNodeContext node) { + this.scope = scope; + this.node = node; // doesn't matter in this case + } + + @Override + public CountValuesAggregationBuilder builder() { + return new ElasticsearchCountValuesAggregation.Builder( scope, node.toValueField() ); + } + } + + @Override + protected final JsonObject doRequest(AggregationRequestBuildingContextContext context) { + JsonObject outerObject = new JsonObject(); + JsonObject innerObject = new JsonObject(); + + operation.set( outerObject, innerObject ); + FIELD_PROPERTY_ACCESSOR.set( innerObject, absoluteFieldPath ); + return outerObject; + } + + @Override + protected Extractor extractor(AggregationKey key, AggregationRequestBuildingContextContext context) { + return new MetricLongExtractor( key, nestedPathHierarchy, filter ); + } + + private static class MetricLongExtractor extends AbstractExtractor { + protected MetricLongExtractor( + AggregationKey key, List nestedPathHierarchy, + ElasticsearchSearchPredicate filter + ) { + super( key, nestedPathHierarchy, filter ); + } + + @Override + protected Long doExtract(JsonObject aggregationResult, AggregationExtractContext context) { + JsonElement value = aggregationResult.get( "value" ); + return JsonElementTypes.LONG.fromElement( value ); + } + } + + private static class Builder extends AbstractBuilder + implements CountValuesAggregationBuilder { + private JsonAccessor operation; + + private Builder(ElasticsearchSearchIndexScope scope, ElasticsearchSearchIndexValueFieldContext field) { + super( scope, field ); + this.operation = COUNT_PROPERTY_ACCESSOR; + } + + @Override + public ElasticsearchCountValuesAggregation build() { + return new ElasticsearchCountValuesAggregation( this ); + } + + @Override + public void distinct(boolean distinct) { + if ( distinct ) { + operation = COUNT_DISTINCT_PROPERTY_ACCESSOR; + } + else { + operation = COUNT_PROPERTY_ACCESSOR; + } + } + } +} diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchMetricLongAggregation.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchMetricLongAggregation.java deleted file mode 100644 index e8c56ed59eb..00000000000 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchMetricLongAggregation.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.search.backend.elasticsearch.search.aggregation.impl; - -import java.util.List; - -import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor; -import org.hibernate.search.backend.elasticsearch.gson.impl.JsonElementTypes; -import org.hibernate.search.backend.elasticsearch.search.common.impl.AbstractElasticsearchCodecAwareSearchQueryElementFactory; -import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope; -import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexValueFieldContext; -import org.hibernate.search.backend.elasticsearch.search.predicate.impl.ElasticsearchSearchPredicate; -import org.hibernate.search.backend.elasticsearch.types.codec.impl.ElasticsearchFieldCodec; -import org.hibernate.search.engine.search.aggregation.AggregationKey; -import org.hibernate.search.engine.search.aggregation.spi.SearchFilterableAggregationBuilder; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -public class ElasticsearchMetricLongAggregation extends AbstractElasticsearchNestableAggregation { - - private static final JsonAccessor COUNT_PROPERTY_ACCESSOR = - JsonAccessor.root().property( "value_count" ).asObject(); - - private static final JsonAccessor COUNT_DISTINCT_PROPERTY_ACCESSOR = - JsonAccessor.root().property( "cardinality" ).asObject(); - - private static final JsonAccessor FIELD_PROPERTY_ACCESSOR = - JsonAccessor.root().property( "field" ).asString(); - - public static ElasticsearchMetricLongAggregation.Factory count(ElasticsearchFieldCodec codec) { - return new ElasticsearchMetricLongAggregation.Factory<>( codec, COUNT_PROPERTY_ACCESSOR ); - } - - public static ElasticsearchMetricLongAggregation.Factory countDistinct(ElasticsearchFieldCodec codec) { - return new ElasticsearchMetricLongAggregation.Factory<>( codec, COUNT_DISTINCT_PROPERTY_ACCESSOR ); - } - - private final String absoluteFieldPath; - private final JsonAccessor operation; - - private ElasticsearchMetricLongAggregation(Builder builder) { - super( builder ); - this.absoluteFieldPath = builder.field.absolutePath(); - this.operation = builder.operation; - } - - @Override - protected final JsonObject doRequest(AggregationRequestBuildingContextContext context) { - JsonObject outerObject = new JsonObject(); - JsonObject innerObject = new JsonObject(); - - operation.set( outerObject, innerObject ); - FIELD_PROPERTY_ACCESSOR.set( innerObject, absoluteFieldPath ); - return outerObject; - } - - @Override - protected Extractor extractor(AggregationKey key, AggregationRequestBuildingContextContext context) { - return new MetricLongExtractor( key, nestedPathHierarchy, filter ); - } - - private static class Factory - extends - AbstractElasticsearchCodecAwareSearchQueryElementFactory, F> { - - private final JsonAccessor operation; - - private Factory(ElasticsearchFieldCodec codec, JsonAccessor operation) { - super( codec ); - this.operation = operation; - } - - @Override - public SearchFilterableAggregationBuilder create(ElasticsearchSearchIndexScope scope, - ElasticsearchSearchIndexValueFieldContext field) { - return new Builder( scope, field, operation ); - } - } - - private static class MetricLongExtractor extends AbstractExtractor { - protected MetricLongExtractor(AggregationKey key, List nestedPathHierarchy, - ElasticsearchSearchPredicate filter) { - super( key, nestedPathHierarchy, filter ); - } - - @Override - protected Long doExtract(JsonObject aggregationResult, AggregationExtractContext context) { - JsonElement value = aggregationResult.get( "value" ); - return JsonElementTypes.LONG.fromElement( value ); - } - } - - private static class Builder extends AbstractBuilder implements SearchFilterableAggregationBuilder { - private final JsonAccessor operation; - - private Builder(ElasticsearchSearchIndexScope scope, ElasticsearchSearchIndexValueFieldContext field, - JsonAccessor operation) { - super( scope, field ); - this.operation = operation; - } - - @Override - public ElasticsearchMetricLongAggregation build() { - return new ElasticsearchMetricLongAggregation( this ); - } - } -} diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchRangeAggregation.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchRangeAggregation.java index 78806a11345..dcd9c1fcdf2 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchRangeAggregation.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchRangeAggregation.java @@ -138,8 +138,7 @@ protected CountBuilder(ElasticsearchSearchIndexScope scope, Function encoder) { super( scope, field, encoder, new ArrayList<>(), new JsonArray(), ElasticsearchSearchAggregation.from( scope, - ElasticsearchCountDocumentAggregation.factory( !field.nestedPathHierarchy().isEmpty() ) - .create( scope, null ).type().build() ) ); + ElasticsearchCountDocumentAggregation.factory().create( scope, field ).builder().build() ) ); } } diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchTermsAggregation.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchTermsAggregation.java index f19a8027e91..b590f3d335c 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchTermsAggregation.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchTermsAggregation.java @@ -163,8 +163,7 @@ protected CountBuilder(ElasticsearchSearchIndexScope scope, ProjectionConverter fromFieldValueConverter) { super( scope, field, decodeFunction, fromFieldValueConverter, ElasticsearchSearchAggregation.from( scope, - ElasticsearchCountDocumentAggregation.factory( !field.nestedPathHierarchy().isEmpty() ) - .create( scope, null ).type().build() ) ); + ElasticsearchCountDocumentAggregation.factory().create( scope, field ).builder().build() ) ); } } diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchNumericFieldTypeOptionsStep.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchNumericFieldTypeOptionsStep.java index 4976e0b9ebc..bed32ee2f37 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchNumericFieldTypeOptionsStep.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchNumericFieldTypeOptionsStep.java @@ -4,8 +4,8 @@ */ package org.hibernate.search.backend.elasticsearch.types.dsl.impl; +import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchCountValuesAggregation; import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchMetricFieldAggregation; -import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchMetricLongAggregation; import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchRangeAggregation; import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchTermsAggregation; import org.hibernate.search.backend.elasticsearch.search.predicate.impl.ElasticsearchExistsPredicate; @@ -69,9 +69,7 @@ protected final void complete() { builder.queryElementFactory( AggregationTypeKeys.MIN, ElasticsearchMetricFieldAggregation.min( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MAX, ElasticsearchMetricFieldAggregation.max( codec ) ); builder.queryElementFactory( AggregationTypeKeys.AVG, ElasticsearchMetricFieldAggregation.avg( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_VALUES, ElasticsearchMetricLongAggregation.count( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_DISTINCT_VALUES, - ElasticsearchMetricLongAggregation.countDistinct( codec ) ); + builder.queryElementFactory( AggregationTypeKeys.COUNT, ElasticsearchCountValuesAggregation.factory() ); } } diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchTemporalIndexFieldTypeOptionsStep.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchTemporalIndexFieldTypeOptionsStep.java index a929b11767b..d1dc6a7456f 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchTemporalIndexFieldTypeOptionsStep.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/dsl/impl/AbstractElasticsearchTemporalIndexFieldTypeOptionsStep.java @@ -8,8 +8,8 @@ import java.time.temporal.TemporalAccessor; import org.hibernate.search.backend.elasticsearch.lowlevel.index.mapping.impl.DataTypes; +import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchCountValuesAggregation; import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchMetricFieldAggregation; -import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchMetricLongAggregation; import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchRangeAggregation; import org.hibernate.search.backend.elasticsearch.search.aggregation.impl.ElasticsearchTermsAggregation; import org.hibernate.search.backend.elasticsearch.search.predicate.impl.ElasticsearchExistsPredicate; @@ -88,9 +88,7 @@ protected final void complete() { builder.queryElementFactory( AggregationTypeKeys.MIN, ElasticsearchMetricFieldAggregation.min( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MAX, ElasticsearchMetricFieldAggregation.max( codec ) ); builder.queryElementFactory( AggregationTypeKeys.AVG, ElasticsearchMetricFieldAggregation.avg( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_VALUES, ElasticsearchMetricLongAggregation.count( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_DISTINCT_VALUES, - ElasticsearchMetricLongAggregation.countDistinct( codec ) ); + builder.queryElementFactory( AggregationTypeKeys.COUNT, ElasticsearchCountValuesAggregation.factory() ); } } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java index e25d1f619c4..163b40db4ba 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java @@ -7,6 +7,7 @@ import java.util.List; import org.hibernate.search.engine.search.common.spi.AbstractMultiIndexSearchIndexCompositeNodeContext; +import org.hibernate.search.engine.search.common.spi.SearchIndexSchemaElementContextHelper; public final class LuceneMultiIndexSearchIndexCompositeNodeContext extends AbstractMultiIndexSearchIndexCompositeNodeContext< @@ -36,6 +37,11 @@ protected LuceneSearchIndexCompositeNodeTypeContext typeOf(LuceneSearchIndexComp return indexElement.type(); } + @Override + public LuceneSearchIndexValueFieldContext toValueField() { + return SearchIndexSchemaElementContextHelper.throwingToValueField( this ); + } + @Override protected LuceneSearchIndexNodeContext childInScope(String childRelativeName) { return scope.child( this, childRelativeName ); diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java index 94ad9be84c6..556adf378df 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java @@ -15,4 +15,7 @@ public interface LuceneSearchIndexNodeContext @Override LuceneSearchIndexCompositeNodeContext toObjectField(); + @Override + LuceneSearchIndexValueFieldContext toValueField(); + } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java deleted file mode 100644 index f83e3d09acc..00000000000 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.search.backend.lucene.types.aggregation.impl; - -import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountDistinctValuesCollectorFactory; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; -import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; -import org.hibernate.search.backend.lucene.search.common.impl.AbstractLuceneCodecAwareSearchQueryElementFactory; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexValueFieldContext; -import org.hibernate.search.backend.lucene.types.codec.impl.AbstractLuceneNumericFieldCodec; -import org.hibernate.search.engine.search.aggregation.spi.FieldMetricAggregationBuilder; - -public class LuceneCountDistinctNumericLongAggregation extends AbstractLuceneMetricNumericLongAggregation { - - public static Factory factory(AbstractLuceneNumericFieldCodec codec) { - return new Factory<>( codec ); - } - - LuceneCountDistinctNumericLongAggregation(Builder builder) { - super( builder ); - } - - @Override - void fillCollectors(JoiningLongMultiValuesSource source, AggregationRequestContext context) { - CountDistinctValuesCollectorFactory collectorFactory = new CountDistinctValuesCollectorFactory( source ); - collectorKey = collectorFactory.getCollectorKey(); - context.requireCollector( collectorFactory ); - } - - protected static class Factory - extends AbstractLuceneCodecAwareSearchQueryElementFactory, - F, - AbstractLuceneNumericFieldCodec> { - - protected Factory(AbstractLuceneNumericFieldCodec codec) { - super( codec ); - } - - @Override - public FieldMetricAggregationBuilder create(LuceneSearchIndexScope scope, - LuceneSearchIndexValueFieldContext field) { - return new Builder( scope, field ); - } - } - - protected static class Builder extends AbstractBuilder implements FieldMetricAggregationBuilder { - public Builder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFieldContext field) { - super( scope, field ); - } - - @Override - public AbstractLuceneMetricNumericLongAggregation build() { - return new LuceneCountDistinctNumericLongAggregation( this ); - } - } -} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java index b35fd6dc169..cf745941c90 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java @@ -12,50 +12,28 @@ import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationExtractContext; import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; import org.hibernate.search.backend.lucene.search.aggregation.impl.LuceneSearchAggregation; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexCompositeNodeContext; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexNodeContext; import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; import org.hibernate.search.engine.search.aggregation.spi.CountDocumentAggregationBuilder; import org.hibernate.search.engine.search.common.spi.SearchQueryElementFactory; public class LuceneCountDocumentAggregation implements LuceneSearchAggregation { - public static Factory factory() { - return Factory.INSTANCE; - } - private final Set indexNames; - LuceneCountDocumentAggregation(Builder builder) { + private LuceneCountDocumentAggregation(Builder builder) { this.indexNames = builder.scope.hibernateSearchIndexNames(); } - @Override - public Extractor request(AggregationRequestContext context) { - CountDocuemntsCollectorFactory collectorFactory = CountDocuemntsCollectorFactory.instance(); - var collectorKey = collectorFactory.getCollectorKey(); - - context.requireCollector( collectorFactory ); - return new CountDocumentsExtractor( collectorKey ); - } - - private record CountDocumentsExtractor(CollectorKey collectorKey) implements Extractor { - - @Override - public Long extract(AggregationExtractContext context) { - return context.getCollectorResults( collectorKey ); - } - } - - @Override - public Set indexNames() { - return indexNames; + public static Factory factory() { + return Factory.INSTANCE; } protected static class Factory implements SearchQueryElementFactory, - LuceneSearchIndexCompositeNodeContext> { + LuceneSearchIndexNodeContext> { private static final Factory INSTANCE = new Factory(); @@ -64,8 +42,8 @@ private Factory() { @Override public CountDocumentAggregationBuilder.TypeSelector create(LuceneSearchIndexScope scope, - LuceneSearchIndexCompositeNodeContext node) { - return new TypeSelector( scope ); + LuceneSearchIndexNodeContext node) { + return new TypeSelector( scope, node ); } @Override @@ -76,20 +54,38 @@ public void checkCompatibleWith(SearchQueryElementFactory other) { } } - protected record TypeSelector(LuceneSearchIndexScope scope) implements CountDocumentAggregationBuilder.TypeSelector { + private record TypeSelector(LuceneSearchIndexScope scope, LuceneSearchIndexNodeContext node) + implements CountDocumentAggregationBuilder.TypeSelector { + @Override - public CountDocumentAggregationBuilder type() { - return new Builder( scope ); + public CountDocumentAggregationBuilder builder() { + return new LuceneCountDocumentAggregation.Builder( scope ); } } - public static class Builder implements CountDocumentAggregationBuilder { + @Override + public Extractor request(AggregationRequestContext context) { + CountDocuemntsCollectorFactory collectorFactory = CountDocuemntsCollectorFactory.instance(); + var collectorKey = collectorFactory.getCollectorKey(); - protected final LuceneSearchIndexScope scope; + context.requireCollector( collectorFactory ); + return new CountDocumentsExtractor( collectorKey ); + } - public Builder(LuceneSearchIndexScope scope) { - this.scope = scope; + private record CountDocumentsExtractor(CollectorKey collectorKey) implements Extractor { + + @Override + public Long extract(AggregationExtractContext context) { + return context.getCollectorResults( collectorKey ); } + } + + @Override + public Set indexNames() { + return indexNames; + } + + private record Builder(LuceneSearchIndexScope scope) implements CountDocumentAggregationBuilder { @Override public LuceneCountDocumentAggregation build() { diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java deleted file mode 100644 index b9128f0eae4..00000000000 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.search.backend.lucene.types.aggregation.impl; - -import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountValuesCollectorFactory; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; -import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; -import org.hibernate.search.backend.lucene.search.common.impl.AbstractLuceneCodecAwareSearchQueryElementFactory; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexValueFieldContext; -import org.hibernate.search.backend.lucene.types.codec.impl.AbstractLuceneNumericFieldCodec; -import org.hibernate.search.engine.search.aggregation.spi.FieldMetricAggregationBuilder; - -public class LuceneCountNumericLongAggregation extends AbstractLuceneMetricNumericLongAggregation { - - public static Factory factory(AbstractLuceneNumericFieldCodec codec) { - return new Factory<>( codec ); - } - - LuceneCountNumericLongAggregation(Builder builder) { - super( builder ); - } - - @Override - void fillCollectors(JoiningLongMultiValuesSource source, AggregationRequestContext context) { - CountValuesCollectorFactory collectorFactory = new CountValuesCollectorFactory( source ); - collectorKey = collectorFactory.getCollectorKey(); - context.requireCollector( collectorFactory ); - } - - protected static class Factory - extends AbstractLuceneCodecAwareSearchQueryElementFactory, - F, - AbstractLuceneNumericFieldCodec> { - - protected Factory(AbstractLuceneNumericFieldCodec codec) { - super( codec ); - } - - @Override - public FieldMetricAggregationBuilder create(LuceneSearchIndexScope scope, - LuceneSearchIndexValueFieldContext field) { - return new Builder( scope, field ); - } - } - - protected static class Builder extends AbstractBuilder implements FieldMetricAggregationBuilder { - public Builder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFieldContext field) { - super( scope, field ); - } - - @Override - public AbstractLuceneMetricNumericLongAggregation build() { - return new LuceneCountNumericLongAggregation( this ); - } - } -} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java new file mode 100644 index 00000000000..1a7d2832e20 --- /dev/null +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java @@ -0,0 +1,97 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.backend.lucene.types.aggregation.impl; + +import java.util.function.Function; + +import org.hibernate.search.backend.lucene.logging.impl.QueryLog; +import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountDistinctValuesCollectorFactory; +import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountValuesCollectorFactory; +import org.hibernate.search.backend.lucene.lowlevel.collector.impl.CollectorFactory; +import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; +import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexNodeContext; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexValueFieldContext; +import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder; +import org.hibernate.search.engine.search.common.spi.SearchQueryElementFactory; + +public class LuceneCountValuesAggregation extends AbstractLuceneMetricNumericLongAggregation { + private final Function> collectorFactorySupplier; + + LuceneCountValuesAggregation(Builder builder) { + super( builder ); + collectorFactorySupplier = builder.collectorFactorySupplier; + } + + public static Factory factory() { + return Factory.INSTANCE; + } + + protected static class Factory + implements + SearchQueryElementFactory, + LuceneSearchIndexNodeContext> { + + private static final Factory INSTANCE = new Factory(); + + private Factory() { + } + + @Override + public CountValuesAggregationBuilder.TypeSelector create(LuceneSearchIndexScope scope, + LuceneSearchIndexNodeContext node) { + return new TypeSelector( scope, node ); + } + + @Override + public void checkCompatibleWith(SearchQueryElementFactory other) { + if ( !getClass().equals( other.getClass() ) ) { + throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() ); + } + } + } + + private record TypeSelector(LuceneSearchIndexScope scope, LuceneSearchIndexNodeContext node) + implements CountValuesAggregationBuilder.TypeSelector { + + @Override + public CountValuesAggregationBuilder builder() { + return new Builder( scope, node.toValueField() ); + } + } + + @Override + void fillCollectors(JoiningLongMultiValuesSource source, AggregationRequestContext context) { + var collectorFactory = collectorFactorySupplier.apply( source ); + collectorKey = collectorFactory.getCollectorKey(); + context.requireCollector( collectorFactory ); + } + + protected static class Builder extends AbstractBuilder implements CountValuesAggregationBuilder { + private Function> collectorFactorySupplier; + + public Builder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFieldContext field) { + super( scope, field ); + collectorFactorySupplier = CountValuesCollectorFactory::new; + } + + @Override + public void distinct(boolean distinct) { + if ( distinct ) { + collectorFactorySupplier = CountDistinctValuesCollectorFactory::new; + } + else { + collectorFactorySupplier = CountValuesCollectorFactory::new; + } + } + + @Override + public AbstractLuceneMetricNumericLongAggregation build() { + return new LuceneCountValuesAggregation( this ); + } + } +} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java index 19cd2204aab..df03a39702d 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java @@ -195,7 +195,7 @@ protected CountBuilder(AbstractLuceneNumericFieldCodec codec, Function scope, LuceneSearchIndexValueFieldContext field) { super( scope, field, codec, convertAndEncode, LuceneSearchAggregation.from( scope, - LuceneCountDocumentAggregation.factory().create( scope, null ).type().build() ), + LuceneCountDocumentAggregation.factory().create( scope, field ).builder().build() ), new ArrayList<>(), new ArrayList<>() ); } } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java index b070e7b7977..43b2bdf3b30 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java @@ -196,7 +196,8 @@ private CountBuilder(AbstractLuceneNumericFieldCodec codec, LuceneSearchIn ProjectionConverter fromFieldValueConverter, Function decoder) { super( codec, scope, field, LuceneSearchAggregation.from( scope, - LuceneCountDocumentAggregation.factory().create( scope, null ).type().build() ), fromFieldValueConverter, + LuceneCountDocumentAggregation.factory().create( scope, field ).builder().build() ), + fromFieldValueConverter, decoder ); } } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java index d0980d10457..c44123112c7 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java @@ -176,7 +176,7 @@ private CountBuilder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFiel ProjectionConverter fromFieldValueConverter) { super( scope, field, LuceneSearchAggregation.from( scope, - LuceneCountDocumentAggregation.factory().create( scope, null ).type().build() ), + LuceneCountDocumentAggregation.factory().create( scope, field ).builder().build() ), fromFieldValueConverter ); } } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java index 250387a6fba..b360775be48 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java @@ -8,8 +8,7 @@ import org.hibernate.search.backend.lucene.search.predicate.impl.LucenePredicateTypeKeys; import org.hibernate.search.backend.lucene.search.projection.impl.LuceneFieldProjection; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneAvgNumericFieldAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountDistinctNumericLongAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountNumericLongAggregation; +import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountValuesAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMaxNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMinNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneNumericRangeAggregation; @@ -96,9 +95,7 @@ public LuceneIndexValueFieldType toIndexFieldType() { builder.queryElementFactory( AggregationTypeKeys.SUM, sumMetricAggregationFactory( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MIN, LuceneMinNumericFieldAggregation.factory( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MAX, LuceneMaxNumericFieldAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_VALUES, LuceneCountNumericLongAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_DISTINCT_VALUES, - LuceneCountDistinctNumericLongAggregation.factory( codec ) ); + builder.queryElementFactory( AggregationTypeKeys.COUNT, LuceneCountValuesAggregation.factory() ); builder.queryElementFactory( AggregationTypeKeys.AVG, avgMetricAggregationFactory( codec ) ); } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java index 08e8311752f..65fe0985e5b 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java @@ -9,8 +9,7 @@ import org.hibernate.search.backend.lucene.search.predicate.impl.LucenePredicateTypeKeys; import org.hibernate.search.backend.lucene.search.projection.impl.LuceneFieldProjection; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneAvgNumericFieldAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountDistinctNumericLongAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountNumericLongAggregation; +import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountValuesAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMaxNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMinNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneNumericRangeAggregation; @@ -102,9 +101,7 @@ public LuceneIndexValueFieldType toIndexFieldType() { } builder.queryElementFactory( AggregationTypeKeys.MIN, LuceneMinNumericFieldAggregation.factory( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MAX, LuceneMaxNumericFieldAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_VALUES, LuceneCountNumericLongAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_DISTINCT_VALUES, - LuceneCountDistinctNumericLongAggregation.factory( codec ) ); + builder.queryElementFactory( AggregationTypeKeys.COUNT, LuceneCountValuesAggregation.factory() ); builder.queryElementFactory( AggregationTypeKeys.AVG, LuceneAvgNumericFieldAggregation.factory( codec ) ); } diff --git a/documentation/src/main/asciidoc/migration/index.adoc b/documentation/src/main/asciidoc/migration/index.adoc index 26a50389cbf..79fdff8db3e 100644 --- a/documentation/src/main/asciidoc/migration/index.adoc +++ b/documentation/src/main/asciidoc/migration/index.adoc @@ -84,8 +84,7 @@ The https://hibernate.org/community/compatibility-policy/#code-categorization[AP in Hibernate Search {hibernateSearchVersion} is, in general, backward-compatible with Hibernate Search {hibernateSearchPreviousStableVersionShort}. -* Metic aggregations `count()` and `countDistinct()` are deprecated in favor of more -descriptive `countValues()` and `countDistinctValues()`, as these aggregations are counting the field values rather than documents. +* Metic aggregation `countDistinct()` is deprecated in favor of an option in the `count()` aggregation: `.count().field(..).distinct()`. [[spi]] == SPI diff --git a/documentation/src/main/asciidoc/public/reference/_search-dsl-aggregation.adoc b/documentation/src/main/asciidoc/public/reference/_search-dsl-aggregation.adoc index 8e5d13b20ba..217a9a5fddf 100644 --- a/documentation/src/main/asciidoc/public/reference/_search-dsl-aggregation.adoc +++ b/documentation/src/main/asciidoc/public/reference/_search-dsl-aggregation.adoc @@ -355,8 +355,9 @@ but that can be < Define the target field path to which you want to apply the aggregation function and the expected returned type. ==== -=== Count documents metric aggregation +=== Count metric aggregation + +The count aggregation allows counting either the documents that matched or field values. The `count documents` aggregation counts the number of documents. While it is usually discouraged to use this aggregation at the root level, @@ -424,11 +427,10 @@ this aggregation can still be useful in defining aggregation values in other, mo ---- include::{sourcedir}/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java[tags=count-documents] ---- -<1> Apply the document count aggregation. For this function a `Long.class` value is always returned. +<1> Start building the counts aggregation by calling `.count()`. This aggregation always return a `Long.class` value. +<2> Request the document count. ==== -=== Count values metric aggregation - The `count values` aggregation counts the number of non-empty field values. This aggregation mostly make sense when the aggregated field is multivalued. For single-valued fields this aggregation would result in the number of documents where the aggregated field is present. @@ -439,12 +441,11 @@ For single-valued fields this aggregation would result in the number of document ---- include::{sourcedir}/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java[tags=count] ---- -<1> Define the target field path to which you want to apply the aggregation function. For this function a `Long.class` value is always returned. +<1> Start building the counts aggregation by calling `.count()`. This aggregation always return a `Long.class` value. +<2> Specify the path of the field whose values to count. ==== -=== Count distinct values metric aggregation - -The `count distinct values` aggregation counts the number of unique field values. +Additionally, it is possible to count only the distinct field values. .Count the number of all different price value among all the science fiction books ==== @@ -452,7 +453,9 @@ The `count distinct values` aggregation counts the number of unique field values ---- include::{sourcedir}/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java[tags=count-distinct] ---- -<1> Define the target field path to which you want to apply the aggregation function. For this function a `Long.class` value is always returned. +<1> Start building the counts aggregation by calling `.count()`. This aggregation always return a `Long.class` value. +<2> Specify the path of the field whose values to count. +<3> Request a count of distinct values (ignoring duplicates). ==== === Avg metric aggregation diff --git a/documentation/src/test/java/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java b/documentation/src/test/java/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java index 0fe3093ffba..5ecddc44c2b 100644 --- a/documentation/src/test/java/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java +++ b/documentation/src/test/java/org/hibernate/search/documentation/search/aggregation/AggregationDslIT.java @@ -304,7 +304,7 @@ void terms_value() { .aggregation( countsByPriceKey, f -> f.terms() .field( "price", Double.class ) // <1> - .value( f.countDocuments() ) // <4> + .value( f.count().documents() ) // <4> ) .fetch( 20 ); Map countsByPrice = result.aggregation( countsByPriceKey ); @@ -442,7 +442,7 @@ void range_value() { .range( 0.0, 10.0 ) // <2> .range( 10.0, 20.0 ) .range( 20.0, null ) // <3> - .value( f.countDocuments() ) // <4> + .value( f.count().documents() ) // <4> ) .fetch( 20 ); Map, Long> countsByPrice = result.aggregation( countsByPriceKey ); @@ -753,7 +753,8 @@ void countDocuments() { AggregationKey countBooksKey = AggregationKey.of( "countBooks" ); SearchResult result = searchSession.search( Book.class ) .where( f -> f.match().field( "genre" ).matching( Genre.SCIENCE_FICTION ) ) - .aggregation( countBooksKey, f -> f.countDocuments() ) // <1> + .aggregation( countBooksKey, f -> f.count() // <1> + .documents() ) // <2> .fetch( 20 ); Long countPrices = result.aggregation( countBooksKey ); // end::count-documents[] @@ -768,7 +769,8 @@ void countValues() { AggregationKey countRatingsKey = AggregationKey.of( "countRatings" ); SearchResult result = searchSession.search( Book.class ) .where( f -> f.match().field( "genre" ).matching( Genre.SCIENCE_FICTION ) ) - .aggregation( countRatingsKey, f -> f.countValues().field( "ratings" ) ) // <1> + .aggregation( countRatingsKey, f -> f.count() // <1> + .field( "ratings" ) ) // <2> .fetch( 20 ); Long countPrices = result.aggregation( countRatingsKey ); // end::count[] @@ -783,7 +785,9 @@ void countDistinctValues() { AggregationKey countDistinctPricesKey = AggregationKey.of( "countDistinctPrices" ); SearchResult result = searchSession.search( Book.class ) .where( f -> f.match().field( "genre" ).matching( Genre.SCIENCE_FICTION ) ) - .aggregation( countDistinctPricesKey, f -> f.countDistinctValues().field( "price" ) ) // <1> + .aggregation( countDistinctPricesKey, f -> f.count() // <1> + .field( "price" ) // <2> + .distinct() ) // <3> .fetch( 20 ); Long countDistinctPrices = result.aggregation( countDistinctPricesKey ); // end::count-distinct[] @@ -852,7 +856,7 @@ record BookAggregation(Double avg, Double min, Double max, Long ratingCount) { f.avg().field( "price", Double.class ), // <2> f.min().field( "price", Double.class ), f.max().field( "price", Double.class ), - f.countValues().field( "ratings" ) + f.count().field( "ratings" ) ).asList( BookAggregation::new ) ) // <3> .fetch( 20 ); BookAggregation aggregations = result.aggregation( aggKey ); // <4> @@ -874,7 +878,7 @@ record BookAggregation(Double avg, Double min, Double max, Long ratingCount) { f.avg().field( "price", Double.class ), // <2> f.min().field( "price", Double.class ), f.max().field( "price", Double.class ), - f.countValues().field( "ratings" ) + f.count().field( "ratings" ) ).asList() ) // <3> .fetch( 20 ); List aggregations = result.aggregation( aggKey ); // <4> @@ -899,7 +903,7 @@ record BookAggregation(Double avg, Double min, Double max, Long ratingCount) { f.avg().field( "price", Double.class ), // <2> f.min().field( "price", Double.class ), f.max().field( "price", Double.class ), - f.countValues().field( "ratings" ) + f.count().field( "ratings" ) ).asArray() ) // <3> .fetch( 20 ); Object[] aggregations = result.aggregation( aggKey ); // <4> @@ -923,7 +927,7 @@ record BookAggregation(Double avg, Double min, Double max, Long ratingCount) { f.avg().field( "price", Double.class ), // <2> f.min().field( "price", Double.class ), f.max().field( "price", Double.class ), - f.countValues().field( "ratings" ) + f.count().field( "ratings" ) ) ) // <3> .fetch( 20 ); List aggregations = result.aggregation( aggKey ); // <4> diff --git a/engine/src/main/java/org/hibernate/search/engine/backend/types/IndexFieldTraits.java b/engine/src/main/java/org/hibernate/search/engine/backend/types/IndexFieldTraits.java index 70a7811f6a0..16900933a2c 100644 --- a/engine/src/main/java/org/hibernate/search/engine/backend/types/IndexFieldTraits.java +++ b/engine/src/main/java/org/hibernate/search/engine/backend/types/IndexFieldTraits.java @@ -103,19 +103,13 @@ private Aggregations() { public static final String SUM = "aggregation:sum"; public static final String MIN = "aggregation:min"; public static final String MAX = "aggregation:max"; + public static final String COUNT = "aggregation:count"; + public static final String COUNT_DOCUMENTS = "aggregation:countDocuments"; /** - * @deprecated Use {@link #COUNT_VALUES} instead. - */ - @Deprecated(since = "8.1", forRemoval = true) - public static final String COUNT = "aggregation:countValues"; - /** - * @deprecated Use {@link #COUNT_DISTINCT_VALUES} instead. + * @deprecated Use {@link #COUNT} instead. */ @Deprecated(since = "8.1", forRemoval = true) - public static final String COUNT_DISTINCT = "aggregation:countDistinctValues"; - public static final String COUNT_VALUES = "aggregation:countValues"; - public static final String COUNT_DISTINCT_VALUES = "aggregation:countDistinctValues"; - public static final String COUNT_DOCUMENTS = "aggregation:countDocuments"; + public static final String COUNT_DISTINCT = "aggregation:countDistinct"; public static final String AVG = "aggregation:avg"; } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountAggregationKindStep.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountAggregationKindStep.java new file mode 100644 index 00000000000..ca164174235 --- /dev/null +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountAggregationKindStep.java @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.engine.search.aggregation.dsl; + +import java.util.function.Function; + +import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; +import org.hibernate.search.engine.search.reference.aggregation.CountAggregationFieldReference; +import org.hibernate.search.util.common.annotation.Incubating; + +/** + * The initial step in a "count" aggregation definition, where the kind of the aggregation can be picked. + * + * @param Scope root type. + * @param The type of factory used to create predicates in {@link AggregationFilterStep#filter(Function)}. + */ +@Incubating +public interface CountAggregationKindStep> { + + /** + * Count documents that match the query. + *

+ * This aggregation may be useful for building {@link SearchAggregationFactory#range()} or {@link SearchAggregationFactory#terms()} aggregations. + * + * @return The next step. + */ + @Incubating + CountDocumentsAggregationFinalStep documents(); + + /** + * Count the number of non-empty values for the given field. + *

+ * For a multi-valued field, the resulting count + * may be greater than the number of matched documents. + * + * @param fieldPath The path to the index field to aggregate. + * @return The next step. + */ + @Incubating + CountValuesAggregationOptionsStep field(String fieldPath); + + /** + * Count the number of non-empty values for the given field. + *

+ * For a multi-valued field, the resulting count + * may be greater than the number of matched documents. + * + * @param fieldReference The field reference representing a definition of the index field to aggregate. + * @return The next step. + */ + @Incubating + default CountValuesAggregationOptionsStep field(CountAggregationFieldReference fieldReference) { + return field( fieldReference.absolutePath() ); + } +} diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountDistinctValuesAggregationFieldStep.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountDistinctValuesAggregationFieldStep.java index a5661cc6e35..ff7b30881a1 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountDistinctValuesAggregationFieldStep.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountDistinctValuesAggregationFieldStep.java @@ -7,7 +7,7 @@ import java.util.function.Function; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; -import org.hibernate.search.engine.search.reference.aggregation.CountValuesAggregationFieldReference; +import org.hibernate.search.engine.search.reference.aggregation.CountAggregationFieldReference; import org.hibernate.search.util.common.annotation.Incubating; /** @@ -34,8 +34,7 @@ public interface CountDistinctValuesAggregationFieldStep field( - CountValuesAggregationFieldReference fieldReference) { + default CountDistinctValuesAggregationOptionsStep field(CountAggregationFieldReference fieldReference) { return field( fieldReference.absolutePath() ); } } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationFieldStep.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationFieldStep.java index 0f6a699173e..ba3932d858c 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationFieldStep.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationFieldStep.java @@ -7,7 +7,7 @@ import java.util.function.Function; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; -import org.hibernate.search.engine.search.reference.aggregation.CountValuesAggregationFieldReference; +import org.hibernate.search.engine.search.reference.aggregation.CountAggregationFieldReference; import org.hibernate.search.util.common.annotation.Incubating; /** @@ -34,7 +34,7 @@ public interface CountValuesAggregationFieldStep field(CountValuesAggregationFieldReference fieldReference) { + default CountValuesAggregationOptionsStep field(CountAggregationFieldReference fieldReference) { return field( fieldReference.absolutePath() ); } } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationOptionsStep.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationOptionsStep.java index f11ce3cd017..2a609ad699d 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationOptionsStep.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/CountValuesAggregationOptionsStep.java @@ -23,4 +23,19 @@ public interface CountValuesAggregationOptionsStep< PDF extends TypedSearchPredicateFactory> extends AggregationFinalStep, AggregationFilterStep { + /** + * Count only distinct field values. + * + * @return The next step. + */ + default S distinct() { + return distinct( true ); + } + + /** + * Specify whether to count distinct or all field values. + * @param distinct Use {@code true} if only distinct field values should be counted, {@code false} otherwise. + * @return The next step. + */ + S distinct(boolean distinct); } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/ExtendedSearchAggregationFactory.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/ExtendedSearchAggregationFactory.java index dfbaad2d0c5..e0eb6c9e5ee 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/ExtendedSearchAggregationFactory.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/ExtendedSearchAggregationFactory.java @@ -7,6 +7,7 @@ import java.util.function.Function; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; +import org.hibernate.search.util.common.annotation.Incubating; /** * A base interface for subtypes of {@link TypedSearchAggregationFactory} allowing to @@ -43,28 +44,14 @@ public interface ExtendedSearchAggregationFactory< @Override MaxAggregationFieldStep max(); - @SuppressWarnings("removal") - @Deprecated(since = "8.1", forRemoval = true) - @Override - default CountValuesAggregationFieldStep count() { - return countValues(); - } - + @Incubating @Override - CountValuesAggregationFieldStep countValues(); + CountAggregationKindStep count(); @SuppressWarnings("removal") @Deprecated(since = "8.1", forRemoval = true) @Override - default CountDistinctValuesAggregationFieldStep countDistinct() { - return countDistinctValues(); - } - - @Override - CountDistinctValuesAggregationFieldStep countDistinctValues(); - - @Override - CountDocumentsAggregationFinalStep countDocuments(); + CountDistinctValuesAggregationFieldStep countDistinct(); @Override AvgAggregationFieldStep avg(); diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/SearchAggregationFactory.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/SearchAggregationFactory.java index 52cb1a5e599..4b8b571a4e0 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/SearchAggregationFactory.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/SearchAggregationFactory.java @@ -103,33 +103,16 @@ public interface SearchAggregationFactory { MaxAggregationFieldStep max(); /** - * Perform the count values metric aggregation. + * Perform the count metric aggregation. *

- * Counts the number of non-empty field values. - *

- * As this aggregation counts the field values for a multi-valued fields the resulting count - * may be greater as the number of the matched documents. + * The following steps allow defining the kind of the count aggregation: + * {@link CountAggregationKindStep#documents() count documents} + * or {@link CountAggregationKindStep#field(String) count values}. * * @return The next step. - * @deprecated Use {@link #countValues()} instead. */ - @Deprecated(since = "8.1", forRemoval = true) @Incubating - default CountValuesAggregationFieldStep count() { - return countValues(); - } - - /** - * Perform the count values metric aggregation. - *

- * Counts the number of non-empty field values. - *

- * As this aggregation counts the field values for a multi-valued fields the resulting count - * may be greater as the number of the matched documents. - * - * @return The next step. - */ - CountValuesAggregationFieldStep countValues(); + CountAggregationKindStep count(); /** * Perform the count distinct values metric aggregation. @@ -137,34 +120,11 @@ public interface SearchAggregationFactory { * Counts the number of unique field values. * * @return The next step. - * @deprecated Use {@link #countDistinctValues()} instead. + * @deprecated Use {@link #count()} with {@link CountValuesAggregationOptionsStep#distinct()} instead. */ @Deprecated(since = "8.1", forRemoval = true) @Incubating - default CountDistinctValuesAggregationFieldStep countDistinct() { - return countDistinctValues(); - } - - /** - * Perform the count distinct values metric aggregation. - *

- * Counts the number of unique field values. - * - * @return The next step. - */ - @Incubating - CountDistinctValuesAggregationFieldStep countDistinctValues(); - - /** - * Perform the count documents metric aggregation. - *

- * Counts the number of matched documents. - * This aggregation may be useful for building {@link #range()} or {@link #terms()} aggregations. - * - * @return The next step. - */ - @Incubating - CountDocumentsAggregationFinalStep countDocuments(); + CountDistinctValuesAggregationFieldStep countDistinct(); /** * Perform the count distinct values metric aggregation. diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/TypedSearchAggregationFactory.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/TypedSearchAggregationFactory.java index 3139f2eab7f..67d3c3bff80 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/TypedSearchAggregationFactory.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/TypedSearchAggregationFactory.java @@ -106,37 +106,17 @@ public interface TypedSearchAggregationFactory extends SearchAggregationFact /** - * Perform the count values metric aggregation. + * Perform the count metric aggregation. *

- * Counts the number of non-empty field values. - *

- * As this aggregation counts the field values for a multi-valued fields the resulting count - * may be greater as the number of the matched documents. + * The following steps allow defining the kind of the count aggregation: + * {@link CountAggregationKindStep#documents() count documents} + * or {@link CountAggregationKindStep#field(String) count values}. * * @return The next step. - * @deprecated Use {@link #countValues()} instead. */ - @SuppressWarnings("removal") - @Deprecated(since = "8.1", forRemoval = true) @Incubating @Override - default CountValuesAggregationFieldStep count() { - return countValues(); - } - - /** - * Perform the count values metric aggregation. - *

- * Counts the number of non-empty field values. - *

- * As this aggregation counts the field values for a multi-valued fields the resulting count - * may be greater as the number of the matched documents. - * - * @return The next step. - */ - @Override - @Incubating - CountValuesAggregationFieldStep countValues(); + CountAggregationKindStep count(); /** * Perform the count distinct values metric aggregation. @@ -144,38 +124,13 @@ public interface TypedSearchAggregationFactory extends SearchAggregationFact * Counts the number of unique field values. * * @return The next step. - * @deprecated Use {@link #countDistinctValues()} instead. + * @deprecated Use {@link #count()} with {@link CountValuesAggregationOptionsStep#distinct()} instead. */ @SuppressWarnings("removal") @Deprecated(since = "8.1", forRemoval = true) @Incubating @Override - default CountDistinctValuesAggregationFieldStep countDistinct() { - return countDistinctValues(); - } - - /** - * Perform the count distinct values metric aggregation. - *

- * Counts the number of unique field values. - * - * @return The next step. - */ - @Override - @Incubating - CountDistinctValuesAggregationFieldStep countDistinctValues(); - - /** - * Perform the count documents metric aggregation. - *

- * Counts the number of matched documents. - * This aggregation may be useful for building {@link #range()} or {@link #terms()} aggregations. - * - * @return The next step. - */ - @Override - @Incubating - CountDocumentsAggregationFinalStep countDocuments(); + CountDistinctValuesAggregationFieldStep countDistinct(); /** * Perform the avg metric aggregation. diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationFieldStepImpl.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountAggregationKindStepImpl.java similarity index 50% rename from engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationFieldStepImpl.java rename to engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountAggregationKindStepImpl.java index 3f890b8b6d3..a80f1cbb4c2 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationFieldStepImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountAggregationKindStepImpl.java @@ -4,25 +4,31 @@ */ package org.hibernate.search.engine.search.aggregation.dsl.impl; -import org.hibernate.search.engine.search.aggregation.dsl.CountValuesAggregationFieldStep; +import org.hibernate.search.engine.search.aggregation.dsl.CountAggregationKindStep; +import org.hibernate.search.engine.search.aggregation.dsl.CountDocumentsAggregationFinalStep; import org.hibernate.search.engine.search.aggregation.dsl.CountValuesAggregationOptionsStep; import org.hibernate.search.engine.search.aggregation.dsl.spi.SearchAggregationDslContext; import org.hibernate.search.engine.search.aggregation.spi.AggregationTypeKeys; -import org.hibernate.search.engine.search.aggregation.spi.SearchFilterableAggregationBuilder; +import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; -public class CountValuesAggregationFieldStepImpl> - implements CountValuesAggregationFieldStep { +public class CountAggregationKindStepImpl> + implements CountAggregationKindStep { private final SearchAggregationDslContext dslContext; - public CountValuesAggregationFieldStepImpl(SearchAggregationDslContext dslContext) { + public CountAggregationKindStepImpl(SearchAggregationDslContext dslContext) { this.dslContext = dslContext; } + @Override + public CountDocumentsAggregationFinalStep documents() { + return new CountDocumentsAggregationFinalStepImpl( dslContext ); + } + @Override public CountValuesAggregationOptionsStep field(String fieldPath) { - SearchFilterableAggregationBuilder builder = dslContext.scope() - .fieldQueryElement( fieldPath, AggregationTypeKeys.COUNT_VALUES ); + CountValuesAggregationBuilder builder = dslContext.scope() + .fieldQueryElement( fieldPath, AggregationTypeKeys.COUNT ).builder(); return new CountValuesAggregationOptionsStepImpl<>( builder, dslContext ); } } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationFieldStepImpl.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationFieldStepImpl.java index d98d0ffbaeb..568b4a93450 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationFieldStepImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationFieldStepImpl.java @@ -8,9 +8,11 @@ import org.hibernate.search.engine.search.aggregation.dsl.CountDistinctValuesAggregationOptionsStep; import org.hibernate.search.engine.search.aggregation.dsl.spi.SearchAggregationDslContext; import org.hibernate.search.engine.search.aggregation.spi.AggregationTypeKeys; -import org.hibernate.search.engine.search.aggregation.spi.SearchFilterableAggregationBuilder; +import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; +@SuppressWarnings("removal") +@Deprecated(since = "8.1", forRemoval = true) public class CountDistinctValuesAggregationFieldStepImpl> implements CountDistinctValuesAggregationFieldStep { private final SearchAggregationDslContext dslContext; @@ -21,8 +23,9 @@ public CountDistinctValuesAggregationFieldStepImpl(SearchAggregationDslContext field(String fieldPath) { - SearchFilterableAggregationBuilder builder = dslContext.scope() - .fieldQueryElement( fieldPath, AggregationTypeKeys.COUNT_DISTINCT_VALUES ); + CountValuesAggregationBuilder builder = dslContext.scope() + .fieldQueryElement( fieldPath, AggregationTypeKeys.COUNT ).builder(); + builder.distinct( true ); return new CountDistinctValuesAggregationOptionsStepImpl<>( builder, dslContext ); } } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationOptionsStepImpl.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationOptionsStepImpl.java index f776f109a61..2668041d1b6 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationOptionsStepImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDistinctValuesAggregationOptionsStepImpl.java @@ -14,6 +14,7 @@ import org.hibernate.search.engine.search.predicate.dsl.PredicateFinalStep; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; +@Deprecated(since = "8.1", forRemoval = true) class CountDistinctValuesAggregationOptionsStepImpl> implements CountDistinctValuesAggregationOptionsStep, PDF> { private final SearchFilterableAggregationBuilder builder; diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDocumentsAggregationFinalStepImpl.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDocumentsAggregationFinalStepImpl.java index ef32043df96..ab88f60642f 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDocumentsAggregationFinalStepImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountDocumentsAggregationFinalStepImpl.java @@ -8,18 +8,18 @@ import org.hibernate.search.engine.search.aggregation.dsl.CountDocumentsAggregationFinalStep; import org.hibernate.search.engine.search.aggregation.dsl.spi.SearchAggregationDslContext; import org.hibernate.search.engine.search.aggregation.spi.AggregationTypeKeys; +import org.hibernate.search.engine.search.aggregation.spi.CountDocumentAggregationBuilder; public class CountDocumentsAggregationFinalStepImpl implements CountDocumentsAggregationFinalStep { - private final SearchAggregationDslContext dslContext; + private final CountDocumentAggregationBuilder builder; public CountDocumentsAggregationFinalStepImpl(SearchAggregationDslContext dslContext) { - this.dslContext = dslContext; + this.builder = dslContext.scope().rootQueryElement( AggregationTypeKeys.COUNT_DOCUMENTS ).builder(); } @Override public SearchAggregation toAggregation() { - return dslContext.scope() - .rootQueryElement( AggregationTypeKeys.COUNT_DOCUMENTS ).type().build(); + return builder.build(); } } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationOptionsStepImpl.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationOptionsStepImpl.java index b1547ef39f3..1f6f45d1442 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationOptionsStepImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/impl/CountValuesAggregationOptionsStepImpl.java @@ -9,17 +9,17 @@ import org.hibernate.search.engine.search.aggregation.SearchAggregation; import org.hibernate.search.engine.search.aggregation.dsl.CountValuesAggregationOptionsStep; import org.hibernate.search.engine.search.aggregation.dsl.spi.SearchAggregationDslContext; -import org.hibernate.search.engine.search.aggregation.spi.SearchFilterableAggregationBuilder; +import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder; import org.hibernate.search.engine.search.predicate.SearchPredicate; import org.hibernate.search.engine.search.predicate.dsl.PredicateFinalStep; import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory; class CountValuesAggregationOptionsStepImpl> implements CountValuesAggregationOptionsStep, PDF> { - private final SearchFilterableAggregationBuilder builder; + private final CountValuesAggregationBuilder builder; private final SearchAggregationDslContext dslContext; - CountValuesAggregationOptionsStepImpl(SearchFilterableAggregationBuilder builder, + CountValuesAggregationOptionsStepImpl(CountValuesAggregationBuilder builder, SearchAggregationDslContext dslContext) { this.builder = builder; this.dslContext = dslContext; @@ -42,4 +42,10 @@ public CountValuesAggregationOptionsStepImpl filter(SearchPredicate sea public SearchAggregation toAggregation() { return builder.build(); } + + @Override + public CountValuesAggregationOptionsStepImpl distinct(boolean distinct) { + builder.distinct( distinct ); + return this; + } } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/spi/AbstractSearchAggregationFactory.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/spi/AbstractSearchAggregationFactory.java index 39a53b954f4..f90cfbb8d18 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/spi/AbstractSearchAggregationFactory.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/dsl/spi/AbstractSearchAggregationFactory.java @@ -12,9 +12,8 @@ import org.hibernate.search.engine.search.aggregation.dsl.AggregationFinalStep; import org.hibernate.search.engine.search.aggregation.dsl.AvgAggregationFieldStep; import org.hibernate.search.engine.search.aggregation.dsl.CompositeAggregationInnerStep; +import org.hibernate.search.engine.search.aggregation.dsl.CountAggregationKindStep; import org.hibernate.search.engine.search.aggregation.dsl.CountDistinctValuesAggregationFieldStep; -import org.hibernate.search.engine.search.aggregation.dsl.CountDocumentsAggregationFinalStep; -import org.hibernate.search.engine.search.aggregation.dsl.CountValuesAggregationFieldStep; import org.hibernate.search.engine.search.aggregation.dsl.ExtendedSearchAggregationFactory; import org.hibernate.search.engine.search.aggregation.dsl.MaxAggregationFieldStep; import org.hibernate.search.engine.search.aggregation.dsl.MinAggregationFieldStep; @@ -24,9 +23,8 @@ import org.hibernate.search.engine.search.aggregation.dsl.TermsAggregationFieldStep; import org.hibernate.search.engine.search.aggregation.dsl.impl.AvgAggregationFieldStepImpl; import org.hibernate.search.engine.search.aggregation.dsl.impl.CompositeAggregationInnerStepImpl; +import org.hibernate.search.engine.search.aggregation.dsl.impl.CountAggregationKindStepImpl; import org.hibernate.search.engine.search.aggregation.dsl.impl.CountDistinctValuesAggregationFieldStepImpl; -import org.hibernate.search.engine.search.aggregation.dsl.impl.CountDocumentsAggregationFinalStepImpl; -import org.hibernate.search.engine.search.aggregation.dsl.impl.CountValuesAggregationFieldStepImpl; import org.hibernate.search.engine.search.aggregation.dsl.impl.MaxAggregationFieldStepImpl; import org.hibernate.search.engine.search.aggregation.dsl.impl.MinAggregationFieldStepImpl; import org.hibernate.search.engine.search.aggregation.dsl.impl.RangeAggregationFieldStepImpl; @@ -76,20 +74,17 @@ public MaxAggregationFieldStep max() { } @Override - public CountValuesAggregationFieldStep countValues() { - return new CountValuesAggregationFieldStepImpl<>( dslContext ); + public CountAggregationKindStep count() { + return new CountAggregationKindStepImpl<>( dslContext ); } + @SuppressWarnings("removal") + @Deprecated(since = "8.1", forRemoval = true) @Override - public CountDistinctValuesAggregationFieldStep countDistinctValues() { + public CountDistinctValuesAggregationFieldStep countDistinct() { return new CountDistinctValuesAggregationFieldStepImpl<>( dslContext ); } - @Override - public CountDocumentsAggregationFinalStep countDocuments() { - return new CountDocumentsAggregationFinalStepImpl( dslContext ); - } - public AvgAggregationFieldStep avg() { return new AvgAggregationFieldStepImpl<>( dslContext ); } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/AggregationTypeKeys.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/AggregationTypeKeys.java index 3edc3e6a5e5..ed866c08f3b 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/AggregationTypeKeys.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/AggregationTypeKeys.java @@ -24,14 +24,10 @@ private AggregationTypeKeys() { of( IndexFieldTraits.Aggregations.MIN ); public static final SearchQueryElementTypeKey MAX = of( IndexFieldTraits.Aggregations.MAX ); - public static final SearchQueryElementTypeKey> COUNT_VALUES = - of( IndexFieldTraits.Aggregations.COUNT_VALUES ); - public static final SearchQueryElementTypeKey> COUNT_DISTINCT_VALUES = - of( IndexFieldTraits.Aggregations.COUNT_DISTINCT_VALUES ); - public static final SearchQueryElementTypeKey AVG = - of( IndexFieldTraits.Aggregations.AVG ); + public static final SearchQueryElementTypeKey COUNT = + of( IndexFieldTraits.Aggregations.COUNT ); public static final SearchQueryElementTypeKey COUNT_DOCUMENTS = of( IndexFieldTraits.Aggregations.COUNT_DOCUMENTS ); - - + public static final SearchQueryElementTypeKey AVG = + of( IndexFieldTraits.Aggregations.AVG ); } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountDocumentAggregationBuilder.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountDocumentAggregationBuilder.java index 29c7a79f423..0d143f17da0 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountDocumentAggregationBuilder.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountDocumentAggregationBuilder.java @@ -5,9 +5,7 @@ package org.hibernate.search.engine.search.aggregation.spi; public interface CountDocumentAggregationBuilder extends SearchAggregationBuilder { - interface TypeSelector { - CountDocumentAggregationBuilder type(); + CountDocumentAggregationBuilder builder(); } - } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountValuesAggregationBuilder.java b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountValuesAggregationBuilder.java new file mode 100644 index 00000000000..e0a8f1387c3 --- /dev/null +++ b/engine/src/main/java/org/hibernate/search/engine/search/aggregation/spi/CountValuesAggregationBuilder.java @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.engine.search.aggregation.spi; + +public interface CountValuesAggregationBuilder extends SearchFilterableAggregationBuilder { + interface TypeSelector { + CountValuesAggregationBuilder builder(); + } + + void distinct(boolean distinct); + +} diff --git a/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/AnyAggregationReference.java b/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/AnyAggregationReference.java index e8886faf11c..a85285d48fd 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/AnyAggregationReference.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/AnyAggregationReference.java @@ -26,8 +26,7 @@ public record AnyAggregationReference( String absolutePath, Class scopeRootType, ValueModel valueModel, Class aggregationType) implements AvgAggregationFieldReference, - CountValuesAggregationFieldReference, - CountDistinctValuesAggregationFieldReference, + CountAggregationFieldReference, MaxAggregationFieldReference, MinAggregationFieldReference, RangeAggregationFieldReference, diff --git a/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountValuesAggregationFieldReference.java b/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountAggregationFieldReference.java similarity index 70% rename from engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountValuesAggregationFieldReference.java rename to engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountAggregationFieldReference.java index 7b1fd725532..68e64836aab 100644 --- a/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountValuesAggregationFieldReference.java +++ b/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountAggregationFieldReference.java @@ -7,5 +7,5 @@ import org.hibernate.search.util.common.annotation.Incubating; @Incubating -public interface CountValuesAggregationFieldReference extends AggregationFieldReference { +public interface CountAggregationFieldReference extends AggregationFieldReference { } diff --git a/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountDistinctValuesAggregationFieldReference.java b/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountDistinctValuesAggregationFieldReference.java deleted file mode 100644 index bce6e722387..00000000000 --- a/engine/src/main/java/org/hibernate/search/engine/search/reference/aggregation/CountDistinctValuesAggregationFieldReference.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.search.engine.search.reference.aggregation; - -import org.hibernate.search.util.common.annotation.Incubating; - -@Incubating -public interface CountDistinctValuesAggregationFieldReference extends AggregationFieldReference { -} diff --git a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricNumericFieldsAggregationsIT.java b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricNumericFieldsAggregationsIT.java index 0d6c297aefe..035855ddd7b 100644 --- a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricNumericFieldsAggregationsIT.java +++ b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricNumericFieldsAggregationsIT.java @@ -190,10 +190,10 @@ private SearchQuery defineAggregations( .aggregation( maxIntegers, f -> f.max().field( "integer", Integer.class ) ) .aggregation( maxIntegersAsString, f -> f.max().field( "integer", String.class, ValueModel.STRING ) ) .aggregation( maxConverted, f -> f.max().field( "converted", String.class ) ) - .aggregation( countIntegers, f -> f.countValues().field( "integer" ) ) - .aggregation( countConverted, f -> f.countValues().field( "converted" ) ) - .aggregation( countDistinctIntegers, f -> f.countDistinctValues().field( "integer" ) ) - .aggregation( countDistinctConverted, f -> f.countDistinctValues().field( "converted" ) ) + .aggregation( countIntegers, f -> f.count().field( "integer" ) ) + .aggregation( countConverted, f -> f.count().field( "converted" ).distinct( false ) ) + .aggregation( countDistinctIntegers, f -> f.count().field( "integer" ).distinct() ) + .aggregation( countDistinctConverted, f -> f.count().field( "converted" ).distinct( true ) ) .aggregation( avgIntegers, f -> f.avg().field( "integer", Integer.class ) ) .aggregation( avgIntegersAsString, f -> f.avg().field( "integer", String.class, ValueModel.STRING ) ) .aggregation( avgConverted, f -> f.avg().field( "converted", String.class ) ) @@ -211,10 +211,9 @@ private SearchQuery defineAggregations( .aggregation( avgFloats, f -> f.avg().field( "floatF", Float.class ) ) .aggregation( avgBigIntegers, f -> f.avg().field( "bigInteger", BigInteger.class ) ) .aggregation( avgBigDecimals, f -> f.avg().field( "bigDecimal", BigDecimal.class ) ) - .aggregation( countDocuments, f -> f.countDocuments() ) - .aggregation( countDistinctValuesIntegerMultiValued, - f -> f.countDistinctValues().field( "integerMultiValued" ) ) - .aggregation( countValuesIntegerMultiValued, f -> f.countValues().field( "integerMultiValued" ) ) + .aggregation( countDocuments, f -> f.count().documents() ) + .aggregation( countDistinctValuesIntegerMultiValued, f -> f.count().field( "integerMultiValued" ).distinct() ) + .aggregation( countValuesIntegerMultiValued, f -> f.count().field( "integerMultiValued" ) ) .toQuery(); } diff --git a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricTemporalFieldsAggregationsIT.java b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricTemporalFieldsAggregationsIT.java index 0175d77251f..77db0c5f034 100644 --- a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricTemporalFieldsAggregationsIT.java +++ b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/MetricTemporalFieldsAggregationsIT.java @@ -121,10 +121,10 @@ private SearchQuery defineAggregations( .aggregation( minConverted, f -> f.min().field( "converted", String.class ) ) .aggregation( maxDates, f -> f.max().field( "date", LocalDate.class ) ) .aggregation( maxConverted, f -> f.max().field( "converted", String.class ) ) - .aggregation( countDates, f -> f.countValues().field( "date" ) ) - .aggregation( countConverted, f -> f.countValues().field( "converted" ) ) - .aggregation( countDistinctDates, f -> f.countDistinctValues().field( "date" ) ) - .aggregation( countDistinctConverted, f -> f.countDistinctValues().field( "converted" ) ) + .aggregation( countDates, f -> f.count().field( "date" ) ) + .aggregation( countConverted, f -> f.count().field( "converted" ).distinct( false ) ) + .aggregation( countDistinctDates, f -> f.count().field( "date" ).distinct() ) + .aggregation( countDistinctConverted, f -> f.count().field( "converted" ).distinct( true ) ) .aggregation( avgDates, f -> f.avg().field( "date", LocalDate.class ) ) .aggregation( avgConverted, f -> f.avg().field( "converted", String.class ) ) .toQuery(); diff --git a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/RangeAggregationSpecificsIT.java b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/RangeAggregationSpecificsIT.java index f3f4ed92a33..3e980e6a7a6 100644 --- a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/RangeAggregationSpecificsIT.java +++ b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/RangeAggregationSpecificsIT.java @@ -575,7 +575,7 @@ void rangesBucket_countDocuments(FieldTypeDescriptor fieldType, DataSet Range.canonical( null, dataSet.ascendingValues.get( 3 ) ), Range.canonical( dataSet.ascendingValues.get( 3 ), dataSet.ascendingValues.get( 5 ) ), Range.canonical( dataSet.ascendingValues.get( 5 ), null ) - ) ).value( f.countDocuments() ) + ) ).value( f.count().documents() ) ) .routing( dataSet.name ) .toQuery() @@ -686,7 +686,7 @@ void rangesBucket_countValues(FieldTypeDescriptor fieldType, DataSet da Range.canonical( dataSet.ascendingValues.get( 3 ), dataSet.ascendingValues.get( 5 ) ), Range.canonical( dataSet.ascendingValues.get( 5 ), null ) - ) ).value( f.countValues().field( index.binding().bucketMultiValue.relativeFieldName ) ) + ) ).value( f.count().field( index.binding().bucketMultiValue.relativeFieldName ) ) ) .routing( dataSet.name ) .toQuery() @@ -726,8 +726,8 @@ void rangesBucket_countDistinctValues(FieldTypeDescriptor fieldType, DataS dataSet.ascendingValues.get( 5 ) ), Range.canonical( dataSet.ascendingValues.get( 5 ), null ) ) ) - .value( f.countDistinctValues() - .field( index.binding().bucketMultiValue.relativeFieldName ) ) + .value( f.count().field( index.binding().bucketMultiValue.relativeFieldName ) + .distinct() ) ) .routing( dataSet.name ) .toQuery() @@ -895,7 +895,7 @@ void rangesBucket_composite_single(FieldTypeDescriptor fieldType, DataSet< .ranges( Arrays.asList( Range.canonical( null, dataSet.ascendingValues.get( 5 ) ), Range.canonical( dataSet.ascendingValues.get( 5 ), null ) - ) ).value( f.composite().from( f.countDocuments() ).asList() ) + ) ).value( f.composite().from( f.count().documents() ).asList() ) ) .routing( dataSet.name ) .toQuery() @@ -928,7 +928,7 @@ void rangesBucket_composite_double(FieldTypeDescriptor fieldType, DataSet< .ranges( Arrays.asList( Range.canonical( null, dataSet.ascendingValues.get( 5 ) ), Range.canonical( dataSet.ascendingValues.get( 5 ), null ) - ) ).value( f.composite().from( f.countDocuments(), f.countDocuments() ).asList() ) + ) ).value( f.composite().from( f.count().documents(), f.count().documents() ).asList() ) ) .routing( dataSet.name ) .toQuery() @@ -962,7 +962,8 @@ void rangesBucket_composite_triple(FieldTypeDescriptor fieldType, DataSet< Range.canonical( null, dataSet.ascendingValues.get( 5 ) ), Range.canonical( dataSet.ascendingValues.get( 5 ), null ) ) ) - .value( f.composite().from( f.countDocuments(), f.countDocuments(), f.countDocuments() ) + .value( f.composite() + .from( f.count().documents(), f.count().documents(), f.count().documents() ) .asArray() ) ) .routing( dataSet.name ) @@ -998,8 +999,8 @@ void rangesBucket_composite_quad(FieldTypeDescriptor fieldType, DataSet Range.canonical( dataSet.ascendingValues.get( 5 ), null ) ) ) .value( (AggregationFinalStep) f.composite() - .from( f.countDocuments(), f.countDocuments(), f.countDocuments(), - f.countDocuments() ) + .from( f.count().documents(), f.count().documents(), f.count().documents(), + f.count().documents() ) .asArray( arr -> (Long) arr[0] ) ) ) .routing( dataSet.name ) @@ -1038,9 +1039,8 @@ record MyRecord(Long countDoc, Long countValue) { Range.canonical( dataSet.ascendingValues.get( 5 ), null ) ) ) .value( f.composite() - .from( f.countDocuments(), - f.countValues() - .field( index.binding().bucketMultiValue.relativeFieldName ) ) + .from( f.count().documents(), + f.count().field( index.binding().bucketMultiValue.relativeFieldName ) ) .as( MyRecord::new ) ) ) .routing( dataSet.name ) diff --git a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/TermsAggregationSpecificsIT.java b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/TermsAggregationSpecificsIT.java index 07b6ba00f8c..2bc45bb61bf 100644 --- a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/TermsAggregationSpecificsIT.java +++ b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/search/aggregation/TermsAggregationSpecificsIT.java @@ -622,7 +622,7 @@ void terms_explicitDocCount(FieldTypeDescriptor fieldType, DataSet data assertThatQuery( matchAllQuery() .aggregation( aggregationKey, f -> f.terms().field( fieldPath, fieldType.getJavaType() ) - .value( f.countDocuments() ) + .value( f.count().documents() ) ) .routing( dataSet.name ) ) .aggregation( diff --git a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/testsupport/operations/MetricAggregationsTestCase.java b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/testsupport/operations/MetricAggregationsTestCase.java index 0e273c4d8ff..ea925211e7d 100644 --- a/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/testsupport/operations/MetricAggregationsTestCase.java +++ b/integrationtest/backend/tck/src/main/java/org/hibernate/search/integrationtest/backend/tck/testsupport/operations/MetricAggregationsTestCase.java @@ -79,8 +79,8 @@ public Result testMetricsAggregation(StubMappingScope scope, SingleFieldI .where( SearchPredicateFactory::matchAll ) .aggregation( result.minKey, f -> f.min().field( fieldPath, javaClass, valueModel ) ) .aggregation( result.maxKey, f -> f.max().field( fieldPath, javaClass, valueModel ) ) - .aggregation( result.countKey, f -> f.countValues().field( fieldPath ) ) - .aggregation( result.countDistinctKey, f -> f.countDistinctValues().field( fieldPath ) ) + .aggregation( result.countKey, f -> f.count().field( fieldPath ) ) + .aggregation( result.countDistinctKey, f -> f.count().field( fieldPath ).distinct() ) .aggregation( result.avgKey, f -> f.avg().field( fieldPath, javaClass, valueModel ) ); if ( metricAggregationsValues.sum() != null ) { diff --git a/integrationtest/metamodel/orm-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/elasticsearch/AggregationTypesIT.java b/integrationtest/metamodel/orm-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/elasticsearch/AggregationTypesIT.java index 62cb701a504..e84a623f7dc 100644 --- a/integrationtest/metamodel/orm-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/elasticsearch/AggregationTypesIT.java +++ b/integrationtest/metamodel/orm-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/elasticsearch/AggregationTypesIT.java @@ -62,9 +62,9 @@ void smoke() { .aggregation( AggregationKey.of( "sum" ), f -> f.sum().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) .aggregation( AggregationKey.of( "count" ), - f -> f.countValues().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) .aggregation( AggregationKey.of( "countDistinct" ), - f -> f.countDistinctValues().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ).distinct() ) .aggregation( AggregationKey.of( "min" ), f -> f.min().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) .aggregation( AggregationKey.of( "max" ), diff --git a/integrationtest/metamodel/orm-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/lucene/AggregationTypesIT.java b/integrationtest/metamodel/orm-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/lucene/AggregationTypesIT.java index b40c251b40f..e4a096eb76a 100644 --- a/integrationtest/metamodel/orm-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/lucene/AggregationTypesIT.java +++ b/integrationtest/metamodel/orm-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/orm/lucene/AggregationTypesIT.java @@ -62,9 +62,9 @@ void smoke() { .aggregation( AggregationKey.of( "sum" ), f -> f.sum().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) .aggregation( AggregationKey.of( "count" ), - f -> f.countValues().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) .aggregation( AggregationKey.of( "countDistinct" ), - f -> f.countDistinctValues().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ).distinct() ) .aggregation( AggregationKey.of( "min" ), f -> f.min().field( AggregationTypesIT_IndexedEntity__.INDEX.myNumber ) ) .aggregation( AggregationKey.of( "max" ), diff --git a/integrationtest/metamodel/standalone-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/elasticsearch/AggregationTypesIT.java b/integrationtest/metamodel/standalone-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/elasticsearch/AggregationTypesIT.java index 866a75a3515..5fec31bf5f7 100644 --- a/integrationtest/metamodel/standalone-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/elasticsearch/AggregationTypesIT.java +++ b/integrationtest/metamodel/standalone-elasticsearch/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/elasticsearch/AggregationTypesIT.java @@ -83,9 +83,9 @@ void smoke() { .aggregation( AggregationKey.of( "sum" ), f -> f.sum().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) .aggregation( AggregationKey.of( "count" ), - f -> f.countValues().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) .aggregation( AggregationKey.of( "countDistinct" ), - f -> f.countDistinctValues().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.number ).distinct() ) .aggregation( AggregationKey.of( "min" ), f -> f.min().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) .aggregation( AggregationKey.of( "max" ), diff --git a/integrationtest/metamodel/standalone-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/lucene/AggregationTypesIT.java b/integrationtest/metamodel/standalone-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/lucene/AggregationTypesIT.java index 9938ce4e99d..4620a40bf74 100644 --- a/integrationtest/metamodel/standalone-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/lucene/AggregationTypesIT.java +++ b/integrationtest/metamodel/standalone-lucene/src/test/java/org/hibernate/search/integrationtest/metamodel/standalone/lucene/AggregationTypesIT.java @@ -83,9 +83,9 @@ void smoke() { .aggregation( AggregationKey.of( "sum" ), f -> f.sum().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) .aggregation( AggregationKey.of( "count" ), - f -> f.countValues().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) .aggregation( AggregationKey.of( "countDistinct" ), - f -> f.countDistinctValues().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) + f -> f.count().field( AggregationTypesIT_IndexedEntity__.INDEX.number ).distinct() ) .aggregation( AggregationKey.of( "min" ), f -> f.min().field( AggregationTypesIT_IndexedEntity__.INDEX.number ) ) .aggregation( AggregationKey.of( "max" ), diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java index e25d1f619c4..163b40db4ba 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneMultiIndexSearchIndexCompositeNodeContext.java @@ -7,6 +7,7 @@ import java.util.List; import org.hibernate.search.engine.search.common.spi.AbstractMultiIndexSearchIndexCompositeNodeContext; +import org.hibernate.search.engine.search.common.spi.SearchIndexSchemaElementContextHelper; public final class LuceneMultiIndexSearchIndexCompositeNodeContext extends AbstractMultiIndexSearchIndexCompositeNodeContext< @@ -36,6 +37,11 @@ protected LuceneSearchIndexCompositeNodeTypeContext typeOf(LuceneSearchIndexComp return indexElement.type(); } + @Override + public LuceneSearchIndexValueFieldContext toValueField() { + return SearchIndexSchemaElementContextHelper.throwingToValueField( this ); + } + @Override protected LuceneSearchIndexNodeContext childInScope(String childRelativeName) { return scope.child( this, childRelativeName ); diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java index 94ad9be84c6..556adf378df 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/common/impl/LuceneSearchIndexNodeContext.java @@ -15,4 +15,7 @@ public interface LuceneSearchIndexNodeContext @Override LuceneSearchIndexCompositeNodeContext toObjectField(); + @Override + LuceneSearchIndexValueFieldContext toValueField(); + } diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java deleted file mode 100644 index f83e3d09acc..00000000000 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDistinctNumericLongAggregation.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.search.backend.lucene.types.aggregation.impl; - -import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountDistinctValuesCollectorFactory; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; -import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; -import org.hibernate.search.backend.lucene.search.common.impl.AbstractLuceneCodecAwareSearchQueryElementFactory; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexValueFieldContext; -import org.hibernate.search.backend.lucene.types.codec.impl.AbstractLuceneNumericFieldCodec; -import org.hibernate.search.engine.search.aggregation.spi.FieldMetricAggregationBuilder; - -public class LuceneCountDistinctNumericLongAggregation extends AbstractLuceneMetricNumericLongAggregation { - - public static Factory factory(AbstractLuceneNumericFieldCodec codec) { - return new Factory<>( codec ); - } - - LuceneCountDistinctNumericLongAggregation(Builder builder) { - super( builder ); - } - - @Override - void fillCollectors(JoiningLongMultiValuesSource source, AggregationRequestContext context) { - CountDistinctValuesCollectorFactory collectorFactory = new CountDistinctValuesCollectorFactory( source ); - collectorKey = collectorFactory.getCollectorKey(); - context.requireCollector( collectorFactory ); - } - - protected static class Factory - extends AbstractLuceneCodecAwareSearchQueryElementFactory, - F, - AbstractLuceneNumericFieldCodec> { - - protected Factory(AbstractLuceneNumericFieldCodec codec) { - super( codec ); - } - - @Override - public FieldMetricAggregationBuilder create(LuceneSearchIndexScope scope, - LuceneSearchIndexValueFieldContext field) { - return new Builder( scope, field ); - } - } - - protected static class Builder extends AbstractBuilder implements FieldMetricAggregationBuilder { - public Builder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFieldContext field) { - super( scope, field ); - } - - @Override - public AbstractLuceneMetricNumericLongAggregation build() { - return new LuceneCountDistinctNumericLongAggregation( this ); - } - } -} diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java index b35fd6dc169..329581300b2 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountDocumentAggregation.java @@ -12,50 +12,28 @@ import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationExtractContext; import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; import org.hibernate.search.backend.lucene.search.aggregation.impl.LuceneSearchAggregation; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexCompositeNodeContext; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexNodeContext; import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; import org.hibernate.search.engine.search.aggregation.spi.CountDocumentAggregationBuilder; import org.hibernate.search.engine.search.common.spi.SearchQueryElementFactory; public class LuceneCountDocumentAggregation implements LuceneSearchAggregation { - public static Factory factory() { - return Factory.INSTANCE; - } - private final Set indexNames; - LuceneCountDocumentAggregation(Builder builder) { + private LuceneCountDocumentAggregation(Builder builder) { this.indexNames = builder.scope.hibernateSearchIndexNames(); } - @Override - public Extractor request(AggregationRequestContext context) { - CountDocuemntsCollectorFactory collectorFactory = CountDocuemntsCollectorFactory.instance(); - var collectorKey = collectorFactory.getCollectorKey(); - - context.requireCollector( collectorFactory ); - return new CountDocumentsExtractor( collectorKey ); - } - - private record CountDocumentsExtractor(CollectorKey collectorKey) implements Extractor { - - @Override - public Long extract(AggregationExtractContext context) { - return context.getCollectorResults( collectorKey ); - } - } - - @Override - public Set indexNames() { - return indexNames; + public static Factory factory() { + return Factory.INSTANCE; } protected static class Factory implements SearchQueryElementFactory, - LuceneSearchIndexCompositeNodeContext> { + LuceneSearchIndexNodeContext> { private static final Factory INSTANCE = new Factory(); @@ -64,8 +42,8 @@ private Factory() { @Override public CountDocumentAggregationBuilder.TypeSelector create(LuceneSearchIndexScope scope, - LuceneSearchIndexCompositeNodeContext node) { - return new TypeSelector( scope ); + LuceneSearchIndexNodeContext node) { + return new TypeSelector( scope, node ); } @Override @@ -76,20 +54,38 @@ public void checkCompatibleWith(SearchQueryElementFactory other) { } } - protected record TypeSelector(LuceneSearchIndexScope scope) implements CountDocumentAggregationBuilder.TypeSelector { + private record TypeSelector(LuceneSearchIndexScope scope, LuceneSearchIndexNodeContext node) + implements CountDocumentAggregationBuilder.TypeSelector { + @Override - public CountDocumentAggregationBuilder type() { + public CountDocumentAggregationBuilder builder() { return new Builder( scope ); } } - public static class Builder implements CountDocumentAggregationBuilder { + @Override + public Extractor request(AggregationRequestContext context) { + CountDocuemntsCollectorFactory collectorFactory = CountDocuemntsCollectorFactory.instance(); + var collectorKey = collectorFactory.getCollectorKey(); - protected final LuceneSearchIndexScope scope; + context.requireCollector( collectorFactory ); + return new CountDocumentsExtractor( collectorKey ); + } - public Builder(LuceneSearchIndexScope scope) { - this.scope = scope; + private record CountDocumentsExtractor(CollectorKey collectorKey) implements Extractor { + + @Override + public Long extract(AggregationExtractContext context) { + return context.getCollectorResults( collectorKey ); } + } + + @Override + public Set indexNames() { + return indexNames; + } + + private record Builder(LuceneSearchIndexScope scope) implements CountDocumentAggregationBuilder { @Override public LuceneCountDocumentAggregation build() { diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java deleted file mode 100644 index b9128f0eae4..00000000000 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountNumericLongAggregation.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.search.backend.lucene.types.aggregation.impl; - -import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountValuesCollectorFactory; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; -import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; -import org.hibernate.search.backend.lucene.search.common.impl.AbstractLuceneCodecAwareSearchQueryElementFactory; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; -import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexValueFieldContext; -import org.hibernate.search.backend.lucene.types.codec.impl.AbstractLuceneNumericFieldCodec; -import org.hibernate.search.engine.search.aggregation.spi.FieldMetricAggregationBuilder; - -public class LuceneCountNumericLongAggregation extends AbstractLuceneMetricNumericLongAggregation { - - public static Factory factory(AbstractLuceneNumericFieldCodec codec) { - return new Factory<>( codec ); - } - - LuceneCountNumericLongAggregation(Builder builder) { - super( builder ); - } - - @Override - void fillCollectors(JoiningLongMultiValuesSource source, AggregationRequestContext context) { - CountValuesCollectorFactory collectorFactory = new CountValuesCollectorFactory( source ); - collectorKey = collectorFactory.getCollectorKey(); - context.requireCollector( collectorFactory ); - } - - protected static class Factory - extends AbstractLuceneCodecAwareSearchQueryElementFactory, - F, - AbstractLuceneNumericFieldCodec> { - - protected Factory(AbstractLuceneNumericFieldCodec codec) { - super( codec ); - } - - @Override - public FieldMetricAggregationBuilder create(LuceneSearchIndexScope scope, - LuceneSearchIndexValueFieldContext field) { - return new Builder( scope, field ); - } - } - - protected static class Builder extends AbstractBuilder implements FieldMetricAggregationBuilder { - public Builder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFieldContext field) { - super( scope, field ); - } - - @Override - public AbstractLuceneMetricNumericLongAggregation build() { - return new LuceneCountNumericLongAggregation( this ); - } - } -} diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java new file mode 100644 index 00000000000..1a7d2832e20 --- /dev/null +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneCountValuesAggregation.java @@ -0,0 +1,97 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.search.backend.lucene.types.aggregation.impl; + +import java.util.function.Function; + +import org.hibernate.search.backend.lucene.logging.impl.QueryLog; +import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountDistinctValuesCollectorFactory; +import org.hibernate.search.backend.lucene.lowlevel.aggregation.collector.impl.CountValuesCollectorFactory; +import org.hibernate.search.backend.lucene.lowlevel.collector.impl.CollectorFactory; +import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; +import org.hibernate.search.backend.lucene.search.aggregation.impl.AggregationRequestContext; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexNodeContext; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope; +import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexValueFieldContext; +import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder; +import org.hibernate.search.engine.search.common.spi.SearchQueryElementFactory; + +public class LuceneCountValuesAggregation extends AbstractLuceneMetricNumericLongAggregation { + private final Function> collectorFactorySupplier; + + LuceneCountValuesAggregation(Builder builder) { + super( builder ); + collectorFactorySupplier = builder.collectorFactorySupplier; + } + + public static Factory factory() { + return Factory.INSTANCE; + } + + protected static class Factory + implements + SearchQueryElementFactory, + LuceneSearchIndexNodeContext> { + + private static final Factory INSTANCE = new Factory(); + + private Factory() { + } + + @Override + public CountValuesAggregationBuilder.TypeSelector create(LuceneSearchIndexScope scope, + LuceneSearchIndexNodeContext node) { + return new TypeSelector( scope, node ); + } + + @Override + public void checkCompatibleWith(SearchQueryElementFactory other) { + if ( !getClass().equals( other.getClass() ) ) { + throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() ); + } + } + } + + private record TypeSelector(LuceneSearchIndexScope scope, LuceneSearchIndexNodeContext node) + implements CountValuesAggregationBuilder.TypeSelector { + + @Override + public CountValuesAggregationBuilder builder() { + return new Builder( scope, node.toValueField() ); + } + } + + @Override + void fillCollectors(JoiningLongMultiValuesSource source, AggregationRequestContext context) { + var collectorFactory = collectorFactorySupplier.apply( source ); + collectorKey = collectorFactory.getCollectorKey(); + context.requireCollector( collectorFactory ); + } + + protected static class Builder extends AbstractBuilder implements CountValuesAggregationBuilder { + private Function> collectorFactorySupplier; + + public Builder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFieldContext field) { + super( scope, field ); + collectorFactorySupplier = CountValuesCollectorFactory::new; + } + + @Override + public void distinct(boolean distinct) { + if ( distinct ) { + collectorFactorySupplier = CountDistinctValuesCollectorFactory::new; + } + else { + collectorFactorySupplier = CountValuesCollectorFactory::new; + } + } + + @Override + public AbstractLuceneMetricNumericLongAggregation build() { + return new LuceneCountValuesAggregation( this ); + } + } +} diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java index 19cd2204aab..52dcf9d6c88 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericRangeAggregation.java @@ -150,7 +150,7 @@ private TypeSelector(AbstractLuceneNumericFieldCodec codec, } public static class Builder - extends AbstractLuceneBucketAggregation.AbstractBuilder, V> + extends AbstractBuilder, V> implements RangeAggregationBuilder { private final AbstractLuceneNumericFieldCodec codec; @@ -195,7 +195,7 @@ protected CountBuilder(AbstractLuceneNumericFieldCodec codec, Function scope, LuceneSearchIndexValueFieldContext field) { super( scope, field, codec, convertAndEncode, LuceneSearchAggregation.from( scope, - LuceneCountDocumentAggregation.factory().create( scope, null ).type().build() ), + LuceneCountDocumentAggregation.factory().create( scope, field ).builder().build() ), new ArrayList<>(), new ArrayList<>() ); } } diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java index b070e7b7977..43b2bdf3b30 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneNumericTermsAggregation.java @@ -196,7 +196,8 @@ private CountBuilder(AbstractLuceneNumericFieldCodec codec, LuceneSearchIn ProjectionConverter fromFieldValueConverter, Function decoder) { super( codec, scope, field, LuceneSearchAggregation.from( scope, - LuceneCountDocumentAggregation.factory().create( scope, null ).type().build() ), fromFieldValueConverter, + LuceneCountDocumentAggregation.factory().create( scope, field ).builder().build() ), + fromFieldValueConverter, decoder ); } } diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java index d0980d10457..c44123112c7 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/aggregation/impl/LuceneTextTermsAggregation.java @@ -176,7 +176,7 @@ private CountBuilder(LuceneSearchIndexScope scope, LuceneSearchIndexValueFiel ProjectionConverter fromFieldValueConverter) { super( scope, field, LuceneSearchAggregation.from( scope, - LuceneCountDocumentAggregation.factory().create( scope, null ).type().build() ), + LuceneCountDocumentAggregation.factory().create( scope, field ).builder().build() ), fromFieldValueConverter ); } } diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java index 250387a6fba..b360775be48 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneNumericIndexFieldTypeOptionsStep.java @@ -8,8 +8,7 @@ import org.hibernate.search.backend.lucene.search.predicate.impl.LucenePredicateTypeKeys; import org.hibernate.search.backend.lucene.search.projection.impl.LuceneFieldProjection; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneAvgNumericFieldAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountDistinctNumericLongAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountNumericLongAggregation; +import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountValuesAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMaxNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMinNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneNumericRangeAggregation; @@ -96,9 +95,7 @@ public LuceneIndexValueFieldType toIndexFieldType() { builder.queryElementFactory( AggregationTypeKeys.SUM, sumMetricAggregationFactory( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MIN, LuceneMinNumericFieldAggregation.factory( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MAX, LuceneMaxNumericFieldAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_VALUES, LuceneCountNumericLongAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_DISTINCT_VALUES, - LuceneCountDistinctNumericLongAggregation.factory( codec ) ); + builder.queryElementFactory( AggregationTypeKeys.COUNT, LuceneCountValuesAggregation.factory() ); builder.queryElementFactory( AggregationTypeKeys.AVG, avgMetricAggregationFactory( codec ) ); } diff --git a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java index 08e8311752f..65fe0985e5b 100644 --- a/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java +++ b/lucene-next/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/dsl/impl/AbstractLuceneTemporalIndexFieldTypeOptionsStep.java @@ -9,8 +9,7 @@ import org.hibernate.search.backend.lucene.search.predicate.impl.LucenePredicateTypeKeys; import org.hibernate.search.backend.lucene.search.projection.impl.LuceneFieldProjection; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneAvgNumericFieldAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountDistinctNumericLongAggregation; -import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountNumericLongAggregation; +import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneCountValuesAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMaxNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneMinNumericFieldAggregation; import org.hibernate.search.backend.lucene.types.aggregation.impl.LuceneNumericRangeAggregation; @@ -102,9 +101,7 @@ public LuceneIndexValueFieldType toIndexFieldType() { } builder.queryElementFactory( AggregationTypeKeys.MIN, LuceneMinNumericFieldAggregation.factory( codec ) ); builder.queryElementFactory( AggregationTypeKeys.MAX, LuceneMaxNumericFieldAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_VALUES, LuceneCountNumericLongAggregation.factory( codec ) ); - builder.queryElementFactory( AggregationTypeKeys.COUNT_DISTINCT_VALUES, - LuceneCountDistinctNumericLongAggregation.factory( codec ) ); + builder.queryElementFactory( AggregationTypeKeys.COUNT, LuceneCountValuesAggregation.factory() ); builder.queryElementFactory( AggregationTypeKeys.AVG, LuceneAvgNumericFieldAggregation.factory( codec ) ); } diff --git a/metamodel/metamodel-processor/src/main/java/org/hibernate/search/processor/writer/impl/TraitReferenceMapping.java b/metamodel/metamodel-processor/src/main/java/org/hibernate/search/processor/writer/impl/TraitReferenceMapping.java index 474e09af463..3f542bbd7c7 100644 --- a/metamodel/metamodel-processor/src/main/java/org/hibernate/search/processor/writer/impl/TraitReferenceMapping.java +++ b/metamodel/metamodel-processor/src/main/java/org/hibernate/search/processor/writer/impl/TraitReferenceMapping.java @@ -10,8 +10,7 @@ import org.hibernate.search.engine.backend.types.IndexFieldTraits; import org.hibernate.search.engine.search.reference.aggregation.AvgAggregationFieldReference; -import org.hibernate.search.engine.search.reference.aggregation.CountDistinctValuesAggregationFieldReference; -import org.hibernate.search.engine.search.reference.aggregation.CountValuesAggregationFieldReference; +import org.hibernate.search.engine.search.reference.aggregation.CountAggregationFieldReference; import org.hibernate.search.engine.search.reference.aggregation.MaxAggregationFieldReference; import org.hibernate.search.engine.search.reference.aggregation.MinAggregationFieldReference; import org.hibernate.search.engine.search.reference.aggregation.RangeAggregationFieldReference; @@ -116,10 +115,8 @@ private TraitReferenceMapping() { traits.put( IndexFieldTraits.Aggregations.MAX, new TraitReferenceDetails( MaxAggregationFieldReference.class, "A4", TraitKind.TYPED_OUTPUT, EXTRA_PROPERTY_AGGREGATION_TYPE ) ); - traits.put( IndexFieldTraits.Aggregations.COUNT_VALUES, - new TraitReferenceDetails( CountValuesAggregationFieldReference.class, "A5", TraitKind.UNTYPED ) ); - traits.put( IndexFieldTraits.Aggregations.COUNT_DISTINCT_VALUES, - new TraitReferenceDetails( CountDistinctValuesAggregationFieldReference.class, "A6", TraitKind.UNTYPED ) ); + traits.put( IndexFieldTraits.Aggregations.COUNT, + new TraitReferenceDetails( CountAggregationFieldReference.class, "A5", TraitKind.UNTYPED ) ); traits.put( IndexFieldTraits.Aggregations.AVG, new TraitReferenceDetails( AvgAggregationFieldReference.class, "A7", TraitKind.TYPED_OUTPUT, EXTRA_PROPERTY_AGGREGATION_TYPE ) ); diff --git a/metamodel/metamodel-processor/src/test/java/org/hibernate/search/processor/writer/impl/TraitReferenceMappingTest.java b/metamodel/metamodel-processor/src/test/java/org/hibernate/search/processor/writer/impl/TraitReferenceMappingTest.java index 5c1523049c7..5ae037dc88d 100644 --- a/metamodel/metamodel-processor/src/test/java/org/hibernate/search/processor/writer/impl/TraitReferenceMappingTest.java +++ b/metamodel/metamodel-processor/src/test/java/org/hibernate/search/processor/writer/impl/TraitReferenceMappingTest.java @@ -39,6 +39,7 @@ void smoke(String traitName) { } } + @SuppressWarnings("removal") private static Stream traitNames() { Set traitNames = new HashSet<>(); traitNames.addAll( traitNames( IndexFieldTraits.Predicates.class ) ); @@ -46,6 +47,8 @@ private static Stream traitNames() { traitNames.addAll( traitNames( IndexFieldTraits.Sorts.class ) ); traitNames.addAll( traitNames( IndexFieldTraits.Aggregations.class ) ); + // this is a redundant-to-be-removed type and does not require the field reference: + traitNames.remove( IndexFieldTraits.Aggregations.COUNT_DISTINCT ); // count documents is an aggregation that does not require a field and as a result does not require the field reference: traitNames.remove( IndexFieldTraits.Aggregations.COUNT_DOCUMENTS );