Skip to content

Commit f8eaa18

Browse files
committed
Allow IndexCoordinates in repositories
It is common to have multiple indexes with the same document structure. E.g. rolling indices over time and having a wildcard alias. Sometimes one wants to select different IndexCoordinates than specified in `@Document(indexName = "...", ...)`. Also you might want to use the same Repository to do cross cluster searches and for this need to specify the IndexCoordinates. It would therefore be helpful to support IndexCoordinates as an argument to repository methods the same way ScrollPosition, Sort and Pageable are handled. This PR is an attempt to introduce this change. I keep it as draft to get some comments I can add tests to it if we can agree on the change being valid.
1 parent 675b779 commit f8eaa18

9 files changed

+94
-37
lines changed

src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractElasticsearchRepositoryQuery.java

+9-11
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
*/
1616
package org.springframework.data.elasticsearch.repository.query;
1717

18+
import java.util.Collections;
19+
1820
import org.springframework.data.domain.PageRequest;
19-
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
20-
import org.springframework.data.elasticsearch.core.SearchHitSupport;
21-
import org.springframework.data.elasticsearch.core.SearchHits;
22-
import org.springframework.data.elasticsearch.core.SearchHitsImpl;
23-
import org.springframework.data.elasticsearch.core.TotalHitsRelation;
21+
import org.springframework.data.elasticsearch.core.*;
2422
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
2523
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
2624
import org.springframework.data.elasticsearch.core.query.Query;
@@ -32,8 +30,6 @@
3230
import org.springframework.util.Assert;
3331
import org.springframework.util.ClassUtils;
3432

35-
import java.util.Collections;
36-
3733
/**
3834
* AbstractElasticsearchRepositoryQuery
3935
*
@@ -74,15 +70,17 @@ public QueryMethod getQueryMethod() {
7470
@Override
7571
public Object execute(Object[] parameters) {
7672

77-
ParametersParameterAccessor parameterAccessor = getParameterAccessor(parameters);
73+
ElasticsearchParametersParameterAccessor parameterAccessor = getParameterAccessor(parameters);
7874
Class<?> clazz = getResultClass();
7975
Query query = createQuery(parameters);
8076

81-
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
77+
IndexCoordinates index = parameterAccessor
78+
.getIndexCoordinatesOrDefaults(elasticsearchOperations.getIndexCoordinatesFor(clazz));
8279

8380
Object result = null;
8481

8582
if (isDeleteQuery()) {
83+
index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
8684
result = countOrGetDocumentsForDelete(query, parameterAccessor);
8785
elasticsearchOperations.delete(query, clazz, index);
8886
elasticsearchOperations.indexOps(index).refresh();
@@ -158,8 +156,8 @@ private Class<?> getResultClass() {
158156
return queryMethod.getResultProcessor().getReturnedType().getDomainType();
159157
}
160158

161-
private ParametersParameterAccessor getParameterAccessor(Object[] parameters) {
162-
return new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
159+
private ElasticsearchParametersParameterAccessor getParameterAccessor(Object[] parameters) {
160+
return new ElasticsearchParametersParameterAccessor(queryMethod, parameters);
163161
}
164162

165163
@Nullable

src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractReactiveElasticsearchRepositoryQuery.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ private Object execute(ElasticsearchParameterAccessor parameterAccessor) {
9595
}
9696

9797
String indexName = queryMethod.getEntityInformation().getIndexName();
98-
IndexCoordinates index = IndexCoordinates.of(indexName);
98+
IndexCoordinates index = parameterAccessor.getIndexCoordinatesOrDefaults(IndexCoordinates.of(indexName));
9999

100100
ReactiveElasticsearchQueryExecution execution = getExecution(parameterAccessor,
101101
new ResultProcessingConverter(processor));

src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchParameterAccessor.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616
package org.springframework.data.elasticsearch.repository.query;
1717

18+
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
1819
import org.springframework.data.repository.query.ParameterAccessor;
20+
import org.springframework.lang.NonNull;
1921

2022
/**
2123
* @author Christoph Strobl
@@ -26,7 +28,9 @@ public interface ElasticsearchParameterAccessor extends ParameterAccessor {
2628
/**
2729
* Returns the raw parameter values of the underlying query method.
2830
*
29-
* @return
31+
* @return values.
3032
*/
3133
Object[] getValues();
34+
35+
IndexCoordinates getIndexCoordinatesOrDefaults(@NonNull IndexCoordinates defaults);
3236
}

