DATAES-106 - Add support for countBy projection

This commit is contained in:
Kevin Leturc
2014-08-26 16:44:21 +02:00
committed by Mohsin Husen
parent c866664acc
commit 1ea9920a0d
8 changed files with 818 additions and 21 deletions

View File

@@ -30,6 +30,7 @@ import org.springframework.data.elasticsearch.core.query.*;
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Kevin Leturc
*/
public interface ElasticsearchOperations {
@@ -246,6 +247,23 @@ public interface ElasticsearchOperations {
*/
<T> List<String> queryForIds(SearchQuery query);
/**
* return number of elements found by given query
*
* @param query
* @param clazz
* @return
*/
<T> long count(CriteriaQuery query, Class<T> clazz);
/**
* return number of elements found by given query
*
* @param query
* @return
*/
<T> long count(CriteriaQuery query);
/**
* return number of elements found by given query
*

View File

@@ -50,6 +50,7 @@ import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.mlt.MoreLikeThisRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Client;
@@ -96,6 +97,7 @@ import org.springframework.util.Assert;
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Kevin Leturc
*/
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
@@ -317,10 +319,65 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
return mapper.mapResults(response, clazz, query.getPageable());
}
@Override
public <T> long count(CriteriaQuery criteriaQuery, Class<T> clazz) {
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
if (elasticsearchFilter == null) {
return doCount(prepareCount(criteriaQuery, clazz), elasticsearchQuery);
} else {
// filter could not be set into CountRequestBuilder, convert request into search request
return doCount(prepareSearch(criteriaQuery, clazz), elasticsearchQuery, elasticsearchFilter);
}
}
@Override
public <T> long count(SearchQuery searchQuery, Class<T> clazz) {
String indexName[] = isNotEmpty(searchQuery.getIndices()) ? searchQuery.getIndices().toArray(new String[searchQuery.getIndices().size()]) : retrieveIndexNameFromPersistentEntity(clazz);
String types[] = isNotEmpty(searchQuery.getTypes()) ? searchQuery.getTypes().toArray(new String[searchQuery.getTypes().size()]) : retrieveTypeFromPersistentEntity(clazz);
QueryBuilder elasticsearchQuery = searchQuery.getQuery();
FilterBuilder elasticsearchFilter = searchQuery.getFilter();
if (elasticsearchFilter == null) {
return doCount(prepareCount(searchQuery, clazz), elasticsearchQuery);
} else {
// filter could not be set into CountRequestBuilder, convert request into search request
return doCount(prepareSearch(searchQuery, clazz), elasticsearchQuery, elasticsearchFilter);
}
}
@Override
public <T> long count(CriteriaQuery query) {
return count(query, null);
}
@Override
public <T> long count(SearchQuery query) {
return count(query, null);
}
private long doCount(CountRequestBuilder countRequestBuilder, QueryBuilder elasticsearchQuery) {
if (elasticsearchQuery != null) {
countRequestBuilder.setQuery(elasticsearchQuery);
}
return countRequestBuilder.execute().actionGet().getCount();
}
private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, FilterBuilder elasticsearchFilter) {
if (elasticsearchQuery != null) {
searchRequestBuilder.setQuery(elasticsearchQuery);
} else {
searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
}
if (elasticsearchFilter != null) {
searchRequestBuilder.setPostFilter(elasticsearchFilter);
}
searchRequestBuilder.setSearchType(SearchType.COUNT);
return searchRequestBuilder.execute().actionGet().getHits().getTotalHits();
}
private <T> CountRequestBuilder prepareCount(Query query, Class<T> clazz) {
String indexName[] = isNotEmpty(query.getIndices()) ? query.getIndices().toArray(new String[query.getIndices().size()]) : retrieveIndexNameFromPersistentEntity(clazz);
String types[] = isNotEmpty(query.getTypes()) ? query.getTypes().toArray(new String[query.getTypes().size()]) : retrieveTypeFromPersistentEntity(clazz);
Assert.notNull(indexName, "No index defined for Query");
@@ -329,15 +386,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
if (types != null) {
countRequestBuilder.setTypes(types);
}
if (searchQuery.getQuery() != null) {
countRequestBuilder.setQuery(searchQuery.getQuery());
}
return countRequestBuilder.execute().actionGet().getCount();
}
@Override
public <T> long count(SearchQuery query) {
return count(query, null);
return countRequestBuilder;
}
@Override

View File

@@ -28,6 +28,7 @@ import org.springframework.data.repository.query.parser.PartTree;
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Kevin Leturc
*/
public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery {
@@ -52,6 +53,8 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
query.setPageable(accessor.getPageable());
}
return elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType());
} else if (tree.isCountProjection()) {
return elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
}
return elasticsearchOperations.queryForObject(query, queryMethod.getEntityInformation().getJavaType());
}

View File

@@ -19,8 +19,6 @@ import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.support.ElasticsearchEntityInformation;
import org.springframework.data.elasticsearch.repository.support.ElasticsearchEntityInformationCreator;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.StringUtils;
@@ -33,14 +31,10 @@ import org.springframework.util.StringUtils;
*/
public class ElasticsearchQueryMethod extends QueryMethod {
private final ElasticsearchEntityInformation<?, ?> entityInformation;
private Method method;
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata,
ElasticsearchEntityInformationCreator elasticsearchEntityInformationCreator) {
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata) {
super(method, metadata);
this.entityInformation = elasticsearchEntityInformationCreator.getEntityInformation(metadata
.getReturnedDomainClass(method));
this.method = method;
}

View File

@@ -105,7 +105,7 @@ public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
@Override
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method, metadata, entityInformationCreator);
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method, metadata);
String namedQueryName = queryMethod.getNamedQueryName();
if (namedQueries.hasQuery(namedQueryName)) {