Skip to content

Commit f68d76a

Browse files
committed
HSEARCH-4806 Parameterized sorts
1 parent 9023250 commit f68d76a

File tree

20 files changed

+336
-18
lines changed

20 files changed

+336
-18
lines changed

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/query/impl/ElasticsearchSearchQueryBuilder.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import static org.hibernate.search.util.common.impl.CollectionHelper.notInTheOtherSet;
1111

1212
import java.lang.invoke.MethodHandles;
13+
import java.util.ArrayList;
1314
import java.util.Collections;
1415
import java.util.HashMap;
1516
import java.util.HashSet;
1617
import java.util.LinkedHashMap;
18+
import java.util.List;
1719
import java.util.Map;
1820
import java.util.Set;
1921
import java.util.concurrent.TimeUnit;
@@ -74,10 +76,10 @@ public class ElasticsearchSearchQueryBuilder<H>
7476
private final SearchLoadingContextBuilder<?, ?> loadingContextBuilder;
7577
private final ElasticsearchSearchProjection<H> rootProjection;
7678
private final Integer scrollTimeout;
77-
7879
private final Set<String> routingKeys;
7980
private ElasticsearchSearchPredicate elasticsearchPredicate;
8081
private JsonArray jsonSort;
82+
private List<ElasticsearchSearchSort> elasticsearchSearchSorts;
8183
private Map<DistanceSortKey, Integer> distanceSorts;
8284
private Map<AggregationKey<?>, ElasticsearchSearchAggregation<?>> aggregations;
8385
private Long timeoutValue;
@@ -114,14 +116,15 @@ public ElasticsearchSearchQueryBuilder(
114116

115117
@Override
116118
public void predicate(SearchPredicate predicate) {
117-
ElasticsearchSearchPredicate elasticsearchPredicate = ElasticsearchSearchPredicate.from( scope, predicate );
118-
this.elasticsearchPredicate = elasticsearchPredicate;
119+
this.elasticsearchPredicate = ElasticsearchSearchPredicate.from( scope, predicate );
119120
}
120121

121122
@Override
122123
public void sort(SearchSort sort) {
123-
ElasticsearchSearchSort elasticsearchSort = ElasticsearchSearchSort.from( scope, sort );
124-
elasticsearchSort.toJsonSorts( this );
124+
if ( elasticsearchSearchSorts == null ) {
125+
elasticsearchSearchSorts = new ArrayList<>();
126+
}
127+
elasticsearchSearchSorts.add( ElasticsearchSearchSort.from( scope, sort ) );
125128
}
126129

127130
@Override
@@ -250,6 +253,12 @@ public ElasticsearchSearchQuery<H> build() {
250253
payload.add( "query", jsonQuery );
251254
}
252255

256+
if ( elasticsearchSearchSorts != null ) {
257+
for ( ElasticsearchSearchSort elasticsearchSearchSort : elasticsearchSearchSorts ) {
258+
elasticsearchSearchSort.toJsonSorts( this );
259+
}
260+
}
261+
253262
if ( jsonSort != null ) {
254263
payload.add( "sort", jsonSort );
255264
}

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/sort/impl/ElasticsearchSearchSortBuilderFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.hibernate.search.engine.search.sort.spi.CompositeSortBuilder;
1212
import org.hibernate.search.engine.search.sort.spi.ScoreSortBuilder;
1313
import org.hibernate.search.engine.search.sort.spi.SearchSortBuilderFactory;
14+
import org.hibernate.search.engine.search.sort.spi.WithParametersSortBuilder;
1415

1516
import com.google.gson.JsonObject;
1617

@@ -37,6 +38,11 @@ public CompositeSortBuilder composite() {
3738
return new ElasticsearchCompositeSort.Builder( scope );
3839
}
3940

41+
@Override
42+
public WithParametersSortBuilder withParameters() {
43+
return new ElasticsearchWithParametersSort.Builder( scope );
44+
}
45+
4046
public ElasticsearchSearchSort fromJson(JsonObject jsonObject) {
4147
return new ElasticsearchUserProvidedJsonSort( scope, jsonObject );
4248
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Hibernate Search, full-text search for your domain model
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.search.backend.elasticsearch.search.sort.impl;
8+
9+
import java.util.function.Function;
10+
11+
import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope;
12+
import org.hibernate.search.engine.search.common.NamedValues;
13+
import org.hibernate.search.engine.search.sort.SearchSort;
14+
import org.hibernate.search.engine.search.sort.dsl.SortFinalStep;
15+
import org.hibernate.search.engine.search.sort.spi.WithParametersSortBuilder;
16+
17+
class ElasticsearchWithParametersSort extends AbstractElasticsearchSort {
18+
19+
private final ElasticsearchSearchIndexScope<?> scope;
20+
private final Function<? super NamedValues, ? extends SortFinalStep> sortCreator;
21+
22+
ElasticsearchWithParametersSort(Builder builder) {
23+
super( builder );
24+
scope = builder.scope;
25+
sortCreator = builder.sortCreator;
26+
}
27+
28+
@Override
29+
public void toJsonSorts(ElasticsearchSearchSortCollector collector) {
30+
SearchSort sort = sortCreator.apply( collector.getRootPredicateContext().queryParameters() ).toSort();
31+
32+
ElasticsearchSearchSort.from( scope, sort ).toJsonSorts( collector );
33+
}
34+
35+
static class Builder extends AbstractBuilder implements WithParametersSortBuilder {
36+
private Function<? super NamedValues, ? extends SortFinalStep> sortCreator;
37+
38+
Builder(ElasticsearchSearchIndexScope<?> scope) {
39+
super( scope );
40+
}
41+
42+
@Override
43+
public void creator(Function<? super NamedValues, ? extends SortFinalStep> sortCreator) {
44+
this.sortCreator = sortCreator;
45+
}
46+
47+
@Override
48+
public SearchSort build() {
49+
return new ElasticsearchWithParametersSort( this );
50+
}
51+
}
52+
}

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/query/impl/LuceneSearchQueryBuilder.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public class LuceneSearchQueryBuilder<H> implements SearchQueryBuilder<H>, Lucen
7272

7373
private LuceneSearchPredicate lucenePredicate;
7474
private List<SortField> sortFields;
75+
private List<LuceneSearchSort> luceneSearchSorts;
7576
private Map<AggregationKey<?>, LuceneSearchAggregation<?>> aggregations;
7677
private Long timeout;
7778
private TimeUnit timeUnit;
@@ -106,8 +107,10 @@ public void predicate(SearchPredicate predicate) {
106107

107108
@Override
108109
public void sort(SearchSort sort) {
109-
LuceneSearchSort luceneSort = LuceneSearchSort.from( scope, sort );
110-
luceneSort.toSortFields( this );
110+
if ( luceneSearchSorts == null ) {
111+
luceneSearchSorts = new ArrayList<>();
112+
}
113+
luceneSearchSorts.add( LuceneSearchSort.from( scope, sort ) );
111114
}
112115

113116
@Override
@@ -235,6 +238,12 @@ public LuceneSearchQuery<H> build() {
235238

236239
Query definitiveLuceneQuery = luceneQueryBuilder.build();
237240

241+
if ( luceneSearchSorts != null ) {
242+
for ( LuceneSearchSort luceneSearchSort : luceneSearchSorts ) {
243+
luceneSearchSort.toSortFields( this );
244+
}
245+
}
246+
238247
Sort luceneSort = null;
239248
if ( sortFields != null && !sortFields.isEmpty() ) {
240249
luceneSort = new Sort( sortFields.toArray( new SortField[0] ) );

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/sort/impl/LuceneSearchSortBuilderFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.hibernate.search.engine.search.sort.spi.CompositeSortBuilder;
1212
import org.hibernate.search.engine.search.sort.spi.ScoreSortBuilder;
1313
import org.hibernate.search.engine.search.sort.spi.SearchSortBuilderFactory;
14+
import org.hibernate.search.engine.search.sort.spi.WithParametersSortBuilder;
1415

1516
import org.apache.lucene.search.Sort;
1617
import org.apache.lucene.search.SortField;
@@ -38,6 +39,11 @@ public CompositeSortBuilder composite() {
3839
return new LuceneCompositeSort.Builder( scope );
3940
}
4041

42+
@Override
43+
public WithParametersSortBuilder withParameters() {
44+
return new LuceneWithParametersSort.Builder( scope );
45+
}
46+
4147
public LuceneSearchSort fromLuceneSortField(SortField luceneSortField) {
4248
return new LuceneUserProvidedLuceneSortFieldSort( scope, luceneSortField );
4349
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Hibernate Search, full-text search for your domain model
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.search.backend.lucene.search.sort.impl;
8+
9+
import java.util.function.Function;
10+
11+
import org.hibernate.search.backend.lucene.search.common.impl.LuceneSearchIndexScope;
12+
import org.hibernate.search.engine.search.common.NamedValues;
13+
import org.hibernate.search.engine.search.sort.SearchSort;
14+
import org.hibernate.search.engine.search.sort.dsl.SortFinalStep;
15+
import org.hibernate.search.engine.search.sort.spi.WithParametersSortBuilder;
16+
17+
class LuceneWithParametersSort extends AbstractLuceneSort {
18+
19+
private final LuceneSearchIndexScope<?> scope;
20+
private final Function<? super NamedValues, ? extends SortFinalStep> sortCreator;
21+
22+
LuceneWithParametersSort(Builder builder) {
23+
super( builder );
24+
scope = builder.scope;
25+
sortCreator = builder.sortCreator;
26+
}
27+
28+
@Override
29+
public void toSortFields(LuceneSearchSortCollector collector) {
30+
SearchSort sort = sortCreator.apply( collector.toPredicateRequestContext( null ).queryParameters() ).toSort();
31+
32+
LuceneSearchSort.from( scope, sort ).toSortFields( collector );
33+
}
34+
35+
static class Builder extends AbstractBuilder implements WithParametersSortBuilder {
36+
private Function<? super NamedValues, ? extends SortFinalStep> sortCreator;
37+
38+
Builder(LuceneSearchIndexScope<?> scope) {
39+
super( scope );
40+
}
41+
42+
43+
@Override
44+
public void creator(Function<? super NamedValues, ? extends SortFinalStep> sortCreator) {
45+
this.sortCreator = sortCreator;
46+
}
47+
48+
@Override
49+
public SearchSort build() {
50+
return new LuceneWithParametersSort( this );
51+
}
52+
}
53+
}

engine/src/main/java/org/hibernate/search/engine/search/sort/dsl/SearchSortFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
package org.hibernate.search.engine.search.sort.dsl;
88

99
import java.util.function.Consumer;
10+
import java.util.function.Function;
1011

12+
import org.hibernate.search.engine.search.common.NamedValues;
1113
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
1214
import org.hibernate.search.engine.spatial.GeoPoint;
1315
import org.hibernate.search.util.common.SearchException;
@@ -126,6 +128,17 @@ public interface SearchSortFactory {
126128
*/
127129
SortThenStep composite(Consumer<? super CompositeSortComponentsStep<?>> elementContributor);
128130

131+
/**
132+
* Delegating sort that creates the actual sort at query create time and provides access to query parameters.
133+
* <p>
134+
* Which sort exactly to create is defined by a function passed to the arguments of this sort.
135+
*
136+
* @param sortCreator The function defining an actual sort to apply.
137+
* @return A final DSL step in a parameterized sort definition.
138+
*/
139+
@Incubating
140+
SortThenStep withParameters(Function<? super NamedValues, ? extends SortFinalStep> sortCreator);
141+
129142
/**
130143
* Extend the current factory with the given extension,
131144
* resulting in an extended factory offering different types of sorts.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Hibernate Search, full-text search for your domain model
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.search.engine.search.sort.dsl.impl;
8+
9+
import java.util.function.Function;
10+
11+
import org.hibernate.search.engine.search.common.NamedValues;
12+
import org.hibernate.search.engine.search.sort.SearchSort;
13+
import org.hibernate.search.engine.search.sort.dsl.SortFinalStep;
14+
import org.hibernate.search.engine.search.sort.dsl.spi.AbstractSortThenStep;
15+
import org.hibernate.search.engine.search.sort.dsl.spi.SearchSortDslContext;
16+
import org.hibernate.search.engine.search.sort.spi.WithParametersSortBuilder;
17+
18+
public class WithParametersSortFinalStep extends AbstractSortThenStep {
19+
20+
private final WithParametersSortBuilder builder;
21+
22+
public WithParametersSortFinalStep(SearchSortDslContext<?, ?> dslContext,
23+
Function<? super NamedValues, ? extends SortFinalStep> sortCreator) {
24+
super( dslContext );
25+
builder = dslContext.scope().sortBuilders().withParameters();
26+
builder.creator( sortCreator );
27+
}
28+
29+
30+
@Override
31+
protected SearchSort build() {
32+
return builder.build();
33+
}
34+
35+
}

engine/src/main/java/org/hibernate/search/engine/search/sort/dsl/spi/AbstractSearchSortFactory.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
package org.hibernate.search.engine.search.sort.dsl.spi;
88

99
import java.util.function.Consumer;
10+
import java.util.function.Function;
1011

1112
import org.hibernate.search.engine.common.dsl.spi.DslExtensionState;
13+
import org.hibernate.search.engine.search.common.NamedValues;
1214
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
1315
import org.hibernate.search.engine.search.sort.SearchSort;
1416
import org.hibernate.search.engine.search.sort.dsl.CompositeSortComponentsStep;
@@ -18,12 +20,14 @@
1820
import org.hibernate.search.engine.search.sort.dsl.ScoreSortOptionsStep;
1921
import org.hibernate.search.engine.search.sort.dsl.SearchSortFactoryExtension;
2022
import org.hibernate.search.engine.search.sort.dsl.SearchSortFactoryExtensionIfSupportedStep;
23+
import org.hibernate.search.engine.search.sort.dsl.SortFinalStep;
2124
import org.hibernate.search.engine.search.sort.dsl.SortThenStep;
2225
import org.hibernate.search.engine.search.sort.dsl.impl.CompositeSortComponentsStepImpl;
2326
import org.hibernate.search.engine.search.sort.dsl.impl.DistanceSortOptionsStepImpl;
2427
import org.hibernate.search.engine.search.sort.dsl.impl.FieldSortOptionsStepImpl;
2528
import org.hibernate.search.engine.search.sort.dsl.impl.ScoreSortOptionsStepImpl;
2629
import org.hibernate.search.engine.search.sort.dsl.impl.SearchSortFactoryExtensionStep;
30+
import org.hibernate.search.engine.search.sort.dsl.impl.WithParametersSortFinalStep;
2731
import org.hibernate.search.engine.search.sort.spi.SearchSortIndexScope;
2832
import org.hibernate.search.engine.spatial.GeoPoint;
2933

@@ -73,6 +77,11 @@ public SortThenStep composite(Consumer<? super CompositeSortComponentsStep<?>> e
7377
return next;
7478
}
7579

80+
@Override
81+
public SortThenStep withParameters(Function<? super NamedValues, ? extends SortFinalStep> sortCreator) {
82+
return new WithParametersSortFinalStep( dslContext, sortCreator );
83+
}
84+
7685
@Override
7786
public <T> T extension(SearchSortFactoryExtension<T> extension) {
7887
return DslExtensionState.returnIfSupported(

engine/src/main/java/org/hibernate/search/engine/search/sort/spi/SearchSortBuilderFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ public interface SearchSortBuilderFactory {
2222

2323
CompositeSortBuilder composite();
2424

25+
WithParametersSortBuilder withParameters();
26+
2527
}

0 commit comments

Comments
 (0)