src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchParameters.java

+45-10
Original file line numberDiff line numberDiff line change
@@ -16,54 +16,89 @@
1616
package org.springframework.data.elasticsearch.repository.query;
1717

1818
import java.lang.reflect.Method;
19+
import java.util.ArrayList;
1920
import java.util.List;
2021

2122
import org.springframework.core.MethodParameter;
23+
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
2224
import org.springframework.data.elasticsearch.repository.query.ElasticsearchParameters.ElasticsearchParameter;
2325
import org.springframework.data.geo.Distance;
2426
import org.springframework.data.repository.query.Parameter;
2527
import org.springframework.data.repository.query.Parameters;
28+
import org.springframework.data.util.TypeInformation;
2629

2730
/**
2831
* @author Christoph Strobl
2932
* @author Peter-Josef Meisch
3033
* @since 3.2
3134
*/
3235
public class ElasticsearchParameters extends Parameters<ElasticsearchParameters, ElasticsearchParameter> {
33-
34-
public ElasticsearchParameters(Method method) {
35-
super(method);
36-
}
36+
private final int indexCoordinatesIndex;
3737

3838
private ElasticsearchParameters(List<ElasticsearchParameter> parameters) {
3939
super(parameters);
40+
this.indexCoordinatesIndex = initIndexCoordinatesIndex();
4041
}
4142

42-
@Override
43-
protected ElasticsearchParameter createParameter(MethodParameter parameter) {
44-
return new ElasticsearchParameter(parameter);
43+
public ElasticsearchParameters(Method method, TypeInformation<?> aggregateType) {
44+
super(method, (param) -> new ElasticsearchParameter(param, aggregateType));
45+
this.indexCoordinatesIndex = initIndexCoordinatesIndex();
46+
}
47+
48+
private int initIndexCoordinatesIndex() {
49+
int index = 0;
50+
List<Integer> foundIndices = new ArrayList<>();
51+
for (ElasticsearchParameter parameter : this) {
52+
if (parameter.isIndexCoordinatesParameter()) {
53+
foundIndices.add(index);
54+
}
55+
index++;
56+
}
57+
if (foundIndices.size() > 1) {
58+
throw new IllegalArgumentException(this + " can only contain at most one IndexCoordinates parameter.");
59+
}
60+
return foundIndices.isEmpty() ? -1 : foundIndices.get(0);
4561
}
4662

4763
@Override
4864
protected ElasticsearchParameters createFrom(List<ElasticsearchParameter> parameters) {
4965
return new ElasticsearchParameters(parameters);
5066
}
5167

68+
public boolean hasIndexCoordinatesParameter() {
69+
return this.indexCoordinatesIndex != -1;
70+
}
71+
72+
public int getIndexCoordinatesIndex() {
73+
return indexCoordinatesIndex;
74+
}
75+
5276
/**
5377
* Custom {@link Parameter} implementation adding parameters of type {@link Distance} to the special ones.
5478
*
5579
* @author Christoph Strobl
5680
*/
57-
class ElasticsearchParameter extends Parameter {
81+
static class ElasticsearchParameter extends Parameter {
82+
83+
private final boolean indexCoordinatesParameter;
5884

5985
/**
6086
* Creates a new {@link ElasticsearchParameter}.
6187
*
6288
* @param parameter must not be {@literal null}.
6389
*/
64-
ElasticsearchParameter(MethodParameter parameter) {
65-
super(parameter);
90+
ElasticsearchParameter(MethodParameter parameter, TypeInformation<?> aggregateType) {
91+
super(parameter, aggregateType);
92+
this.indexCoordinatesParameter = parameter.getParameter().getType().isAssignableFrom(IndexCoordinates.class);
6693
}
6794

95+
@Override
96+
public boolean isSpecialParameter() {
97+
return isIndexCoordinatesParameter() || super.isSpecialParameter();
98+
}
99+
100+
public boolean isIndexCoordinatesParameter() {
101+
return this.indexCoordinatesParameter;
102+
}
68103
}
69104
}

src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchParametersParameterAccessor.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import java.util.Arrays;
1919
import java.util.List;
2020

21+
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
2122
import org.springframework.data.repository.query.ParametersParameterAccessor;
23+
import org.springframework.lang.NonNull;
2224

2325
/**
2426
* @author Christoph Strobl
@@ -36,13 +38,25 @@ class ElasticsearchParametersParameterAccessor extends ParametersParameterAccess
3638
* @param values must not be {@literal null}.
3739
*/
3840
ElasticsearchParametersParameterAccessor(ElasticsearchQueryMethod method, Object... values) {
39-
4041
super(method.getParameters(), values);
4142
this.values = Arrays.asList(values);
4243
}
4344

45+
@Override
46+
public ElasticsearchParameters getParameters() {
47+
return (ElasticsearchParameters) super.getParameters();
48+
}
49+
4450
@Override
4551
public Object[] getValues() {
4652
return values.toArray();
4753
}
54+
55+
@Override
56+
public IndexCoordinates getIndexCoordinatesOrDefaults(@NonNull IndexCoordinates defaults) {
57+
if (!getParameters().hasIndexCoordinatesParameter()) {
58+
return defaults;
59+
}
60+
return (IndexCoordinates) getValues()[getParameters().getIndexCoordinatesIndex()];
61+
}
4862
}

src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchQueryMethod.java

+10
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,14 @@ private String[] mapParameters(String[] source, ParameterAccessor parameterAcces
322322

323323
return fieldNames.toArray(new String[0]);
324324
}
325+
326+
@Override
327+
protected ElasticsearchParameters createParameters(Method method, TypeInformation<?> domainType) {
328+
return new ElasticsearchParameters(method, domainType);
329+
}
330+
331+
@Override
332+
public ElasticsearchParameters getParameters() {
333+
return (ElasticsearchParameters) super.getParameters();
334+
}
325335
}

src/main/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchParametersParameterAccessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ protected <T> T getValue(int index) {
8181
@Override
8282
public Object[] getValues() {
8383

84-
Object[] result = new Object[getValues().length];
84+
Object[] result = new Object[super.getValues().length];
8585
for (int i = 0; i < result.length; i++) {
8686
result[i] = getValue(i);
8787
}

src/main/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryMethod.java

+1-11
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.repository.query;
1717

18-
import static org.springframework.data.repository.util.ClassUtils.*;
18+
import static org.springframework.data.repository.util.ClassUtils.hasParameterOfType;
1919

2020
import reactor.core.publisher.Mono;
2121

@@ -102,11 +102,6 @@ protected void verifyCountQueryTypes() {
102102
}
103103
}
104104

105-
@Override
106-
protected ElasticsearchParameters createParameters(Method method) {
107-
return new ElasticsearchParameters(method);
108-
}
109-
110105
/**
111106
* Check if the given {@link org.springframework.data.repository.query.QueryMethod} receives a reactive parameter
112107
* wrapper as one of its parameters.
@@ -143,11 +138,6 @@ public boolean isStreamQuery() {
143138
return true;
144139
}
145140

146-
@Override
147-
public ElasticsearchParameters getParameters() {
148-
return (ElasticsearchParameters) super.getParameters();
149-
}
150-
151141
@Override
152142
protected boolean isAllowedGenericType(ParameterizedType methodGenericReturnType) {
153143
return super.isAllowedGenericType(methodGenericReturnType)

src/test/java/org/springframework/data/elasticsearch/repository/query/StubParameterAccessor.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717

1818
import java.util.Arrays;
1919
import java.util.Iterator;
20-
import java.util.Optional;
2120

2221
import org.springframework.data.domain.Pageable;
2322
import org.springframework.data.domain.ScrollPosition;
2423
import org.springframework.data.domain.Sort;
24+
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
2525
import org.springframework.data.repository.query.ParameterAccessor;
26+
import org.springframework.lang.NonNull;
2627

2728
/**
2829
* Simple {@link ParameterAccessor} that returns the given parameters unfiltered.
@@ -97,6 +98,11 @@ public Object[] getValues() {
9798
return this.values;
9899
}
99100

101+
@Override
102+
public IndexCoordinates getIndexCoordinatesOrDefaults(@NonNull IndexCoordinates defaults) {
103+
return defaults;
104+
}
105+
100106
/*
101107
* (non-Javadoc)
102108
* @see org.springframework.data.repository.query.ParameterAccessor#findDynamicProjection()

0 commit comments

Comments
 (0)