Skip to content

Commit 1970cc3

Browse files
committed
Fix handling of array-of-strings parameters for @Query-annotated queries.
Fixes spring-projects#2135
1 parent 0a0fc75 commit 1970cc3

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

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

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

18+
import java.util.Collection;
1819
import java.util.Iterator;
19-
import java.util.Optional;
2020

2121
import org.springframework.data.domain.Pageable;
2222
import org.springframework.data.domain.Sort;
@@ -86,6 +86,10 @@ private Object getConvertedValue(Object value) {
8686
return "null";
8787
}
8888

89+
if (Collection.class.isAssignableFrom(value.getClass())) {
90+
return value;
91+
}
92+
8993
if (converter.getConversionService().canConvert(value.getClass(), String.class)) {
9094
return converter.getConversionService().convert(value, String.class);
9195
}

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

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,29 @@ void shouldUseConverterOnParameters() throws Exception {
144144
.isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'car' : 'Toyota-Prius' } } } }");
145145
}
146146

147+
@Test // #1866
148+
@DisplayName("should handle array-of-strings parameters correctly")
149+
void shouldHandleArrayOfStringsParametersCorrectly() throws Exception {
150+
151+
List<String> otherNames = List.of("Wesley", "Emmett");
152+
153+
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByOtherNames", otherNames);
154+
155+
assertThat(query).isInstanceOf(StringQuery.class);
156+
assertThat(((StringQuery) query).getSource())
157+
.isEqualTo("{ 'bool' : { 'must' : { 'terms' : { 'otherNames' : [\"Wesley\",\"Emmett\"] } } } }");
158+
}
159+
147160
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, Object... args)
148161
throws NoSuchMethodException {
149162

150-
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
163+
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass)
164+
.map(clazz -> Collection.class.isAssignableFrom(clazz) ? List.class : clazz).toArray(Class[]::new);
151165
ReactiveElasticsearchQueryMethod queryMethod = getQueryMethod(methodName, argTypes);
152166
ReactiveElasticsearchStringQuery elasticsearchStringQuery = queryForMethod(queryMethod);
153167

154-
return elasticsearchStringQuery.createQuery(new ElasticsearchParametersParameterAccessor(queryMethod, args));
168+
return elasticsearchStringQuery.createQuery(new ConvertingParameterAccessor(operations.getElasticsearchConverter(),
169+
new ElasticsearchParametersParameterAccessor(queryMethod, args)));
155170
}
156171

157172
private ReactiveElasticsearchStringQuery queryForMethod(ReactiveElasticsearchQueryMethod queryMethod) {
@@ -195,6 +210,9 @@ Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String
195210
@Query("{ 'bool' : { 'must' : { 'term' : { 'car' : '?0' } } } }")
196211
Mono<Person> findByCar(Car car);
197212

213+
@Query("{ 'bool' : { 'must' : { 'terms' : { 'otherNames' : ?0 } } } }")
214+
Flux<Person> findByOtherNames(List<String> otherNames);
215+
198216
}
199217

200218
/**
@@ -211,6 +229,8 @@ public class Person {
211229

212230
@Nullable private String name;
213231

232+
@Nullable private List<String> otherNames;
233+
214234
@Nullable
215235
@Field(type = FieldType.Nested) private List<Car> car;
216236

@@ -235,6 +255,15 @@ public void setName(String name) {
235255
this.name = name;
236256
}
237257

258+
@Nullable
259+
public List<String> getOtherNames() {
260+
return otherNames;
261+
}
262+
263+
public void setOtherNames(List<String> otherNames) {
264+
this.otherNames = otherNames;
265+
}
266+
238267
@Nullable
239268
public List<Car> getCar() {
240269
return car;

src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryIntegrationTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,21 @@ void derivedDeleteMethodShouldBeExecutedCorrectly() {
588588
assertThat(documentWithIdExistsInIndex("id-three").block()).isTrue();
589589
}
590590

591+
@Test // #2135
592+
void FluxOfSearchHitForArrayQuery() {
593+
bulkIndex(new SampleEntity("id-one", "message1"), //
594+
new SampleEntity("id-two", "message2"), //
595+
new SampleEntity("id-three", "message3")) //
596+
.block();
597+
598+
repository.findAllViaAnnotatedQueryByMessageIn(List.of("message1", "message3")) //
599+
.as(StepVerifier::create) //
600+
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-one")) //
601+
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-three")) //
602+
.verifyComplete();
603+
604+
}
605+
591606
Mono<Void> bulkIndex(SampleEntity... entities) {
592607
return operations.saveAll(Arrays.asList(entities), IndexCoordinates.of(indexNameProvider.indexName())).then();
593608
}
@@ -627,6 +642,9 @@ interface ReactiveSampleEntityRepository extends ReactiveCrudRepository<SampleEn
627642

628643
@CountQuery(value = "{\"bool\": {\"must\": [{\"term\": {\"message\": \"?0\"}}]}}")
629644
Mono<Long> retrieveCountByText(String message);
645+
646+
@Query("{ \"terms\": { \"message\": ?0 } }")
647+
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageIn(List<String> messages);
630648
}
631649

632650
@Document(indexName = "#{@indexNameProvider.indexName()}")

0 commit comments

Comments
 (0)