Skip to content

Commit 6f1f365

Browse files
committed
HSEARCH-5426 Adjust the count aggregation DSL
1 parent 7dd276f commit 6f1f365

File tree

64 files changed

+707
-746
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+707
-746
lines changed

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/document/model/dsl/impl/ElasticsearchIndexRootBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public ElasticsearchIndexRootBuilder(ElasticsearchIndexFieldTypeFactoryProvider
8787
this.defaultDynamicType = DynamicType.create( dynamicMapping );
8888

8989
this.typeBuilder.queryElementFactory( AggregationTypeKeys.COUNT_DOCUMENTS,
90-
ElasticsearchCountDocumentAggregation.factory( false ) );
90+
ElasticsearchCountDocumentAggregation.factory() );
9191
this.addDefaultImplicitFields();
9292
}
9393

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchCountDocumentAggregation.java

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor;
88
import org.hibernate.search.backend.elasticsearch.logging.impl.ElasticsearchClientLog;
99
import org.hibernate.search.backend.elasticsearch.logging.impl.QueryLog;
10-
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexCompositeNodeContext;
10+
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexNodeContext;
1111
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope;
1212
import org.hibernate.search.backend.elasticsearch.search.query.impl.ElasticsearchSearchQueryExtractContext;
1313
import org.hibernate.search.engine.search.aggregation.AggregationKey;
@@ -28,19 +28,55 @@ public class ElasticsearchCountDocumentAggregation extends AbstractElasticsearch
2828
private static final JsonAccessor<Long> RESPONSE_ROOT_DOC_COUNT_ACCESSOR =
2929
JsonAccessor.root().property( "root_doc_count" ).property( "doc_count" ).asLong();
3030

31-
public static SearchQueryElementFactory<CountDocumentAggregationBuilder.TypeSelector,
32-
ElasticsearchSearchIndexScope<?>,
33-
ElasticsearchSearchIndexCompositeNodeContext> factory(boolean isNested) {
34-
return new ElasticsearchCountDocumentAggregation.Factory( isNested );
35-
}
36-
3731
private final boolean isNested;
3832

3933
private ElasticsearchCountDocumentAggregation(Builder builder) {
4034
super( builder );
4135
this.isNested = builder.isNested;
4236
}
4337

38+
public static SearchQueryElementFactory<CountDocumentAggregationBuilder.TypeSelector,
39+
ElasticsearchSearchIndexScope<?>,
40+
ElasticsearchSearchIndexNodeContext> factory() {
41+
return new Factory();
42+
}
43+
44+
private static class Factory
45+
implements SearchQueryElementFactory<CountDocumentAggregationBuilder.TypeSelector,
46+
ElasticsearchSearchIndexScope<?>,
47+
ElasticsearchSearchIndexNodeContext> {
48+
49+
@Override
50+
public CountDocumentAggregationBuilder.TypeSelector create(ElasticsearchSearchIndexScope<?> scope,
51+
ElasticsearchSearchIndexNodeContext node) {
52+
return new TypeSelector( scope, node );
53+
}
54+
55+
@Override
56+
public void checkCompatibleWith(SearchQueryElementFactory<?, ?, ?> other) {
57+
if ( !getClass().equals( other.getClass() ) ) {
58+
throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() );
59+
}
60+
}
61+
}
62+
63+
private static final class TypeSelector implements CountDocumentAggregationBuilder.TypeSelector {
64+
private final ElasticsearchSearchIndexScope<?> scope;
65+
private final ElasticsearchSearchIndexNodeContext node;
66+
67+
private TypeSelector(ElasticsearchSearchIndexScope<?> scope,
68+
ElasticsearchSearchIndexNodeContext node) {
69+
this.scope = scope;
70+
this.node = node; // doesn't matter in this case
71+
}
72+
73+
@Override
74+
public CountDocumentAggregationBuilder builder() {
75+
boolean isNested = node.isValueField() && !node.toValueField().nestedPathHierarchy().isEmpty();
76+
return new ElasticsearchCountDocumentAggregation.Builder( scope, isNested );
77+
}
78+
}
79+
4480
@Override
4581
public Extractor<Long> request(AggregationRequestContext context, AggregationKey<?> key, JsonObject jsonAggregations) {
4682
return new CountDocumentsExtractor( key, isNested, context.isRootContext() );
@@ -73,40 +109,6 @@ public Long extract(JsonObject aggregationResult, AggregationExtractContext cont
73109
}
74110
}
75111

