mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-14 16:12:11 +00:00
Fix handling of array-of-strings parameters for @Query-annotated queries.
Original Pull Request #2182 Closes #2135
This commit is contained in:
parent
a2802ce716
commit
259c43af19
@ -82,8 +82,7 @@ abstract class AbstractReactiveElasticsearchRepositoryQuery implements Repositor
|
||||
|
||||
ResultProcessor processor = queryMethod.getResultProcessor().withDynamicProjection(parameterAccessor);
|
||||
|
||||
Query query = createQuery(
|
||||
new ConvertingParameterAccessor(elasticsearchOperations.getElasticsearchConverter(), parameterAccessor));
|
||||
Query query = createQuery(parameterAccessor);
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 3.2
|
||||
*/
|
||||
public class ConvertingParameterAccessor implements ElasticsearchParameterAccessor {
|
||||
|
||||
private final ElasticsearchConverter converter;
|
||||
private final ElasticsearchParameterAccessor delegate;
|
||||
|
||||
public ConvertingParameterAccessor(ElasticsearchConverter converter, ElasticsearchParameterAccessor delegate) {
|
||||
|
||||
this.converter = converter;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return delegate.getValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pageable getPageable() {
|
||||
return delegate.getPageable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sort getSort() {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Optional<Class<?>> getDynamicProjection() {
|
||||
// return delegate.getDynamicProjection();
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Class<?> findDynamicProjection() {
|
||||
return delegate.findDynamicProjection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBindableValue(int index) {
|
||||
return getConvertedValue(delegate.getBindableValue(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBindableNullValue() {
|
||||
return delegate.hasBindableNullValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Object> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object getConvertedValue(Object value) {
|
||||
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (converter.getConversionService().canConvert(value.getClass(), String.class)) {
|
||||
return converter.getConversionService().convert(value, String.class);
|
||||
}
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
}
|
@ -144,10 +144,37 @@ public class ReactiveElasticsearchStringQueryUnitTests extends ElasticsearchStri
|
||||
.isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'car' : 'Toyota-Prius' } } } }");
|
||||
}
|
||||
|
||||
@Test // #2135
|
||||
@DisplayName("should handle array-of-strings parameters correctly")
|
||||
void shouldHandleArrayOfStringsParametersCorrectly() throws Exception {
|
||||
|
||||
List<String> otherNames = List.of("Wesley", "Emmett");
|
||||
|
||||
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByOtherNames", otherNames);
|
||||
|
||||
assertThat(query).isInstanceOf(StringQuery.class);
|
||||
assertThat(((StringQuery) query).getSource())
|
||||
.isEqualTo("{ 'bool' : { 'must' : { 'terms' : { 'otherNames' : [\"Wesley\",\"Emmett\"] } } } }");
|
||||
}
|
||||
|
||||
@Test // #2135
|
||||
@DisplayName("should handle array-of-Integers parameters correctly")
|
||||
void shouldHandleArrayOfIntegerParametersCorrectly() throws Exception {
|
||||
|
||||
List<Integer> ages = List.of(42, 57);
|
||||
|
||||
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByAges", ages);
|
||||
|
||||
assertThat(query).isInstanceOf(StringQuery.class);
|
||||
assertThat(((StringQuery) query).getSource())
|
||||
.isEqualTo("{ 'bool' : { 'must' : { 'terms' : { 'ages' : [42,57] } } } }");
|
||||
}
|
||||
|
||||
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, Object... args)
|
||||
throws NoSuchMethodException {
|
||||
|
||||
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
|
||||
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass)
|
||||
.map(clazz -> Collection.class.isAssignableFrom(clazz) ? List.class : clazz).toArray(Class[]::new);
|
||||
ReactiveElasticsearchQueryMethod queryMethod = getQueryMethod(methodName, argTypes);
|
||||
ReactiveElasticsearchStringQuery elasticsearchStringQuery = queryForMethod(queryMethod);
|
||||
|
||||
@ -195,6 +222,12 @@ public class ReactiveElasticsearchStringQueryUnitTests extends ElasticsearchStri
|
||||
@Query("{ 'bool' : { 'must' : { 'term' : { 'car' : '?0' } } } }")
|
||||
Mono<Person> findByCar(Car car);
|
||||
|
||||
@Query("{ 'bool' : { 'must' : { 'terms' : { 'otherNames' : ?0 } } } }")
|
||||
Flux<Person> findByOtherNames(List<String> otherNames);
|
||||
|
||||
@Query("{ 'bool' : { 'must' : { 'terms' : { 'ages' : ?0 } } } }")
|
||||
Flux<Person> findByAges(List<Integer> ages);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,6 +244,8 @@ public class ReactiveElasticsearchStringQueryUnitTests extends ElasticsearchStri
|
||||
|
||||
@Nullable private String name;
|
||||
|
||||
@Nullable private List<String> otherNames;
|
||||
|
||||
@Nullable
|
||||
@Field(type = FieldType.Nested) private List<Car> car;
|
||||
|
||||
@ -235,6 +270,15 @@ public class ReactiveElasticsearchStringQueryUnitTests extends ElasticsearchStri
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getOtherNames() {
|
||||
return otherNames;
|
||||
}
|
||||
|
||||
public void setOtherNames(List<String> otherNames) {
|
||||
this.otherNames = otherNames;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<Car> getCar() {
|
||||
return car;
|
||||
|
@ -588,6 +588,52 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
assertThat(documentWithIdExistsInIndex("id-three").block()).isTrue();
|
||||
}
|
||||
|
||||
@Test // #2135
|
||||
void FluxOfSearchHitForArrayQuery() {
|
||||
bulkIndex(new SampleEntity("id-one", "message1"), //
|
||||
new SampleEntity("id-two", "message2"), //
|
||||
new SampleEntity("id-three", "message3")) //
|
||||
.block();
|
||||
|
||||
repository.findAllViaAnnotatedQueryByMessageIn(List.of("message1", "message3")) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-one")) //
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-three")) //
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test // #2135
|
||||
void FluxOfSearchHitForIntegerArrayQuery() {
|
||||
bulkIndex(new SampleEntity("id-one", "test", 3), //
|
||||
new SampleEntity("id-two", "test test", 1), //
|
||||
new SampleEntity("id-three", "test test", 2)) //
|
||||
.block();
|
||||
|
||||
repository.findAllViaAnnotatedQueryByRatesIn(List.of(2, 3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-one")) //
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-three")) //
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test // #2135
|
||||
void FluxOfSearchHitForStringAndIntegerArrayQuery() {
|
||||
bulkIndex(new SampleEntity("id-one", "message1", 1), //
|
||||
new SampleEntity("id-two", "message2", 2), //
|
||||
new SampleEntity("id-three", "message3", 3), //
|
||||
new SampleEntity("id-four", "message4", 4), //
|
||||
new SampleEntity("id-five", "message5", 5)) //
|
||||
.block();
|
||||
|
||||
repository.findAllViaAnnotatedQueryByMessageInAndRatesIn(List.of("message5", "message3"), List.of(2, 3)) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-three")) //
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
Mono<Void> bulkIndex(SampleEntity... entities) {
|
||||
return operations.saveAll(Arrays.asList(entities), IndexCoordinates.of(indexNameProvider.indexName())).then();
|
||||
}
|
||||
@ -627,6 +673,16 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
|
||||
@CountQuery(value = "{\"bool\": {\"must\": [{\"term\": {\"message\": \"?0\"}}]}}")
|
||||
Mono<Long> retrieveCountByText(String message);
|
||||
|
||||
@Query("{ \"terms\": { \"message\": ?0 } }")
|
||||
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageIn(List<String> messages);
|
||||
|
||||
@Query("{ \"terms\": { \"rate\": ?0 } }")
|
||||
Flux<SampleEntity> findAllViaAnnotatedQueryByRatesIn(List<Integer> rates);
|
||||
|
||||
@Query("{\"bool\": {\"must\": [{ \"terms\": { \"message\": ?0 } }, { \"terms\": { \"rate\": ?1 } }] } }")
|
||||
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageInAndRatesIn(List<String> messages, List<Integer> rates);
|
||||
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
|
Loading…
x
Reference in New Issue
Block a user