mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-30 16:52:11 +00:00
parent
910ca7b665
commit
fe8c4f12ed
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2021 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.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Alias for a @Query annotation with the count parameter set to true.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Documented
|
||||
@Query(count = true)
|
||||
public @interface CountQuery {
|
||||
|
||||
@AliasFor(annotation = Query.class)
|
||||
String value() default "";
|
||||
}
|
@ -22,24 +22,32 @@ import java.lang.annotation.*;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Documented
|
||||
public @interface Query {
|
||||
|
||||
/**
|
||||
* Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
|
||||
*
|
||||
* @return
|
||||
* @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* Named Query Named looked up by repository.
|
||||
*
|
||||
* @return
|
||||
* @deprecated since 4.2, not implemented and used anywhere
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* Returns whether the query defined should be executed as count projection.
|
||||
*
|
||||
* @return {@literal false} by default.
|
||||
* @since 4.2
|
||||
*/
|
||||
boolean count() default false;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import org.springframework.data.repository.query.RepositoryQuery;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
|
||||
public abstract class AbstractElasticsearchRepositoryQuery implements RepositoryQuery {
|
||||
@ -42,4 +43,10 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
public QueryMethod getQueryMethod() {
|
||||
return queryMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this is a count query
|
||||
* @since 4.2
|
||||
*/
|
||||
public abstract boolean isCountQuery();
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import org.springframework.data.repository.query.ResultProcessor;
|
||||
*/
|
||||
abstract class AbstractReactiveElasticsearchRepositoryQuery implements RepositoryQuery {
|
||||
|
||||
private final ReactiveElasticsearchQueryMethod queryMethod;
|
||||
protected final ReactiveElasticsearchQueryMethod queryMethod;
|
||||
private final ReactiveElasticsearchOperations elasticsearchOperations;
|
||||
|
||||
AbstractReactiveElasticsearchRepositoryQuery(ReactiveElasticsearchQueryMethod queryMethod,
|
||||
|
@ -59,6 +59,11 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
this.mappingContext = elasticsearchConverter.getMappingContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCountQuery() {
|
||||
return tree.isCountProjection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
|
@ -20,7 +20,8 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
@ -34,7 +35,9 @@ import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@ -53,9 +56,9 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
private @Nullable ElasticsearchEntityMetadata<?> metadata;
|
||||
private final Method method; // private in base class, but needed here as well
|
||||
private final Query queryAnnotation;
|
||||
private final Highlight highlightAnnotation;
|
||||
protected final Method method; // private in base class, but needed here and in derived classes as well
|
||||
@Nullable private final Query queryAnnotation;
|
||||
@Nullable private final Highlight highlightAnnotation;
|
||||
private final Lazy<HighlightQuery> highlightQueryLazy = Lazy.of(this::createAnnotatedHighlightQuery);
|
||||
|
||||
public ElasticsearchQueryMethod(Method method, RepositoryMetadata repositoryMetadata, ProjectionFactory factory,
|
||||
@ -67,16 +70,32 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
|
||||
this.method = method;
|
||||
this.mappingContext = mappingContext;
|
||||
this.queryAnnotation = method.getAnnotation(Query.class);
|
||||
this.highlightAnnotation = method.getAnnotation(Highlight.class);
|
||||
this.queryAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
|
||||
this.highlightAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Highlight.class);
|
||||
|
||||
verifyCountQueryTypes();
|
||||
}
|
||||
|
||||
protected void verifyCountQueryTypes() {
|
||||
|
||||
if (hasCountQueryAnnotation()) {
|
||||
TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
|
||||
if (returnType.getType() != long.class && !Long.class.isAssignableFrom(returnType.getType())) {
|
||||
throw new InvalidDataAccessApiUsageException("count query methods must return a Long");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasAnnotatedQuery() {
|
||||
return this.queryAnnotation != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the query String. Must not be {@literal null} when {@link #hasAnnotatedQuery()} returns true
|
||||
*/
|
||||
public String getAnnotatedQuery() {
|
||||
return (String) AnnotationUtils.getValue(queryAnnotation, "value");
|
||||
return queryAnnotation.value();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,4 +236,14 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
public boolean isNotSearchPageMethod() {
|
||||
return !isSearchPageMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the method is annotated with
|
||||
* {@link org.springframework.data.elasticsearch.annotations.CountQuery} or with {@link Query}(count =true)
|
||||
* @since 4.2
|
||||
*/
|
||||
public boolean hasCountQueryAnnotation() {
|
||||
return queryAnnotation != null && queryAnnotation.count();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -69,8 +69,14 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCountQuery() {
|
||||
return queryMethod.hasCountQueryAnnotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
|
||||
@ -86,7 +92,9 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
|
||||
Object result = null;
|
||||
|
||||
if (queryMethod.isPageQuery()) {
|
||||
if (isCountQuery()) {
|
||||
result = elasticsearchOperations.count(stringQuery, clazz, index);
|
||||
} else if (queryMethod.isPageQuery()) {
|
||||
stringQuery.setPageable(accessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||
result = SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable());
|
||||
|
@ -18,9 +18,11 @@ package org.springframework.data.elasticsearch.repository.query;
|
||||
import static org.springframework.data.repository.util.ClassUtils.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -59,7 +61,6 @@ public class ReactiveElasticsearchQueryMethod extends ElasticsearchQueryMethod {
|
||||
if (hasParameterOfType(method, Pageable.class)) {
|
||||
|
||||
TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
|
||||
boolean multiWrapper = ReactiveWrappers.isMultiValueType(returnType.getType());
|
||||
boolean singleWrapperWithWrappedPageableResult = ReactiveWrappers.isSingleValueType(returnType.getType())
|
||||
&& (PAGE_TYPE.isAssignableFrom(returnType.getRequiredComponentType())
|
||||
@ -87,6 +88,20 @@ public class ReactiveElasticsearchQueryMethod extends ElasticsearchQueryMethod {
|
||||
&& ReactiveWrappers.isMultiValueType(metadata.getReturnType(method).getType()) || super.isCollectionQuery()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifyCountQueryTypes() {
|
||||
if (hasCountQueryAnnotation()) {
|
||||
TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
List<TypeInformation<?>> typeArguments = returnType.getTypeArguments();
|
||||
|
||||
if (!Mono.class.isAssignableFrom(returnType.getType()) || typeArguments.size() != 1
|
||||
|| (typeArguments.get(0).getType() != long.class
|
||||
&& !Long.class.isAssignableFrom(typeArguments.get(0).getType()))) {
|
||||
throw new InvalidDataAccessApiUsageException("count query methods must return a Mono<Long>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ElasticsearchParameters createParameters(Method method) {
|
||||
return new ElasticsearchParameters(method);
|
||||
|
@ -75,7 +75,7 @@ public class ReactiveElasticsearchStringQuery extends AbstractReactiveElasticsea
|
||||
|
||||
@Override
|
||||
boolean isCountQuery() {
|
||||
return false;
|
||||
return queryMethod.hasCountQueryAnnotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,17 @@
|
||||
/*
|
||||
* (c) Copyright 2021 sothawo
|
||||
* Copyright 2021 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.core.mapping;
|
||||
|
||||
@ -10,7 +22,7 @@ import org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author P.J. Meisch (pj.meisch@sothawo.com)
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ContextConfiguration(classes = { FieldNamingStrategyIntegrationTemplateTest.Config.class })
|
||||
public class FieldNamingStrategyIntegrationTemplateTest extends FieldNamingStrategyIntegrationTest {
|
||||
|
@ -35,6 +35,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
@ -44,6 +45,7 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.elasticsearch.annotations.CountQuery;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
@ -911,6 +913,31 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
assertThat(count).isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test // #1156
|
||||
@DisplayName("should count with query by type")
|
||||
void shouldCountWithQueryByType() {
|
||||
|
||||
String documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setId(documentId);
|
||||
sampleEntity.setType("test");
|
||||
sampleEntity.setMessage("some message");
|
||||
|
||||
repository.save(sampleEntity);
|
||||
|
||||
documentId = nextIdAsString();
|
||||
SampleEntity sampleEntity2 = new SampleEntity();
|
||||
sampleEntity2.setId(documentId);
|
||||
sampleEntity2.setType("test2");
|
||||
sampleEntity2.setMessage("some message");
|
||||
|
||||
repository.save(sampleEntity2);
|
||||
|
||||
long count = repository.countWithQueryByType("test");
|
||||
|
||||
assertThat(count).isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test // DATAES-106
|
||||
public void shouldCountCustomMethodForNot() {
|
||||
|
||||
@ -1746,6 +1773,9 @@ public abstract class CustomMethodRepositoryBaseTests {
|
||||
SearchHits<SampleEntity> searchBy(Sort sort);
|
||||
|
||||
SearchPage<SampleEntity> searchByMessage(String message, Pageable pageable);
|
||||
|
||||
@CountQuery("{\"bool\" : {\"must\" : {\"term\" : {\"type\" : \"?0\"}}}}")
|
||||
long countWithQueryByType(String type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2021 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.CountQuery;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class ElasticsearchQueryMethodUnitTests {
|
||||
|
||||
private SimpleElasticsearchMappingContext mappingContext;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
mappingContext = new SimpleElasticsearchMappingContext();
|
||||
}
|
||||
|
||||
@Test // #1156
|
||||
@DisplayName("should reject count query method not returning a Long")
|
||||
void shouldRejectCountQueryMethodNotReturningLong() {
|
||||
|
||||
assertThatThrownBy(() -> queryMethod(PersonRepository.class, "invalidCountQueryResult", String.class))
|
||||
.isInstanceOf(InvalidDataAccessApiUsageException.class);
|
||||
}
|
||||
|
||||
@Test // #1156
|
||||
@DisplayName("should accept count query method returning a Long")
|
||||
void shouldAcceptCountQueryMethodReturningALong() throws Exception {
|
||||
queryMethod(PersonRepository.class, "validCountQueryResult", String.class);
|
||||
}
|
||||
|
||||
private ElasticsearchQueryMethod queryMethod(Class<?> repository, String name, Class<?>... parameters)
|
||||
throws Exception {
|
||||
|
||||
Method method = repository.getMethod(name, parameters);
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
return new ElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(repository), factory, mappingContext);
|
||||
}
|
||||
|
||||
interface PersonRepository extends Repository<ReactiveElasticsearchQueryMethodUnitTests.Person, String> {
|
||||
@CountQuery("{}")
|
||||
List<Person> invalidCountQueryResult(String name); // invalid return type here
|
||||
|
||||
@CountQuery("{}")
|
||||
Long validCountQueryResult(String name);
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Document(indexName = "query-method-unit-tests")
|
||||
private static class Person {
|
||||
@Id private String id;
|
||||
@Nullable private String name;
|
||||
@Nullable private String firstName;
|
||||
}
|
||||
}
|
@ -32,12 +32,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.elasticsearch.annotations.CountQuery;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
@ -52,7 +54,6 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @currentRead Fool's Fate - Robin Hobb
|
||||
*/
|
||||
public class ReactiveElasticsearchQueryMethodUnitTests {
|
||||
|
||||
@ -115,6 +116,20 @@ public class ReactiveElasticsearchQueryMethodUnitTests {
|
||||
assertThat(method.getEntityInformation().getJavaType()).isAssignableFrom(Person.class);
|
||||
}
|
||||
|
||||
@Test // #1156
|
||||
@DisplayName("should reject count query method not returning a Mono of Long")
|
||||
void shouldRejectCountQueryMethodNotReturningAMonoOfLong() {
|
||||
|
||||
assertThatThrownBy(() -> queryMethod(PersonRepository.class, "invalidCountQueryResult", String.class))
|
||||
.isInstanceOf(InvalidDataAccessApiUsageException.class);
|
||||
}
|
||||
|
||||
@Test // #1156
|
||||
@DisplayName("should accept count query method returning a Mono of Long")
|
||||
void shouldAcceptCountQueryMethodReturningAMonoOfLong() throws Exception {
|
||||
queryMethod(PersonRepository.class, "validCountQueryResult", String.class);
|
||||
}
|
||||
|
||||
private ReactiveElasticsearchQueryMethod queryMethod(Class<?> repository, String name, Class<?>... parameters)
|
||||
throws Exception {
|
||||
|
||||
@ -137,6 +152,12 @@ public class ReactiveElasticsearchQueryMethodUnitTests {
|
||||
Flux<Person> findByName(String name, Pageable pageRequest);
|
||||
|
||||
void deleteByName(String name);
|
||||
|
||||
@CountQuery("{}")
|
||||
Flux<Person> invalidCountQueryResult(String name); // invalid return type here
|
||||
|
||||
@CountQuery("{}")
|
||||
Mono<Long> validCountQueryResult(String name);
|
||||
}
|
||||
|
||||
interface NonReactiveRepository extends Repository<Person, Long> {
|
||||
@ -156,6 +177,7 @@ public class ReactiveElasticsearchQueryMethodUnitTests {
|
||||
@Nullable @Id private String id;
|
||||
|
||||
@Nullable private String name;
|
||||
@Nullable private String firstName;
|
||||
|
||||
@Nullable @Field(type = FieldType.Nested) private List<Car> car;
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support.simple;
|
||||
package org.springframework.data.elasticsearch.repository.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
@ -77,7 +77,7 @@ class SimpleElasticsearchRepositoryIntegrationTests {
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
@EnableElasticsearchRepositories(
|
||||
basePackages = { "org.springframework.data.elasticsearch.repository.support.simple" },
|
||||
basePackages = { "org.springframework.data.elasticsearch.repository.support" },
|
||||
considerNestedRepositories = true)
|
||||
static class Config {}
|
||||
|
@ -37,6 +37,7 @@ import java.util.stream.IntStream;
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -48,6 +49,7 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.elasticsearch.annotations.CountQuery;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
@ -316,8 +318,7 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
SampleEntity.builder().id("id-three").message("test test").build()).block();
|
||||
|
||||
repository.countAllByMessage("test") //
|
||||
.as(StepVerifier::create) //
|
||||
@ -325,6 +326,20 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #1156
|
||||
@DisplayName("should count with string query")
|
||||
void shouldCountWithStringQuery() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build()).block();
|
||||
|
||||
repository.retrieveCountByText("test") //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
void existsShouldReturnTrueIfExists() {
|
||||
|
||||
@ -593,6 +608,9 @@ class SimpleReactiveElasticsearchRepositoryTests {
|
||||
Mono<Boolean> existsAllByMessage(String message);
|
||||
|
||||
Mono<Long> deleteAllByMessage(String message);
|
||||
|
||||
@CountQuery(value = "{\"bool\": {\"must\": [{\"term\": {\"message\": \"?0\"}}]}}")
|
||||
Mono<Long> retrieveCountByText(String message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user