Skip to content

Commit 2450d57

Browse files
authored
Support different routing for each id in multiget.
Original Pull Request #1956 Closes #1954
1 parent 5e4ce56 commit 2450d57

15 files changed

+211
-40
lines changed

src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core;
1717

18+
import java.util.Collection;
1819
import java.util.List;
1920

2021
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
@@ -121,6 +122,8 @@ public interface DocumentOperations {
121122
* @param query the query defining the ids of the objects to get
122123
* @param clazz the type of the object to be returned
123124
* @return list of {@link MultiGetItem}s
125+
* @see Query#multiGetQuery(Collection)
126+
* @see Query#multiGetQueryWithRouting(List)
124127
* @since 4.1
125128
*/
126129
<T> List<MultiGetItem<T>> multiGet(Query query, Class<T> clazz);
@@ -132,6 +135,8 @@ public interface DocumentOperations {
132135
* @param clazz the type of the object to be returned
133136
* @param index the index(es) from which the objects are read.
134137
* @return list of {@link MultiGetItem}s
138+
* @see Query#multiGetQuery(Collection)
139+
* @see Query#multiGetQueryWithRouting(List)
135140
*/
136141
<T> List<MultiGetItem<T>> multiGet(Query query, Class<T> clazz, IndexCoordinates index);
137142

@@ -283,7 +288,7 @@ default void bulkUpdate(List<UpdateQuery> queries, IndexCoordinates index) {
283288

284289
/**
285290
* Delete all records matching the query.
286-
*
291+
*
287292
* @param query query defining the objects
288293
* @param clazz The entity class, must be annotated with
289294
* {@link org.springframework.data.elasticsearch.annotations.Document}

src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ public <T> T get(String id, Class<T> clazz, IndexCoordinates index) {
182182
public <T> List<MultiGetItem<T>> multiGet(Query query, Class<T> clazz, IndexCoordinates index) {
183183

184184
Assert.notNull(index, "index must not be null");
185-
Assert.notEmpty(query.getIds(), "No Id defined for Query");
186185

187186
MultiGetRequest request = requestFactory.multiGetRequest(query, clazz, index);
188187
MultiGetResponse result = execute(client -> client.mget(request, RequestOptions.DEFAULT));

src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ public <T> T get(String id, Class<T> clazz, IndexCoordinates index) {
205205
public <T> List<MultiGetItem<T>> multiGet(Query query, Class<T> clazz, IndexCoordinates index) {
206206

207207
Assert.notNull(index, "index must not be null");
208-
Assert.notEmpty(query.getIds(), "No Ids defined for Query");
209208

210209
MultiGetRequestBuilder builder = requestFactory.multiGetRequestBuilder(client, query, clazz, index);
211210

src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ default <T> Flux<T> saveAll(Iterable<T> entities, IndexCoordinates index) {
148148
* @param query the query defining the ids of the objects to get
149149
* @param clazz the type of the object to be returned, used to determine the index
150150
* @return flux with list of {@link MultiGetItem}s that contain the entities
151+
* @see Query#multiGetQuery(Collection)
152+
* @see Query#multiGetQueryWithRouting(List)
151153
* @since 4.1
152154
*/
153155
<T> Flux<MultiGetItem<T>> multiGet(Query query, Class<T> clazz);
@@ -159,6 +161,8 @@ default <T> Flux<T> saveAll(Iterable<T> entities, IndexCoordinates index) {
159161
* @param clazz the type of the object to be returned
160162
* @param index the index(es) from which the objects are read.
161163
* @return flux with list of {@link MultiGetItem}s that contain the entities
164+
* @see Query#multiGetQuery(Collection)
165+
* @see Query#multiGetQueryWithRouting(List)
162166
* @since 4.0
163167
*/
164168
<T> Flux<MultiGetItem<T>> multiGet(Query query, Class<T> clazz, IndexCoordinates index);

src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ public <T> Flux<MultiGetItem<T>> multiGet(Query query, Class<T> clazz, IndexCoor
338338
Assert.notNull(index, "Index must not be null");
339339
Assert.notNull(clazz, "Class must not be null");
340340
Assert.notNull(query, "Query must not be null");
341-
Assert.notEmpty(query.getIds(), "No Id define for Query");
342341

343342
DocumentCallback<T> callback = new ReadDocumentCallback<>(converter, clazz, index);
344343

src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -677,13 +677,13 @@ private List<MultiGetRequest.Item> getMultiRequestItems(Query searchQuery, Class
677677

678678
FetchSourceContext fetchSourceContext = getFetchSourceContext(searchQuery);
679679

680-
if (!isEmpty(searchQuery.getIds())) {
680+
if (!isEmpty(searchQuery.getIdsWithRouting())) {
681681
String indexName = index.getIndexName();
682-
for (String id : searchQuery.getIds()) {
683-
MultiGetRequest.Item item = new MultiGetRequest.Item(indexName, id);
684682

685-
if (searchQuery.getRoute() != null) {
686-
item = item.routing(searchQuery.getRoute());
683+
for (Query.IdWithRouting idWithRouting : searchQuery.getIdsWithRouting()) {
684+
MultiGetRequest.Item item = new MultiGetRequest.Item(indexName, idWithRouting.getId());
685+
if (idWithRouting.getRouting() != null) {
686+
item = item.routing(idWithRouting.getRouting());
687687
}
688688

689689
// note: multiGet does not have fields, need to set sourceContext to filter

src/main/java/org/springframework/data/elasticsearch/core/query/AbstractQuery.java renamed to src/main/java/org/springframework/data/elasticsearch/core/query/BaseQuery.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,23 @@
1616
package org.springframework.data.elasticsearch.core.query;
1717

1818
import static java.util.Collections.*;
19+
import static org.springframework.util.CollectionUtils.*;
1920

2021
import java.time.Duration;
2122
import java.util.ArrayList;
2223
import java.util.Collection;
24+
import java.util.Collections;
2325
import java.util.List;
2426
import java.util.Optional;
27+
import java.util.stream.Collectors;
2528

2629
import org.springframework.data.domain.Pageable;
2730
import org.springframework.data.domain.Sort;
2831
import org.springframework.lang.Nullable;
2932
import org.springframework.util.Assert;
3033

3134
/**
32-
* AbstractQuery
35+
* BaseQuery
3336
*
3437
* @author Rizwan Idrees
3538
* @author Mohsin Husen
@@ -40,7 +43,7 @@
4043
* @author Peter-Josef Meisch
4144
* @author Peer Mueller
4245
*/
43-
abstract class AbstractQuery implements Query {
46+
public class BaseQuery implements Query {
4447

4548
protected Pageable pageable = DEFAULT_PAGE;
4649
@Nullable protected Sort sort;
@@ -63,6 +66,7 @@ abstract class AbstractQuery implements Query {
6366
@Nullable private List<Object> searchAfter;
6467
protected List<RescorerQuery> rescorerQueries = new ArrayList<>();
6568
@Nullable protected Boolean requestCache;
69+
private List<IdWithRouting> idsWithRouting = Collections.emptyList();
6670

6771
@Override
6872
@Nullable
@@ -81,7 +85,7 @@ public final <T extends Query> T setPageable(Pageable pageable) {
8185
Assert.notNull(pageable, "Pageable must not be null!");
8286

8387
this.pageable = pageable;
84-
return (T) this.addSort(pageable.getSort());
88+
return this.addSort(pageable.getSort());
8589
}
8690

8791
@Override
@@ -116,7 +120,7 @@ public SourceFilter getSourceFilter() {
116120

117121
@Override
118122
@SuppressWarnings("unchecked")
119-
public final <T extends Query> T addSort(Sort sort) {
123+
public final <T extends Query> T addSort(@Nullable Sort sort) {
120124
if (sort == null) {
121125
return (T) this;
122126
}
@@ -139,14 +143,46 @@ public void setMinScore(float minScore) {
139143
this.minScore = minScore;
140144
}
141145

142-
@Nullable
146+
/**
147+
* Set Ids for a multi-get request with on this query.
148+
*
149+
* @param ids list of id values
150+
*/
151+
public void setIds(@Nullable Collection<String> ids) {
152+
this.ids = ids;
153+
}
154+
143155
@Override
156+
@Nullable
144157
public Collection<String> getIds() {
145158
return ids;
146159
}
147160

148-
public void setIds(Collection<String> ids) {
149-
this.ids = ids;
161+
@Override
162+
public List<IdWithRouting> getIdsWithRouting() {
163+
164+
if (!isEmpty(idsWithRouting)) {
165+
return Collections.unmodifiableList(idsWithRouting);
166+
}
167+
168+
if (!isEmpty(ids)) {
169+
return ids.stream().map(id -> new IdWithRouting(id, route)).collect(Collectors.toList());
170+
}
171+
172+
return Collections.emptyList();
173+
}
174+
175+
/**
176+
* Set Ids with routing values for a multi-get request set on this query.
177+
*
178+
* @param idsWithRouting list of id values, must not be {@literal null}
179+
* @since 4.3
180+
*/
181+
public void setIdsWithRouting(List<IdWithRouting> idsWithRouting) {
182+
183+
Assert.notNull(idsWithRouting, "idsWithRouting must not be null");
184+
185+
this.idsWithRouting = idsWithRouting;
150186
}
151187

152188
@Nullable
@@ -337,4 +373,5 @@ public void setRequestCache(@Nullable Boolean value) {
337373
public Boolean getRequestCache() {
338374
return this.requestCache;
339375
}
376+
340377
}

src/main/java/org/springframework/data/elasticsearch/core/query/CriteriaQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* @author Mark Paluch
2727
* @author Peter-Josef Meisch
2828
*/
29-
public class CriteriaQuery extends AbstractQuery {
29+
public class CriteriaQuery extends BaseQuery {
3030

3131
private Criteria criteria;
3232

src/main/java/org/springframework/data/elasticsearch/core/query/MoreLikeThisQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package org.springframework.data.elasticsearch.core.query;
1717

1818
import static java.util.Collections.*;
19-
import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*;
19+
import static org.springframework.data.elasticsearch.core.query.BaseQuery.*;
2020

2121
import java.util.ArrayList;
2222
import java.util.List;

src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* @author Martin Choraine
4343
* @author Peter-Josef Meisch
4444
*/
45-
public class NativeSearchQuery extends AbstractQuery {
45+
public class NativeSearchQuery extends BaseQuery {
4646

4747
@Nullable private final QueryBuilder query;
4848
@Nullable private QueryBuilder filter;

src/main/java/org/springframework/data/elasticsearch/core/query/Query.java

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.data.domain.Sort;
2727
import org.springframework.data.elasticsearch.core.SearchHit;
2828
import org.springframework.lang.Nullable;
29+
import org.springframework.util.Assert;
2930

3031
/**
3132
* Query
@@ -76,7 +77,7 @@ static Query findAll() {
7677
* @param sort
7778
* @return
7879
*/
79-
<T extends Query> T addSort(Sort sort);
80+
<T extends Query> T addSort(@Nullable Sort sort);
8081

8182
/**
8283
* @return null if not set
@@ -137,13 +138,48 @@ static Query findAll() {
137138
boolean getTrackScores();
138139

139140
/**
140-
* Get Ids
141-
*
142-
* @return
141+
* @return Get ids set on this query.
143142
*/
144143
@Nullable
145144
Collection<String> getIds();
146145

146+
/**
147+
* @return Ids with routing values used in a multi-get request.
148+
* @see #multiGetQueryWithRouting(List)
149+
* @since 4.3
150+
*/
151+
List<IdWithRouting> getIdsWithRouting();
152+
153+
/**
154+
* Utility method to get a query for a multiget request
155+
*
156+
* @param idsWithRouting Ids with routing values used in a multi-get request.
157+
* @return Query instance
158+
*/
159+
static Query multiGetQueryWithRouting(List<IdWithRouting> idsWithRouting) {
160+
161+
Assert.notNull(idsWithRouting, "idsWithRouting must not be null");
162+
163+
BaseQuery query = new BaseQuery();
164+
query.setIdsWithRouting(idsWithRouting);
165+
return query;
166+
}
167+
168+
/**
169+
* Utility method to get a query for a multiget request
170+
*
171+
* @param ids Ids used in a multi-get request.
172+
* @return Query instance
173+
*/
174+
static Query multiGetQuery(Collection<String> ids) {
175+
176+
Assert.notNull(ids, "ids must not be null");
177+
178+
BaseQuery query = new BaseQuery();
179+
query.setIds(ids);
180+
return query;
181+
}
182+
147183
/**
148184
* Get route
149185
*
@@ -362,4 +398,31 @@ default List<RescorerQuery> getRescorerQueries() {
362398
enum SearchType {
363399
QUERY_THEN_FETCH, DFS_QUERY_THEN_FETCH
364400
}
401+
402+
/**
403+
* Value class combining an id with a routing value. Used in multi-get requests.
404+
*
405+
* @since 4.3
406+
*/
407+
final class IdWithRouting {
408+
private final String id;
409+
@Nullable private final String routing;
410+
411+
public IdWithRouting(String id, @Nullable String routing) {
412+
413+
Assert.notNull(id, "id must not be null");
414+
415+
this.id = id;
416+
this.routing = routing;
417+
}
418+
419+
public String getId() {
420+
return id;
421+
}
422+
423+
@Nullable
424+
public String getRouting() {
425+
return routing;
426+
}
427+
}
365428
}

src/main/java/org/springframework/data/elasticsearch/core/query/StringQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* @author Rizwan Idrees
2525
* @author Mohsin Husen
2626
*/
27-
public class StringQuery extends AbstractQuery {
27+
public class StringQuery extends BaseQuery {
2828

2929
private String source;
3030

src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.elasticsearch.repository.support;
1717

1818
import static org.elasticsearch.index.query.QueryBuilders.*;
19+
import static org.springframework.util.CollectionUtils.*;
1920

2021
import java.util.ArrayList;
2122
import java.util.Collections;
@@ -50,7 +51,6 @@
5051
import org.springframework.data.util.Streamable;
5152
import org.springframework.lang.Nullable;
5253
import org.springframework.util.Assert;
53-
import org.springframework.util.CollectionUtils;
5454

5555
/**
5656
* Elasticsearch specific repository implementation. Likely to be used as target within
@@ -149,7 +149,7 @@ public Iterable<T> findAllById(Iterable<ID> ids) {
149149

150150
List<T> result = new ArrayList<>();
151151
Query idQuery = getIdQuery(ids);
152-
if (CollectionUtils.isEmpty(idQuery.getIds())) {
152+
if (isEmpty(idQuery.getIds())) {
153153
return result;
154154
}
155155

0 commit comments

Comments
 (0)