76-
private static class Factory
77-
implements
78-
SearchQueryElementFactory<CountDocumentAggregationBuilder.TypeSelector,
79-
ElasticsearchSearchIndexScope<?>,
80-
ElasticsearchSearchIndexCompositeNodeContext> {
81-
private final boolean isNested;
82-
83-
public Factory(boolean isNested) {
84-
this.isNested = isNested;
85-
}
86-
87-
@Override
88-
public CountDocumentAggregationBuilder.TypeSelector create(ElasticsearchSearchIndexScope<?> scope,
89-
ElasticsearchSearchIndexCompositeNodeContext node) {
90-
return new ElasticsearchCountDocumentAggregation.TypeSelector( scope, isNested );
91-
}
92-
93-
@Override
94-
public void checkCompatibleWith(SearchQueryElementFactory<?, ?, ?> other) {
95-
if ( !getClass().equals( other.getClass() ) ) {
96-
throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() );
97-
}
98-
}
99-
}
100-
101-
private record TypeSelector(ElasticsearchSearchIndexScope<?> scope, boolean isNested)
102-
implements CountDocumentAggregationBuilder.TypeSelector {
103-
104-
@Override
105-
public CountDocumentAggregationBuilder type() {
106-
return new Builder( scope, isNested );
107-
}
108-
}
109-
110112
private static class Builder extends AbstractBuilder<Long>
111113
implements CountDocumentAggregationBuilder {
112114
private final boolean isNested;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.search.backend.elasticsearch.search.aggregation.impl;
6+
7+
import java.util.List;
8+
9+
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor;
10+
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonElementTypes;
11+
import org.hibernate.search.backend.elasticsearch.logging.impl.QueryLog;
12+
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexNodeContext;
13+
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope;
14+
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexValueFieldContext;
15+
import org.hibernate.search.backend.elasticsearch.search.predicate.impl.ElasticsearchSearchPredicate;
16+
import org.hibernate.search.engine.search.aggregation.AggregationKey;
17+
import org.hibernate.search.engine.search.aggregation.spi.CountValuesAggregationBuilder;
18+
import org.hibernate.search.engine.search.common.spi.SearchQueryElementFactory;
19+
20+
import com.google.gson.JsonElement;
21+
import com.google.gson.JsonObject;
22+
23+
public class ElasticsearchCountValuesAggregation extends AbstractElasticsearchNestableAggregation<Long> {
24+
25+
private static final JsonAccessor<JsonObject> COUNT_PROPERTY_ACCESSOR =
26+
JsonAccessor.root().property( "value_count" ).asObject();
27+
28+
private static final JsonAccessor<JsonObject> COUNT_DISTINCT_PROPERTY_ACCESSOR =
29+
JsonAccessor.root().property( "cardinality" ).asObject();
30+
31+
private static final JsonAccessor<String> FIELD_PROPERTY_ACCESSOR =
32+
JsonAccessor.root().property( "field" ).asString();
33+
34+
private final String absoluteFieldPath;
35+
private final JsonAccessor<JsonObject> operation;
36+
37+
private ElasticsearchCountValuesAggregation(Builder builder) {
38+
super( builder );
39+
this.absoluteFieldPath = builder.field.absolutePath();
40+
this.operation = builder.operation;
41+
}
42+
43+
public static SearchQueryElementFactory<CountValuesAggregationBuilder.TypeSelector,
44+
ElasticsearchSearchIndexScope<?>,
45+
ElasticsearchSearchIndexNodeContext> factory() {
46+
return new Factory();
47+
}
48+
49+
private static class Factory
50+
implements SearchQueryElementFactory<CountValuesAggregationBuilder.TypeSelector,
51+
ElasticsearchSearchIndexScope<?>,
52+
ElasticsearchSearchIndexNodeContext> {
53+
54+
@Override
55+
public CountValuesAggregationBuilder.TypeSelector create(ElasticsearchSearchIndexScope<?> scope,
56+
ElasticsearchSearchIndexNodeContext node) {
57+
return new TypeSelector( scope, node );
58+
}
59+
60+
@Override
61+
public void checkCompatibleWith(SearchQueryElementFactory<?, ?, ?> other) {
62+
if ( !getClass().equals( other.getClass() ) ) {
63+
throw QueryLog.INSTANCE.differentImplementationClassForQueryElement( getClass(), other.getClass() );
64+
}
65+
}
66+
}
67+
68+
private static final class TypeSelector implements CountValuesAggregationBuilder.TypeSelector {
69+
private final ElasticsearchSearchIndexScope<?> scope;
70+
private final ElasticsearchSearchIndexNodeContext node;
71+
72+
private TypeSelector(ElasticsearchSearchIndexScope<?> scope,
73+
ElasticsearchSearchIndexNodeContext node) {
74+
this.scope = scope;
75+
this.node = node; // doesn't matter in this case
76+
}
77+
78+
@Override
79+
public CountValuesAggregationBuilder builder() {
80+
return new ElasticsearchCountValuesAggregation.Builder( scope, node.toValueField() );
81+
}
82+
}
83+
84+
@Override
85+
protected final JsonObject doRequest(AggregationRequestBuildingContextContext context) {
86+
JsonObject outerObject = new JsonObject();
87+
JsonObject innerObject = new JsonObject();
88+
89+
operation.set( outerObject, innerObject );
90+
FIELD_PROPERTY_ACCESSOR.set( innerObject, absoluteFieldPath );
91+
return outerObject;
92+
}
93+
94+
@Override
95+
protected Extractor<Long> extractor(AggregationKey<?> key, AggregationRequestBuildingContextContext context) {
96+
return new MetricLongExtractor( key, nestedPathHierarchy, filter );
97+
}
98+
99+
private static class MetricLongExtractor extends AbstractExtractor<Long> {
100+
protected MetricLongExtractor(
101+
AggregationKey<?> key, List<String> nestedPathHierarchy,
102+
ElasticsearchSearchPredicate filter
103+
) {
104+
super( key, nestedPathHierarchy, filter );
105+
}
106+
107+
@Override
108+
protected Long doExtract(JsonObject aggregationResult, AggregationExtractContext context) {
109+
JsonElement value = aggregationResult.get( "value" );
110+
return JsonElementTypes.LONG.fromElement( value );
111+
}
112+
}
113+
114+
private static class Builder extends AbstractBuilder<Long>
115+
implements CountValuesAggregationBuilder {
116+
private JsonAccessor<JsonObject> operation;
117+
118+
private Builder(ElasticsearchSearchIndexScope<?> scope, ElasticsearchSearchIndexValueFieldContext<?> field) {
119+
super( scope, field );
120+
this.operation = COUNT_PROPERTY_ACCESSOR;
121+
}
122+
123+
@Override
124+
public ElasticsearchCountValuesAggregation build() {
125+
return new ElasticsearchCountValuesAggregation( this );
126+
}
127+
128+
@Override
129+
public void distinct(boolean distinct) {
130+
if ( distinct ) {
131+
operation = COUNT_DISTINCT_PROPERTY_ACCESSOR;
132+
}
133+
else {
134+
operation = COUNT_PROPERTY_ACCESSOR;
135+
}
136+
}
137+
}
138+
}

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchMetricLongAggregation.java

Lines changed: 0 additions & 110 deletions
This file was deleted.

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchRangeAggregation.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ protected CountBuilder(ElasticsearchSearchIndexScope<?> scope,
138138
Function<? super K, JsonElement> encoder) {
139139
super( scope, field, encoder, new ArrayList<>(), new JsonArray(),
140140
ElasticsearchSearchAggregation.from( scope,
141-
ElasticsearchCountDocumentAggregation.factory( !field.nestedPathHierarchy().isEmpty() )
142-
.create( scope, null ).type().build() ) );
141+
ElasticsearchCountDocumentAggregation.factory().create( scope, field ).builder().build() ) );
143142
}
144143
}
145144

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/aggregation/impl/ElasticsearchTermsAggregation.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,7 @@ protected CountBuilder(ElasticsearchSearchIndexScope<?> scope,
163163
ProjectionConverter<T, ? extends K> fromFieldValueConverter) {
164164
super( scope, field, decodeFunction, fromFieldValueConverter,
165165
ElasticsearchSearchAggregation.from( scope,
166-
ElasticsearchCountDocumentAggregation.factory( !field.nestedPathHierarchy().isEmpty() )
167-
.create( scope, null ).type().build() ) );
166+
ElasticsearchCountDocumentAggregation.factory().create( scope, field ).builder().build() ) );
168167
}
169168
}
170169

0 commit comments

Comments
 (0)