mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-31 09:12:11 +00:00
basic mechanism for term facets
This commit is contained in:
parent
b421cb5044
commit
b2572d4950
5
.gitignore
vendored
5
.gitignore
vendored
@ -3,8 +3,11 @@ atlassian-ide-plugin.xml
|
||||
## Ignore svn files
|
||||
.svn
|
||||
|
||||
## ignore any target dir
|
||||
target
|
||||
data
|
||||
|
||||
##ignore only top level data dir - local node data files for unit tests
|
||||
/data
|
||||
|
||||
## Ignore project files created by Eclipse
|
||||
.settings
|
||||
|
@ -20,20 +20,26 @@ import java.lang.annotation.*;
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Documented
|
||||
public @interface Field {
|
||||
|
||||
String type() default "";
|
||||
String type() default "";
|
||||
|
||||
String index() default "";
|
||||
String index() default "";
|
||||
|
||||
boolean store() default false;
|
||||
boolean store() default false;
|
||||
|
||||
String searchAnalyzer() default "";
|
||||
String searchAnalyzer() default "";
|
||||
|
||||
String indexAnalyzer() default "";
|
||||
String indexAnalyzer() default "";
|
||||
|
||||
boolean facetable() default false;
|
||||
|
||||
boolean sortable() default false;
|
||||
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public interface ElasticsearchOperations {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz);
|
||||
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute the query against elasticsearch and return result as {@link Page}
|
||||
@ -93,7 +93,7 @@ public interface ElasticsearchOperations {
|
||||
* @param resultsMapper
|
||||
* @return
|
||||
*/
|
||||
<T> Page<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper);
|
||||
<T> FacetedPage<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper);
|
||||
|
||||
/**
|
||||
* Execute the query against elasticsearch and return result as {@link Page}
|
||||
@ -111,7 +111,7 @@ public interface ElasticsearchOperations {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz);
|
||||
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute the criteria query against elasticsearch and return result as {@link List}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.codehaus.jackson.map.DeserializationConfig;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
@ -33,19 +34,20 @@ import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.elasticsearch.search.facet.Facet;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetMapper;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
@ -69,443 +71,460 @@ import static org.springframework.data.elasticsearch.core.MappingBuilder.buildMa
|
||||
|
||||
/**
|
||||
* ElasticsearchTemplate
|
||||
*
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
|
||||
public class ElasticsearchTemplate implements ElasticsearchOperations {
|
||||
|
||||
private Client client;
|
||||
private ElasticsearchConverter elasticsearchConverter;
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
private Client client;
|
||||
private ElasticsearchConverter elasticsearchConverter;
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
{
|
||||
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
{
|
||||
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client) {
|
||||
this(client, null);
|
||||
}
|
||||
public ElasticsearchTemplate(Client client) {
|
||||
this(client, null);
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
|
||||
this.client = client;
|
||||
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
|
||||
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
|
||||
}
|
||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
|
||||
this.client = client;
|
||||
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
|
||||
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean createIndex(Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
return createIndexIfNotCreated(clazz);
|
||||
}
|
||||
@Override
|
||||
public <T> boolean createIndex(Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
return createIndexIfNotCreated(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean putMapping(Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
PutMappingRequestBuilder requestBuilder = client.admin().indices()
|
||||
.preparePutMapping(persistentEntity.getIndexName()).setType(persistentEntity.getIndexType());
|
||||
@Override
|
||||
public <T> boolean putMapping(Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
PutMappingRequestBuilder requestBuilder = client.admin().indices()
|
||||
.preparePutMapping(persistentEntity.getIndexName()).setType(persistentEntity.getIndexType());
|
||||
|
||||
try {
|
||||
XContentBuilder xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), persistentEntity
|
||||
.getIdProperty().getFieldName());
|
||||
return requestBuilder.setSource(xContentBuilder).execute().actionGet().isAcknowledged();
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
XContentBuilder xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), persistentEntity
|
||||
.getIdProperty().getFieldName());
|
||||
return requestBuilder.setSource(xContentBuilder).execute().actionGet().isAcknowledged();
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticsearchConverter getElasticsearchConverter() {
|
||||
return elasticsearchConverter;
|
||||
}
|
||||
@Override
|
||||
public ElasticsearchConverter getElasticsearchConverter() {
|
||||
return elasticsearchConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
GetResponse response = client
|
||||
.prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute()
|
||||
.actionGet();
|
||||
return mapResult(response.getSourceAsString(), clazz);
|
||||
}
|
||||
@Override
|
||||
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
GetResponse response = client
|
||||
.prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute()
|
||||
.actionGet();
|
||||
return mapResult(response.getSourceAsString(), clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T queryForObject(CriteriaQuery query, Class<T> clazz) {
|
||||
Page<T> page = queryForPage(query, clazz);
|
||||
Assert.isTrue(page.getTotalElements() < 2, "Expected 1 but found " + page.getTotalElements() + " results");
|
||||
return page.getTotalElements() > 0 ? page.getContent().get(0) : null;
|
||||
}
|
||||
@Override
|
||||
public <T> T queryForObject(CriteriaQuery query, Class<T> clazz) {
|
||||
Page<T> page = queryForPage(query, clazz);
|
||||
Assert.isTrue(page.getTotalElements() < 2, "Expected 1 but found " + page.getTotalElements() + " results");
|
||||
return page.getTotalElements() > 0 ? page.getContent().get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T queryForObject(StringQuery query, Class<T> clazz) {
|
||||
Page<T> page = queryForPage(query, clazz);
|
||||
Assert.isTrue(page.getTotalElements() < 2, "Expected 1 but found " + page.getTotalElements() + " results");
|
||||
return page.getTotalElements() > 0 ? page.getContent().get(0) : null;
|
||||
}
|
||||
@Override
|
||||
public <T> T queryForObject(StringQuery query, Class<T> clazz) {
|
||||
Page<T> page = queryForPage(query, clazz);
|
||||
Assert.isTrue(page.getTotalElements() < 2, "Expected 1 but found " + page.getTotalElements() + " results");
|
||||
return page.getTotalElements() > 0 ? page.getContent().get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> queryForPage(SearchQuery query, Class<T> clazz) {
|
||||
SearchResponse response = doSearch(prepareSearch(query, clazz), query.getQuery(), query.getFilter(),
|
||||
query.getElasticsearchSort());
|
||||
return mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
|
||||
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
|
||||
return mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper) {
|
||||
SearchResponse response = doSearch(prepareSearch(query), query.getQuery(), query.getFilter(),
|
||||
query.getElasticsearchSort());
|
||||
return resultsMapper.mapResults(response);
|
||||
}
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper) {
|
||||
SearchResponse response = doSearch(prepareSearch(query), query);
|
||||
return resultsMapper.mapResults(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryForList(CriteriaQuery query, Class<T> clazz) {
|
||||
return queryForPage(query, clazz).getContent();
|
||||
}
|
||||
@Override
|
||||
public <T> List<T> queryForList(CriteriaQuery query, Class<T> clazz) {
|
||||
return queryForPage(query, clazz).getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryForList(StringQuery query, Class<T> clazz) {
|
||||
return queryForPage(query, clazz).getContent();
|
||||
}
|
||||
@Override
|
||||
public <T> List<T> queryForList(StringQuery query, Class<T> clazz) {
|
||||
return queryForPage(query, clazz).getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<String> queryForIds(SearchQuery query) {
|
||||
SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields();
|
||||
if (query.getFilter() != null) {
|
||||
request.setFilter(query.getFilter());
|
||||
}
|
||||
SearchResponse response = request.execute().actionGet();
|
||||
return extractIds(response);
|
||||
}
|
||||
@Override
|
||||
public <T> List<String> queryForIds(SearchQuery query) {
|
||||
SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields();
|
||||
if (query.getFilter() != null) {
|
||||
request.setFilter(query.getFilter());
|
||||
}
|
||||
SearchResponse response = request.execute().actionGet();
|
||||
return extractIds(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
||||
QueryBuilder query = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||
SearchResponse response = prepareSearch(criteriaQuery, clazz).setQuery(query).execute().actionGet();
|
||||
return mapResults(response, clazz, criteriaQuery.getPageable());
|
||||
}
|
||||
@Override
|
||||
public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
||||
QueryBuilder query = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||
SearchResponse response = prepareSearch(criteriaQuery, clazz).setQuery(query).execute().actionGet();
|
||||
return mapResults(response, clazz, criteriaQuery.getPageable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz) {
|
||||
SearchResponse response = prepareSearch(query, clazz).setQuery(query.getSource()).execute().actionGet();
|
||||
return mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz) {
|
||||
SearchResponse response = prepareSearch(query, clazz).setQuery(query.getSource()).execute().actionGet();
|
||||
return mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> long count(SearchQuery query, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
CountRequestBuilder countRequestBuilder = client.prepareCount(persistentEntity.getIndexName()).setTypes(
|
||||
persistentEntity.getIndexType());
|
||||
if (query.getQuery() != null) {
|
||||
countRequestBuilder.setQuery(query.getQuery());
|
||||
}
|
||||
return countRequestBuilder.execute().actionGet().getCount();
|
||||
}
|
||||
@Override
|
||||
public <T> long count(SearchQuery query, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
CountRequestBuilder countRequestBuilder = client.prepareCount(persistentEntity.getIndexName()).setTypes(
|
||||
persistentEntity.getIndexType());
|
||||
if (query.getQuery() != null) {
|
||||
countRequestBuilder.setQuery(query.getQuery());
|
||||
}
|
||||
return countRequestBuilder.execute().actionGet().getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String index(IndexQuery query) {
|
||||
return prepareIndex(query).execute().actionGet().getId();
|
||||
}
|
||||
@Override
|
||||
public String index(IndexQuery query) {
|
||||
return prepareIndex(query).execute().actionGet().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bulkIndex(List<IndexQuery> queries) {
|
||||
BulkRequestBuilder bulkRequest = client.prepareBulk();
|
||||
for (IndexQuery query : queries) {
|
||||
bulkRequest.add(prepareIndex(query));
|
||||
}
|
||||
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
|
||||
if (bulkResponse.hasFailures()) {
|
||||
Map<String, String> failedDocuments = new HashMap<String, String>();
|
||||
for (BulkItemResponse item : bulkResponse.getItems()) {
|
||||
if (item.isFailed())
|
||||
failedDocuments.put(item.getId(), item.getFailureMessage());
|
||||
}
|
||||
throw new ElasticsearchException(
|
||||
"Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages ["
|
||||
+ failedDocuments + "]", failedDocuments);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void bulkIndex(List<IndexQuery> queries) {
|
||||
BulkRequestBuilder bulkRequest = client.prepareBulk();
|
||||
for (IndexQuery query : queries) {
|
||||
bulkRequest.add(prepareIndex(query));
|
||||
}
|
||||
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
|
||||
if (bulkResponse.hasFailures()) {
|
||||
Map<String, String> failedDocuments = new HashMap<String, String>();
|
||||
for (BulkItemResponse item : bulkResponse.getItems()) {
|
||||
if (item.isFailed())
|
||||
failedDocuments.put(item.getId(), item.getFailureMessage());
|
||||
}
|
||||
throw new ElasticsearchException(
|
||||
"Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages ["
|
||||
+ failedDocuments + "]", failedDocuments);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean indexExists(Class<T> clazz) {
|
||||
return indexExists(getPersistentEntityFor(clazz).getIndexName());
|
||||
}
|
||||
@Override
|
||||
public <T> boolean indexExists(Class<T> clazz) {
|
||||
return indexExists(getPersistentEntityFor(clazz).getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean deleteIndex(Class<T> clazz) {
|
||||
String indexName = getPersistentEntityFor(clazz).getIndexName();
|
||||
if (indexExists(indexName)) {
|
||||
return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public <T> boolean deleteIndex(Class<T> clazz) {
|
||||
String indexName = getPersistentEntityFor(clazz).getIndexName();
|
||||
if (indexExists(indexName)) {
|
||||
return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String delete(String indexName, String type, String id) {
|
||||
return client.prepareDelete(indexName, type, id).execute().actionGet().getId();
|
||||
}
|
||||
@Override
|
||||
public String delete(String indexName, String type, String id) {
|
||||
return client.prepareDelete(indexName, type, id).execute().actionGet().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> String delete(Class<T> clazz, String id) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
return delete(persistentEntity.getIndexName(), persistentEntity.getIndexType(), id);
|
||||
}
|
||||
@Override
|
||||
public <T> String delete(Class<T> clazz, String id) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
return delete(persistentEntity.getIndexName(), persistentEntity.getIndexType(), id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void delete(DeleteQuery deleteQuery, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
client.prepareDeleteByQuery(persistentEntity.getIndexName()).setTypes(persistentEntity.getIndexType())
|
||||
.setQuery(deleteQuery.getQuery()).execute().actionGet();
|
||||
}
|
||||
@Override
|
||||
public <T> void delete(DeleteQuery deleteQuery, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
client.prepareDeleteByQuery(persistentEntity.getIndexName()).setTypes(persistentEntity.getIndexType())
|
||||
.setQuery(deleteQuery.getQuery()).execute().actionGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) {
|
||||
Assert.notNull(searchQuery.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(searchQuery.getTypes(), "No type define for Query");
|
||||
Assert.notNull(searchQuery.getPageable(), "Query.pageable is required for scan & scroll");
|
||||
@Override
|
||||
public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) {
|
||||
Assert.notNull(searchQuery.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(searchQuery.getTypes(), "No type define for Query");
|
||||
Assert.notNull(searchQuery.getPageable(), "Query.pageable is required for scan & scroll");
|
||||
|
||||
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(searchQuery.getIndices())).setSearchType(SCAN)
|
||||
.setQuery(searchQuery.getQuery()).setTypes(toArray(searchQuery.getTypes()))
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0)
|
||||
.setSize(searchQuery.getPageable().getPageSize());
|
||||
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(searchQuery.getIndices())).setSearchType(SCAN)
|
||||
.setQuery(searchQuery.getQuery()).setTypes(toArray(searchQuery.getTypes()))
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0)
|
||||
.setSize(searchQuery.getPageable().getPageSize());
|
||||
|
||||
if (searchQuery.getFilter() != null) {
|
||||
requestBuilder.setFilter(searchQuery.getFilter());
|
||||
}
|
||||
if (searchQuery.getFilter() != null) {
|
||||
requestBuilder.setFilter(searchQuery.getFilter());
|
||||
}
|
||||
|
||||
if (noFields) {
|
||||
requestBuilder.setNoFields();
|
||||
}
|
||||
return requestBuilder.execute().actionGet().getScrollId();
|
||||
}
|
||||
if (noFields) {
|
||||
requestBuilder.setNoFields();
|
||||
}
|
||||
return requestBuilder.execute().actionGet().getScrollId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, ResultsMapper<T> resultsMapper) {
|
||||
SearchResponse response = client.prepareSearchScroll(scrollId)
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute().actionGet();
|
||||
return resultsMapper.mapResults(response);
|
||||
}
|
||||
@Override
|
||||
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, ResultsMapper<T> resultsMapper) {
|
||||
SearchResponse response = client.prepareSearchScroll(scrollId)
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute().actionGet();
|
||||
return resultsMapper.mapResults(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
|
||||
int startRecord = 0;
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
|
||||
String type = isNotBlank(query.getType()) ? query.getType() : persistentEntity.getIndexType();
|
||||
@Override
|
||||
public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
|
||||
int startRecord = 0;
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
|
||||
String type = isNotBlank(query.getType()) ? query.getType() : persistentEntity.getIndexType();
|
||||
|
||||
Assert.notNull(indexName, "No 'indexName' defined for MoreLikeThisQuery");
|
||||
Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
|
||||
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
||||
Assert.notNull(indexName, "No 'indexName' defined for MoreLikeThisQuery");
|
||||
Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
|
||||
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
||||
|
||||
MoreLikeThisRequestBuilder requestBuilder = client.prepareMoreLikeThis(indexName, type, query.getId());
|
||||
MoreLikeThisRequestBuilder requestBuilder = client.prepareMoreLikeThis(indexName, type, query.getId());
|
||||
|
||||
if (query.getPageable() != null) {
|
||||
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
|
||||
requestBuilder.setSearchSize(query.getPageable().getPageSize());
|
||||
}
|
||||
requestBuilder.setSearchFrom(startRecord);
|
||||
if (query.getPageable() != null) {
|
||||
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
|
||||
requestBuilder.setSearchSize(query.getPageable().getPageSize());
|
||||
}
|
||||
requestBuilder.setSearchFrom(startRecord);
|
||||
|
||||
if (isNotEmpty(query.getSearchIndices())) {
|
||||
requestBuilder.setSearchIndices(toArray(query.getSearchIndices()));
|
||||
}
|
||||
if (isNotEmpty(query.getSearchTypes())) {
|
||||
requestBuilder.setSearchTypes(toArray(query.getSearchTypes()));
|
||||
}
|
||||
if (isNotEmpty(query.getFields())) {
|
||||
requestBuilder.setField(toArray(query.getFields()));
|
||||
}
|
||||
if (isNotBlank(query.getRouting())) {
|
||||
requestBuilder.setRouting(query.getRouting());
|
||||
}
|
||||
if (query.getPercentTermsToMatch() != null) {
|
||||
requestBuilder.setPercentTermsToMatch(query.getPercentTermsToMatch());
|
||||
}
|
||||
if (query.getMinTermFreq() != null) {
|
||||
requestBuilder.setMinTermFreq(query.getMinTermFreq());
|
||||
}
|
||||
if (query.getMaxQueryTerms() != null) {
|
||||
requestBuilder.maxQueryTerms(query.getMaxQueryTerms());
|
||||
}
|
||||
if (isNotEmpty(query.getStopWords())) {
|
||||
requestBuilder.setStopWords(toArray(query.getStopWords()));
|
||||
}
|
||||
if (query.getMinDocFreq() != null) {
|
||||
requestBuilder.setMinDocFreq(query.getMinDocFreq());
|
||||
}
|
||||
if (query.getMaxDocFreq() != null) {
|
||||
requestBuilder.setMaxDocFreq(query.getMaxDocFreq());
|
||||
}
|
||||
if (query.getMinWordLen() != null) {
|
||||
requestBuilder.setMinWordLen(query.getMinWordLen());
|
||||
}
|
||||
if (query.getMaxWordLen() != null) {
|
||||
requestBuilder.setMaxWordLen(query.getMaxWordLen());
|
||||
}
|
||||
if (query.getBoostTerms() != null) {
|
||||
requestBuilder.setBoostTerms(query.getBoostTerms());
|
||||
}
|
||||
if (isNotEmpty(query.getSearchIndices())) {
|
||||
requestBuilder.setSearchIndices(toArray(query.getSearchIndices()));
|
||||
}
|
||||
if (isNotEmpty(query.getSearchTypes())) {
|
||||
requestBuilder.setSearchTypes(toArray(query.getSearchTypes()));
|
||||
}
|
||||
if (isNotEmpty(query.getFields())) {
|
||||
requestBuilder.setField(toArray(query.getFields()));
|
||||
}
|
||||
if (isNotBlank(query.getRouting())) {
|
||||
requestBuilder.setRouting(query.getRouting());
|
||||
}
|
||||
if (query.getPercentTermsToMatch() != null) {
|
||||
requestBuilder.setPercentTermsToMatch(query.getPercentTermsToMatch());
|
||||
}
|
||||
if (query.getMinTermFreq() != null) {
|
||||
requestBuilder.setMinTermFreq(query.getMinTermFreq());
|
||||
}
|
||||
if (query.getMaxQueryTerms() != null) {
|
||||
requestBuilder.maxQueryTerms(query.getMaxQueryTerms());
|
||||
}
|
||||
if (isNotEmpty(query.getStopWords())) {
|
||||
requestBuilder.setStopWords(toArray(query.getStopWords()));
|
||||
}
|
||||
if (query.getMinDocFreq() != null) {
|
||||
requestBuilder.setMinDocFreq(query.getMinDocFreq());
|
||||
}
|
||||
if (query.getMaxDocFreq() != null) {
|
||||
requestBuilder.setMaxDocFreq(query.getMaxDocFreq());
|
||||
}
|
||||
if (query.getMinWordLen() != null) {
|
||||
requestBuilder.setMinWordLen(query.getMinWordLen());
|
||||
}
|
||||
if (query.getMaxWordLen() != null) {
|
||||
requestBuilder.setMaxWordLen(query.getMaxWordLen());
|
||||
}
|
||||
if (query.getBoostTerms() != null) {
|
||||
requestBuilder.setBoostTerms(query.getBoostTerms());
|
||||
}
|
||||
|
||||
SearchResponse response = requestBuilder.execute().actionGet();
|
||||
return mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
SearchResponse response = requestBuilder.execute().actionGet();
|
||||
return mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
|
||||
private SearchResponse doSearch(SearchRequestBuilder searchRequest, QueryBuilder query, FilterBuilder filter,
|
||||
SortBuilder sortBuilder) {
|
||||
if (filter != null) {
|
||||
searchRequest.setFilter(filter);
|
||||
}
|
||||
private SearchResponse doSearch(SearchRequestBuilder searchRequest, SearchQuery searchQuery) {
|
||||
if (searchQuery.getFilter() != null) {
|
||||
searchRequest.setFilter(searchQuery.getFilter());
|
||||
}
|
||||
|
||||
if (sortBuilder != null) {
|
||||
searchRequest.addSort(sortBuilder);
|
||||
}
|
||||
if (searchQuery.getElasticsearchSort() != null) {
|
||||
searchRequest.addSort(searchQuery.getElasticsearchSort());
|
||||
}
|
||||
|
||||
return searchRequest.setQuery(query).execute().actionGet();
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(searchQuery.getFacets())) {
|
||||
for (FacetRequest facetRequest : searchQuery.getFacets()) {
|
||||
FacetBuilder facet = facetRequest.getFacet();
|
||||
if (facetRequest.applyQueryFilter() && searchQuery.getFilter() != null) {
|
||||
facet.facetFilter(searchQuery.getFilter());
|
||||
}
|
||||
searchRequest.addFacet(facet);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> boolean createIndexIfNotCreated(Class<T> clazz) {
|
||||
return indexExists(getPersistentEntityFor(clazz).getIndexName()) || createIndexWithSettings(clazz);
|
||||
}
|
||||
return searchRequest.setQuery(searchQuery.getQuery()).execute().actionGet();
|
||||
}
|
||||
|
||||
private boolean indexExists(String indexName) {
|
||||
return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists();
|
||||
}
|
||||
private <T> boolean createIndexIfNotCreated(Class<T> clazz) {
|
||||
return indexExists(getPersistentEntityFor(clazz).getIndexName()) || createIndexWithSettings(clazz);
|
||||
}
|
||||
|
||||
private <T> boolean createIndexWithSettings(Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
return client.admin().indices()
|
||||
.create(Requests.createIndexRequest(persistentEntity.getIndexName()).settings(getSettings(persistentEntity)))
|
||||
.actionGet().isAcknowledged();
|
||||
}
|
||||
private boolean indexExists(String indexName) {
|
||||
return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists();
|
||||
}
|
||||
|
||||
private <T> Map getSettings(ElasticsearchPersistentEntity<T> persistentEntity) {
|
||||
return new MapBuilder<String, String>().put("index.number_of_shards", String.valueOf(persistentEntity.getShards()))
|
||||
.put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas()))
|
||||
.put("index.refresh_interval", persistentEntity.getRefreshInterval())
|
||||
.put("index.store.type", persistentEntity.getIndexStoreType()).map();
|
||||
}
|
||||
private <T> boolean createIndexWithSettings(Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||
return client.admin().indices()
|
||||
.create(Requests.createIndexRequest(persistentEntity.getIndexName()).settings(getSettings(persistentEntity)))
|
||||
.actionGet().isAcknowledged();
|
||||
}
|
||||
|
||||
private <T> SearchRequestBuilder prepareSearch(Query query, Class<T> clazz) {
|
||||
if (query.getIndices().isEmpty()) {
|
||||
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
|
||||
}
|
||||
if (query.getTypes().isEmpty()) {
|
||||
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
|
||||
}
|
||||
return prepareSearch(query);
|
||||
}
|
||||
private <T> Map getSettings(ElasticsearchPersistentEntity<T> persistentEntity) {
|
||||
return new MapBuilder<String, String>().put("index.number_of_shards", String.valueOf(persistentEntity.getShards()))
|
||||
.put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas()))
|
||||
.put("index.refresh_interval", persistentEntity.getRefreshInterval())
|
||||
.put("index.store.type", persistentEntity.getIndexStoreType()).map();
|
||||
}
|
||||
|
||||
private SearchRequestBuilder prepareSearch(Query query) {
|
||||
Assert.notNull(query.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(query.getTypes(), "No type defined for Query");
|
||||
private <T> SearchRequestBuilder prepareSearch(Query query, Class<T> clazz) {
|
||||
if (query.getIndices().isEmpty()) {
|
||||
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
|
||||
}
|
||||
if (query.getTypes().isEmpty()) {
|
||||
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
|
||||
}
|
||||
return prepareSearch(query);
|
||||
}
|
||||
|
||||
int startRecord = 0;
|
||||
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
||||
.setSearchType(DFS_QUERY_THEN_FETCH).setTypes(toArray(query.getTypes()));
|
||||
private SearchRequestBuilder prepareSearch(Query query) {
|
||||
Assert.notNull(query.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(query.getTypes(), "No type defined for Query");
|
||||
|
||||
if (query.getPageable() != null) {
|
||||
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
|
||||
searchRequestBuilder.setSize(query.getPageable().getPageSize());
|
||||
}
|
||||
searchRequestBuilder.setFrom(startRecord);
|
||||
int startRecord = 0;
|
||||
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
||||
.setSearchType(DFS_QUERY_THEN_FETCH).setTypes(toArray(query.getTypes()));
|
||||
|
||||
if (!query.getFields().isEmpty()) {
|
||||
searchRequestBuilder.addFields(toArray(query.getFields()));
|
||||
}
|
||||
if (query.getPageable() != null) {
|
||||
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
|
||||
searchRequestBuilder.setSize(query.getPageable().getPageSize());
|
||||
}
|
||||
searchRequestBuilder.setFrom(startRecord);
|
||||
|
||||
if (query.getSort() != null) {
|
||||
for (Sort.Order order : query.getSort()) {
|
||||
searchRequestBuilder.addSort(order.getProperty(), order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC
|
||||
: SortOrder.ASC);
|
||||
}
|
||||
}
|
||||
return searchRequestBuilder;
|
||||
}
|
||||
if (!query.getFields().isEmpty()) {
|
||||
searchRequestBuilder.addFields(toArray(query.getFields()));
|
||||
}
|
||||
|
||||
private IndexRequestBuilder prepareIndex(IndexQuery query) {
|
||||
try {
|
||||
String indexName = isBlank(query.getIndexName()) ? retrieveIndexNameFromPersistentEntity(query.getObject()
|
||||
.getClass())[0] : query.getIndexName();
|
||||
String type = isBlank(query.getType()) ? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getType();
|
||||
if (query.getSort() != null) {
|
||||
for (Sort.Order order : query.getSort()) {
|
||||
searchRequestBuilder.addSort(order.getProperty(), order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC
|
||||
: SortOrder.ASC);
|
||||
}
|
||||
}
|
||||
return searchRequestBuilder;
|
||||
}
|
||||
|
||||
IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(
|
||||
objectMapper.writeValueAsString(query.getObject()));
|
||||
private IndexRequestBuilder prepareIndex(IndexQuery query) {
|
||||
try {
|
||||
String indexName = isBlank(query.getIndexName()) ? retrieveIndexNameFromPersistentEntity(query.getObject()
|
||||
.getClass())[0] : query.getIndexName();
|
||||
String type = isBlank(query.getType()) ? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getType();
|
||||
|
||||
if (query.getVersion() != null) {
|
||||
indexRequestBuilder.setVersion(query.getVersion());
|
||||
indexRequestBuilder.setVersionType(EXTERNAL);
|
||||
}
|
||||
return indexRequestBuilder;
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e);
|
||||
}
|
||||
}
|
||||
IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(
|
||||
objectMapper.writeValueAsString(query.getObject()));
|
||||
|
||||
public void refresh(String indexName, boolean waitForOperation) {
|
||||
client.admin().indices().refresh(refreshRequest(indexName).waitForOperations(waitForOperation)).actionGet();
|
||||
}
|
||||
if (query.getVersion() != null) {
|
||||
indexRequestBuilder.setVersion(query.getVersion());
|
||||
indexRequestBuilder.setVersionType(EXTERNAL);
|
||||
}
|
||||
return indexRequestBuilder;
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void refresh(Class<T> clazz, boolean waitForOperation) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
client.admin().indices()
|
||||
.refresh(refreshRequest(persistentEntity.getIndexName()).waitForOperations(waitForOperation)).actionGet();
|
||||
}
|
||||
public void refresh(String indexName, boolean waitForOperation) {
|
||||
client.admin().indices().refresh(refreshRequest(indexName).waitForOperations(waitForOperation)).actionGet();
|
||||
}
|
||||
|
||||
private ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) {
|
||||
Assert.isTrue(clazz.isAnnotationPresent(Document.class), "Unable to identify index name. " + clazz.getSimpleName()
|
||||
+ " is not a Document. Make sure the document class is annotated with @Document(indexName=\"foo\")");
|
||||
return elasticsearchConverter.getMappingContext().getPersistentEntity(clazz);
|
||||
}
|
||||
public <T> void refresh(Class<T> clazz, boolean waitForOperation) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
client.admin().indices()
|
||||
.refresh(refreshRequest(persistentEntity.getIndexName()).waitForOperations(waitForOperation)).actionGet();
|
||||
}
|
||||
|
||||
private String[] retrieveIndexNameFromPersistentEntity(Class clazz) {
|
||||
return new String[] { getPersistentEntityFor(clazz).getIndexName() };
|
||||
}
|
||||
private ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) {
|
||||
Assert.isTrue(clazz.isAnnotationPresent(Document.class), "Unable to identify index name. " + clazz.getSimpleName()
|
||||
+ " is not a Document. Make sure the document class is annotated with @Document(indexName=\"foo\")");
|
||||
return elasticsearchConverter.getMappingContext().getPersistentEntity(clazz);
|
||||
}
|
||||
|
||||
private String[] retrieveTypeFromPersistentEntity(Class clazz) {
|
||||
return new String[] { getPersistentEntityFor(clazz).getIndexType() };
|
||||
}
|
||||
private String[] retrieveIndexNameFromPersistentEntity(Class clazz) {
|
||||
return new String[]{getPersistentEntityFor(clazz).getIndexName()};
|
||||
}
|
||||
|
||||
private <T> Page<T> mapResults(SearchResponse response, final Class<T> elementType, final Pageable pageable) {
|
||||
ResultsMapper<T> resultsMapper = new ResultsMapper<T>() {
|
||||
@Override
|
||||
public Page<T> mapResults(SearchResponse response) {
|
||||
long totalHits = response.getHits().totalHits();
|
||||
List<T> results = new ArrayList<T>();
|
||||
for (SearchHit hit : response.getHits()) {
|
||||
if (hit != null) {
|
||||
results.add(mapResult(hit.sourceAsString(), elementType));
|
||||
}
|
||||
}
|
||||
return new PageImpl<T>(results, pageable, totalHits);
|
||||
}
|
||||
};
|
||||
return resultsMapper.mapResults(response);
|
||||
}
|
||||
private String[] retrieveTypeFromPersistentEntity(Class clazz) {
|
||||
return new String[]{getPersistentEntityFor(clazz).getIndexType()};
|
||||
}
|
||||
|
||||
private List<String> extractIds(SearchResponse response) {
|
||||
List<String> ids = new ArrayList<String>();
|
||||
for (SearchHit hit : response.getHits()) {
|
||||
if (hit != null) {
|
||||
ids.add(hit.getId());
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
private <T> FacetedPage<T> mapResults(SearchResponse response, final Class<T> elementType, final Pageable pageable) {
|
||||
ResultsMapper<T> resultsMapper = new ResultsMapper<T>() {
|
||||
@Override
|
||||
public FacetedPage<T> mapResults(SearchResponse response) {
|
||||
long totalHits = response.getHits().totalHits();
|
||||
List<T> results = new ArrayList<T>();
|
||||
for (SearchHit hit : response.getHits()) {
|
||||
if (hit != null) {
|
||||
results.add(mapResult(hit.sourceAsString(), elementType));
|
||||
}
|
||||
}
|
||||
List<FacetResult> facets = new ArrayList<FacetResult>();
|
||||
if (response.getFacets() != null) {
|
||||
for (Facet facet : response.getFacets()) {
|
||||
FacetResult facetResult = FacetMapper.parse(facet);
|
||||
if (facetResult != null) {
|
||||
facets.add(facetResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T mapResult(String source, Class<T> clazz) {
|
||||
if (isBlank(source)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(source, clazz);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
|
||||
}
|
||||
};
|
||||
return resultsMapper.mapResults(response);
|
||||
}
|
||||
|
||||
private static String[] toArray(List<String> values) {
|
||||
String[] valuesAsArray = new String[values.size()];
|
||||
return values.toArray(valuesAsArray);
|
||||
private List<String> extractIds(SearchResponse response) {
|
||||
List<String> ids = new ArrayList<String>();
|
||||
for (SearchHit hit : response.getHits()) {
|
||||
if (hit != null) {
|
||||
ids.add(hit.getId());
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
}
|
||||
private <T> T mapResult(String source, Class<T> clazz) {
|
||||
if (isBlank(source)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(source, clazz);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] toArray(List<String> values) {
|
||||
String[] valuesAsArray = new String[values.size()];
|
||||
return values.toArray(valuesAsArray);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public interface FacetedPage<T> extends Page<T> {
|
||||
|
||||
boolean hasFacets();
|
||||
|
||||
List<FacetResult> getFacets();
|
||||
|
||||
FacetResult getFacet(String name);
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Container for query result and facet results
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T> {
|
||||
|
||||
private List<FacetResult> facets;
|
||||
private Map<String, FacetResult> mapOfFacets = new HashMap<String, FacetResult>();
|
||||
|
||||
public FacetedPageImpl(List<T> content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
public FacetedPageImpl(List<T> content, Pageable pageable, long total) {
|
||||
super(content, pageable, total);
|
||||
}
|
||||
|
||||
public FacetedPageImpl(List<T> content, Pageable pageable, long total, List<FacetResult> facets) {
|
||||
super(content, pageable, total);
|
||||
this.facets = facets;
|
||||
for (FacetResult facet : facets) {
|
||||
mapOfFacets.put(facet.getName(), facet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFacets() {
|
||||
return CollectionUtils.isNotEmpty(facets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FacetResult> getFacets() {
|
||||
return facets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetResult getFacet(String name) {
|
||||
return mapOfFacets.get(name);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public class FactedPageImpl<T> extends PageImpl<T> implements FacetedPage<T> {
|
||||
|
||||
private List<FacetResult> facets;
|
||||
private Map<String, FacetResult> mapOfFacets;
|
||||
|
||||
public FactedPageImpl(List<T> content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
public FactedPageImpl(List<T> content, Pageable pageable, long total) {
|
||||
super(content, pageable, total);
|
||||
}
|
||||
|
||||
public FactedPageImpl(List<T> content, Pageable pageable, long total, List<FacetResult> facets) {
|
||||
super(content, pageable, total);
|
||||
this.facets = facets;
|
||||
for (FacetResult facet : facets) {
|
||||
mapOfFacets.put(facet.getName(), facet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFacets() {
|
||||
return CollectionUtils.isNotEmpty(facets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FacetResult> getFacets() {
|
||||
return facets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetResult getFacet(String name) {
|
||||
return mapOfFacets.get(name);
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.core.query.FacetRequest;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
@ -31,90 +32,177 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
|
||||
class MappingBuilder {
|
||||
|
||||
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
|
||||
public static final String FIELD_STORE = "store";
|
||||
public static final String FIELD_TYPE = "type";
|
||||
public static final String FIELD_INDEX = "index";
|
||||
public static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
|
||||
public static final String FIELD_INDEX_ANALYZER = "index_analyzer";
|
||||
public static final String FIELD_PROPERTIES = "properties";
|
||||
|
||||
static XContentBuilder buildMapping(Class clazz, String indexType, String idFieldName) throws IOException {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject().startObject(indexType).startObject("properties");
|
||||
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
|
||||
public static final String TYPE_VALUE_STRING = "string";
|
||||
public static final String TYPE_VALUE_OBJECT = "object";
|
||||
|
||||
mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY);
|
||||
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
|
||||
|
||||
return xContentBuilder.endObject().endObject().endObject();
|
||||
}
|
||||
static XContentBuilder buildMapping(Class clazz, String indexType, String idFieldName) throws IOException {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject().startObject(indexType).startObject(FIELD_PROPERTIES);
|
||||
|
||||
private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName,
|
||||
String nestedObjectFieldName) throws IOException {
|
||||
mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY);
|
||||
|
||||
java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
|
||||
return xContentBuilder.endObject().endObject().endObject();
|
||||
}
|
||||
|
||||
if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) {
|
||||
xContentBuilder.startObject(nestedObjectFieldName).field("type", "object").startObject("properties");
|
||||
}
|
||||
private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName,
|
||||
String nestedObjectFieldName) throws IOException {
|
||||
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if (isEntity(field)) {
|
||||
mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
|
||||
}
|
||||
Field fieldAnnotation = field.getAnnotation(Field.class);
|
||||
if (isRootObject && fieldAnnotation != null && isIdField(field, idFieldName)) {
|
||||
applyDefaultIdFieldMapping(xContentBuilder, field);
|
||||
} else if (fieldAnnotation != null) {
|
||||
applyFieldAnnotationMapping(xContentBuilder, field, fieldAnnotation);
|
||||
}
|
||||
}
|
||||
java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
|
||||
|
||||
if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) {
|
||||
xContentBuilder.endObject().endObject();
|
||||
}
|
||||
if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) {
|
||||
xContentBuilder.startObject(nestedObjectFieldName).field(FIELD_TYPE, TYPE_VALUE_OBJECT).startObject(FIELD_PROPERTIES);
|
||||
}
|
||||
|
||||
}
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if (isEntity(field)) {
|
||||
mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
|
||||
}
|
||||
Field fieldAnnotation = field.getAnnotation(Field.class);
|
||||
if (isRootObject && fieldAnnotation != null && isIdField(field, idFieldName)) {
|
||||
applyDefaultIdFieldMapping(xContentBuilder, field);
|
||||
} else if (fieldAnnotation != null) {
|
||||
if ((fieldAnnotation.sortable() || fieldAnnotation.facetable()) && TYPE_VALUE_STRING.equals(fieldAnnotation.type())) {
|
||||
addMultiFieldMapping(xContentBuilder, field, fieldAnnotation);
|
||||
} else {
|
||||
addSimpleFieldMapping(xContentBuilder, field, fieldAnnotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
||||
throws IOException {
|
||||
xContentBuilder.startObject(field.getName()).field("type", "string").field("index", "not_analyzed").endObject();
|
||||
}
|
||||
if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) {
|
||||
xContentBuilder.endObject().endObject();
|
||||
}
|
||||
|
||||
private static void applyFieldAnnotationMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
|
||||
Field fieldAnnotation) throws IOException {
|
||||
xContentBuilder.startObject(field.getName());
|
||||
xContentBuilder.field("store", fieldAnnotation.store());
|
||||
if (isNotBlank(fieldAnnotation.type())) {
|
||||
xContentBuilder.field("type", fieldAnnotation.type());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.index())) {
|
||||
xContentBuilder.field("index", fieldAnnotation.index());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
|
||||
xContentBuilder.field("search_analyzer", fieldAnnotation.searchAnalyzer());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.indexAnalyzer())) {
|
||||
xContentBuilder.field("index_analyzer", fieldAnnotation.indexAnalyzer());
|
||||
}
|
||||
xContentBuilder.endObject();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEntity(java.lang.reflect.Field field) {
|
||||
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
|
||||
TypeInformation<?> actualType = typeInformation.getActualType();
|
||||
boolean isComplexType = actualType == null ? false : !SIMPLE_TYPE_HOLDER.isSimpleType(actualType.getType());
|
||||
return isComplexType && !actualType.isCollectionLike() && !Map.class.isAssignableFrom(typeInformation.getType());
|
||||
}
|
||||
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
||||
throws IOException {
|
||||
xContentBuilder.startObject(field.getName())
|
||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
||||
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED);
|
||||
xContentBuilder.endObject();
|
||||
}
|
||||
|
||||
private static boolean isAnyPropertyAnnotatedAsField(java.lang.reflect.Field[] fields) {
|
||||
if (fields != null) {
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if (field.isAnnotationPresent(Field.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Apply mapping for a single @Field annotation
|
||||
*
|
||||
* @param xContentBuilder
|
||||
* @param field
|
||||
* @param fieldAnnotation
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addSimpleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
|
||||
Field fieldAnnotation) throws IOException {
|
||||
xContentBuilder.startObject(field.getName());
|
||||
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
|
||||
if (isNotBlank(fieldAnnotation.type())) {
|
||||
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.index())) {
|
||||
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.indexAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.indexAnalyzer());
|
||||
}
|
||||
xContentBuilder.endObject();
|
||||
}
|
||||
|
||||
private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) {
|
||||
return idFieldName.equals(field.getName());
|
||||
}
|
||||
/**
|
||||
* Multi field mappings for string type fields, support for sorts and facets
|
||||
*
|
||||
* @param builder
|
||||
* @param field
|
||||
* @param annotation
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
|
||||
Field annotation) throws IOException {
|
||||
builder.startObject(field.getName());
|
||||
builder.field(FIELD_TYPE, "multi_field");
|
||||
builder.startObject("fields");
|
||||
//add standard field
|
||||
addSimpleFieldMapping(builder, field, annotation);
|
||||
//facet field - untouched, not analise, stored
|
||||
if (annotation.facetable()) {
|
||||
addFacetMapping(builder, field, annotation);
|
||||
}
|
||||
//sort field - lowercase, not analise, stored
|
||||
if (annotation.sortable()) {
|
||||
addSortMapping(builder, field, annotation);
|
||||
}
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Facet field for string type, for other types we don't need it(long, int, double, float)
|
||||
*
|
||||
* @param builder
|
||||
* @param field
|
||||
* @param annotation
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addFacetMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
|
||||
builder.startObject(FacetRequest.FIELD_UNTOUCHED)
|
||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
||||
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED)
|
||||
.field(FIELD_STORE, true);
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort field for string type, for other types we don't need it(long, int, double, float)
|
||||
* value of the field should be converted to lowercase and not analise
|
||||
*
|
||||
* @param builder
|
||||
* @param field
|
||||
* @param annotation
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addSortMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
|
||||
builder.startObject(FacetRequest.FIELD_SORT)
|
||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
||||
.field(FIELD_INDEX, "keyword")
|
||||
.field(FIELD_STORE, true);
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
private static boolean isEntity(java.lang.reflect.Field field) {
|
||||
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
|
||||
TypeInformation<?> actualType = typeInformation.getActualType();
|
||||
boolean isComplexType = actualType == null ? false : !SIMPLE_TYPE_HOLDER.isSimpleType(actualType.getType());
|
||||
return isComplexType && !actualType.isCollectionLike() && !Map.class.isAssignableFrom(typeInformation.getType());
|
||||
}
|
||||
|
||||
private static boolean isAnyPropertyAnnotatedAsField(java.lang.reflect.Field[] fields) {
|
||||
if (fields != null) {
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if (field.isAnnotationPresent(Field.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) {
|
||||
return idFieldName.equals(field.getName());
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,12 @@ import org.springframework.data.domain.Page;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
*
|
||||
*/
|
||||
|
||||
public interface ResultsMapper<T> {
|
||||
|
||||
Page<T> mapResults(SearchResponse response);
|
||||
FacetedPage<T> mapResults(SearchResponse response);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public class AbstactFacetResult implements FacetResult {
|
||||
|
||||
private final String name;
|
||||
private final FacetType type;
|
||||
|
||||
protected AbstactFacetResult(String name, FacetType type) {
|
||||
Assert.hasText(name, "Facet name can't be null and should have a value");
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
import org.elasticsearch.search.facet.Facet;
|
||||
import org.elasticsearch.search.facet.terms.TermsFacet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class FacetMapper {
|
||||
|
||||
public static FacetResult parse(Facet facet){
|
||||
if(facet instanceof TermsFacet){
|
||||
return parseTerm((TermsFacet) facet);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FacetResult parseTerm(TermsFacet facet) {
|
||||
List<Term> terms = new ArrayList<Term>();
|
||||
for(TermsFacet.Entry entry:facet.getEntries()){
|
||||
terms.add(new Term(entry.getTerm().toString(),entry.getCount()));
|
||||
}
|
||||
return new TermResult(facet.getName(),terms);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
/**
|
||||
* Generic interface for all facets
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*
|
||||
*/
|
||||
public interface FacetResult {
|
||||
|
||||
String getName();
|
||||
|
||||
FacetType getType();
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
public enum FacetType {
|
||||
|
||||
term, renage, histogram
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
/**
|
||||
* Single term
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public class Term {
|
||||
|
||||
private String term;
|
||||
private int count;
|
||||
|
||||
public Term(String term, int count) {
|
||||
this.term = term;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public String getTerm() {
|
||||
return term;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basic term facet result
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public class TermResult extends AbstactFacetResult {
|
||||
|
||||
private List<Term> terms;
|
||||
|
||||
public TermResult(String name, List<Term> terms) {
|
||||
super(name, FacetType.term);
|
||||
this.terms = terms;
|
||||
}
|
||||
|
||||
public List<Term> getTerms() {
|
||||
return terms;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public abstract class AbstractFacetRequest implements FacetRequest {
|
||||
|
||||
private String name;
|
||||
private boolean applyQueryFilter;
|
||||
|
||||
public AbstractFacetRequest(String name) {
|
||||
Assert.hasText(name, "Facet can't be null or empty !!!");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setApplyQueryFilter(boolean applyQueryFilter) {
|
||||
this.applyQueryFilter = applyQueryFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyQueryFilter() {
|
||||
return applyQueryFilter;
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
|
||||
/**
|
||||
* @author Artur Koczak
|
||||
*/
|
||||
public interface FacetRequest {
|
||||
|
||||
public static final String FIELD_UNTOUCHED = "untouched";
|
||||
public static final String FIELD_SORT = "sort";
|
||||
|
||||
FacetBuilder getFacet();
|
||||
|
||||
boolean applyQueryFilter();
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class NativeFacetRequest implements FacetRequest {
|
||||
|
||||
private FacetBuilder facet;
|
||||
private boolean applyQueryFilter;
|
||||
|
||||
public NativeFacetRequest(FacetBuilder facet) {
|
||||
this(facet, false);
|
||||
}
|
||||
|
||||
public NativeFacetRequest(FacetBuilder facet, boolean applyQueryFilter) {
|
||||
this.facet = facet;
|
||||
this.applyQueryFilter = applyQueryFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetBuilder getFacet() {
|
||||
return facet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyQueryFilter() {
|
||||
return applyQueryFilter;
|
||||
}
|
||||
}
|
@ -17,8 +17,12 @@ package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NativeSearchQuery
|
||||
*
|
||||
@ -31,6 +35,17 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
private QueryBuilder query;
|
||||
private FilterBuilder filter;
|
||||
private SortBuilder sort;
|
||||
private List<FacetRequest> facets;
|
||||
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter) {
|
||||
this.query = query;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter, SortBuilder sort) {
|
||||
this.query = query;
|
||||
@ -49,4 +64,20 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
public SortBuilder getElasticsearchSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public void addFacet(FacetRequest facetRequest){
|
||||
if(facets==null){
|
||||
facets = new ArrayList<FacetRequest>();
|
||||
}
|
||||
facets.add(facetRequest);
|
||||
}
|
||||
|
||||
public void setFacets(List<FacetRequest> facets){
|
||||
this.facets = facets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FacetRequest> getFacets() {
|
||||
return facets;
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NativeSearchQuery
|
||||
*
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
@ -30,63 +34,72 @@ import org.springframework.data.domain.Pageable;
|
||||
|
||||
public class NativeSearchQueryBuilder {
|
||||
|
||||
private QueryBuilder queryBuilder;
|
||||
private FilterBuilder filterBuilder;
|
||||
private SortBuilder sortBuilder;
|
||||
private Pageable pageable;
|
||||
private String[] indices;
|
||||
private String[] types;
|
||||
private String[] fields;
|
||||
private QueryBuilder queryBuilder;
|
||||
private FilterBuilder filterBuilder;
|
||||
private SortBuilder sortBuilder;
|
||||
private List<FacetRequest> facetRequests = new ArrayList<FacetRequest>();
|
||||
private Pageable pageable;
|
||||
private String[] indices;
|
||||
private String[] types;
|
||||
private String[] fields;
|
||||
|
||||
public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) {
|
||||
this.queryBuilder = queryBuilder;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) {
|
||||
this.queryBuilder = queryBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withFilter(FilterBuilder filterBuilder) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withFilter(FilterBuilder filterBuilder) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withSort(SortBuilder sortBuilder) {
|
||||
this.sortBuilder = sortBuilder;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withSort(SortBuilder sortBuilder) {
|
||||
this.sortBuilder = sortBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withPageable(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withFacet(FacetRequest facetRequest) {
|
||||
facetRequests.add(facetRequest);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withIndices(String... indices) {
|
||||
this.indices = indices;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withPageable(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withTypes(String... types) {
|
||||
this.types = types;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withIndices(String... indices) {
|
||||
this.indices = indices;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withFields(String... fields) {
|
||||
this.fields = fields;
|
||||
return this;
|
||||
}
|
||||
public NativeSearchQueryBuilder withTypes(String... types) {
|
||||
this.types = types;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQuery build() {
|
||||
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilder);
|
||||
if (pageable != null) {
|
||||
nativeSearchQuery.setPageable(pageable);
|
||||
}
|
||||
if (indices != null) {
|
||||
nativeSearchQuery.addIndices(indices);
|
||||
}
|
||||
if (types != null) {
|
||||
nativeSearchQuery.addTypes(types);
|
||||
}
|
||||
if (fields != null) {
|
||||
nativeSearchQuery.addFields(fields);
|
||||
}
|
||||
return nativeSearchQuery;
|
||||
}
|
||||
public NativeSearchQueryBuilder withFields(String... fields) {
|
||||
this.fields = fields;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQuery build() {
|
||||
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilder);
|
||||
if (pageable != null) {
|
||||
nativeSearchQuery.setPageable(pageable);
|
||||
}
|
||||
if (indices != null) {
|
||||
nativeSearchQuery.addIndices(indices);
|
||||
}
|
||||
if (types != null) {
|
||||
nativeSearchQuery.addTypes(types);
|
||||
}
|
||||
if (fields != null) {
|
||||
nativeSearchQuery.addFields(fields);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(facetRequests)) {
|
||||
nativeSearchQuery.setFacets(facetRequests);
|
||||
}
|
||||
return nativeSearchQuery;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,11 @@ package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NativeSearchQuery
|
||||
*
|
||||
@ -32,4 +35,6 @@ public interface SearchQuery extends Query {
|
||||
FilterBuilder getFilter();
|
||||
|
||||
SortBuilder getElasticsearchSort();
|
||||
|
||||
List<FacetRequest> getFacets();
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.elasticsearch.search.facet.terms.TermsFacet;
|
||||
import org.elasticsearch.search.facet.terms.TermsFacetBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basic term facet
|
||||
*
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class TermFacetRequest extends AbstractFacetRequest {
|
||||
|
||||
private String[] stringFields;
|
||||
private String[] numberFields;
|
||||
private int size = 10;
|
||||
private TermsFacet.ComparatorType order;
|
||||
|
||||
public TermFacetRequest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void setStringFields(String... fields) {
|
||||
this.stringFields = fields;
|
||||
}
|
||||
|
||||
public void setNumberFields(String... fields) {
|
||||
this.numberFields = fields;
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
Assert.isTrue(size <= 0, "Size should be bigger then zero !!!");
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void ascTerm() {
|
||||
order = TermsFacet.ComparatorType.TERM;
|
||||
}
|
||||
|
||||
public void descTerm() {
|
||||
order = TermsFacet.ComparatorType.REVERSE_TERM;
|
||||
}
|
||||
|
||||
public void ascCount() {
|
||||
order = TermsFacet.ComparatorType.REVERSE_COUNT;
|
||||
}
|
||||
|
||||
public void descCount() {
|
||||
order = TermsFacet.ComparatorType.COUNT;
|
||||
}
|
||||
|
||||
private List<String> convertStringFieldsToFullNames() {
|
||||
List<String> result = new ArrayList<String>();
|
||||
if (ArrayUtils.isNotEmpty(stringFields)) {
|
||||
for (String stringField : stringFields) {
|
||||
result.add(stringField + "." + FIELD_UNTOUCHED);
|
||||
}
|
||||
}
|
||||
if (ArrayUtils.isNotEmpty(numberFields)) {
|
||||
Collections.addAll(result, numberFields);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetBuilder getFacet() {
|
||||
List<String> fields = convertStringFieldsToFullNames();
|
||||
Assert.notEmpty(fields, "Please select at last one field !!!");
|
||||
TermsFacetBuilder builder = FacetBuilders.termsFacet(getName()).fields(fields.toArray(new String[fields.size()])).size(size);
|
||||
if (order != null) {
|
||||
builder.order(order);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
/**
|
||||
* Basic term facet
|
||||
*
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class TermFacetRequestBuilder {
|
||||
|
||||
private TermFacetRequest result;
|
||||
|
||||
public TermFacetRequestBuilder(String name) {
|
||||
result = new TermFacetRequest(name);
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder withStringFields(String... fields) {
|
||||
result.setStringFields(fields);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder withNumberFields(String... fields) {
|
||||
result.setNumberFields(fields);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder withSize(int size) {
|
||||
result.setSize(size);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder ascTerm() {
|
||||
result.ascTerm();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder descTerm() {
|
||||
result.descTerm();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder ascCount() {
|
||||
result.ascCount();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder descCount() {
|
||||
result.descCount();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder applyQueryFilter() {
|
||||
result.setApplyQueryFilter(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequest build() {
|
||||
return result;
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.repository;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.FacetedPage;
|
||||
import org.springframework.data.elasticsearch.core.query.SearchQuery;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
@ -37,9 +38,9 @@ public interface ElasticsearchRepository<T, ID extends Serializable> extends Ela
|
||||
|
||||
Iterable<T> search(QueryBuilder query);
|
||||
|
||||
Page<T> search(QueryBuilder query, Pageable pageable);
|
||||
FacetedPage<T> search(QueryBuilder query, Pageable pageable);
|
||||
|
||||
Page<T> search(SearchQuery searchQuery);
|
||||
FacetedPage<T> search(SearchQuery searchQuery);
|
||||
|
||||
Page<T> searchSimilar(T entity, SearchQuery searchQuery);
|
||||
Page<T> searchSimilar(T entity, SearchQuery searchQuery);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.FacetedPage;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.util.Assert;
|
||||
@ -180,13 +181,13 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> search(QueryBuilder query, Pageable pageable) {
|
||||
public FacetedPage<T> search(QueryBuilder query, Pageable pageable) {
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build();
|
||||
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> search(SearchQuery query) {
|
||||
public FacetedPage<T> search(SearchQuery query) {
|
||||
return elasticsearchOperations.queryForPage(query, getEntityClass());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,66 @@
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Simple type to test facets
|
||||
*/
|
||||
@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1")
|
||||
public class Article {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
private String title;
|
||||
|
||||
@Field(type = "string", facetable = true)
|
||||
private List<String> authors = new ArrayList<String>();
|
||||
|
||||
@Field(type = "integer", facetable = true)
|
||||
private List<Integer> publishedYears = new ArrayList<Integer>();
|
||||
|
||||
public Article() {
|
||||
|
||||
}
|
||||
|
||||
public Article(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public List<String> getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public void setAuthors(List<String> authors) {
|
||||
this.authors = authors;
|
||||
}
|
||||
|
||||
public List<Integer> getPublishedYears() {
|
||||
return publishedYears;
|
||||
}
|
||||
|
||||
public void setPublishedYears(List<Integer> publishedYears) {
|
||||
this.publishedYears = publishedYears;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Simple type to test facets
|
||||
*/
|
||||
public class ArticleBuilder {
|
||||
|
||||
private Article resutl;
|
||||
|
||||
public ArticleBuilder(String id) {
|
||||
resutl = new Article(id);
|
||||
}
|
||||
|
||||
public ArticleBuilder title(String title) {
|
||||
resutl.setTitle(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ArticleBuilder addAuthor(String author) {
|
||||
resutl.getAuthors().add(author);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ArticleBuilder addPublishedYear(Integer year) {
|
||||
resutl.getPublishedYears().add(year);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Article build() {
|
||||
return resutl;
|
||||
}
|
||||
|
||||
public IndexQuery buildIndex(){
|
||||
IndexQuery indexQuery = new IndexQuery();
|
||||
indexQuery.setId(resutl.getId());
|
||||
indexQuery.setObject(resutl);
|
||||
return indexQuery;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright 2013 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilders;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.elasticsearch.Article;
|
||||
import org.springframework.data.elasticsearch.ArticleBuilder;
|
||||
import org.springframework.data.elasticsearch.core.facet.Term;
|
||||
import org.springframework.data.elasticsearch.core.facet.TermResult;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.elasticsearch.index.query.FilterBuilders.termFilter;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.fieldQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Jonathan Yan
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||
public class ElasticsearchTemplateFacetTests {
|
||||
|
||||
public static final String RIZWAN_IDREES = "Rizwan Idrees";
|
||||
public static final String MOHSIN_HUSEN = "Mohsin Husen";
|
||||
public static final String JONATHAN_YAN = "Jonathan Yan";
|
||||
public static final String ARTUR_KONCZAK = "Artur Konczak";
|
||||
public static final int YEAR_2002 = 2002;
|
||||
public static final int YEAR_2001 = 2001;
|
||||
public static final int YEAR_2000 = 2000;
|
||||
@Autowired
|
||||
private ElasticsearchTemplate elasticsearchTemplate;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
elasticsearchTemplate.deleteIndex(Article.class);
|
||||
elasticsearchTemplate.createIndex(Article.class);
|
||||
elasticsearchTemplate.putMapping(Article.class);
|
||||
elasticsearchTemplate.refresh(Article.class, true);
|
||||
|
||||
IndexQuery article1 = new ArticleBuilder("1").title("article four").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addAuthor(JONATHAN_YAN).buildIndex();
|
||||
IndexQuery article2 = new ArticleBuilder("2").title("article three").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addPublishedYear(YEAR_2000).buildIndex();
|
||||
IndexQuery article3 = new ArticleBuilder("3").title("article two").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).buildIndex();
|
||||
IndexQuery article4 = new ArticleBuilder("4").title("article one").addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).buildIndex();
|
||||
|
||||
elasticsearchTemplate.index(article1);
|
||||
elasticsearchTemplate.index(article2);
|
||||
elasticsearchTemplate.index(article3);
|
||||
elasticsearchTemplate.index(article4);
|
||||
elasticsearchTemplate.refresh(Article.class, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedAuthorsForGivenQueryWithDefaultOrder() {
|
||||
|
||||
// given
|
||||
String facetName = "fauthors";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFacet(new TermFacetRequestBuilder(facetName).withStringFields("authors").build()).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(RIZWAN_IDREES));
|
||||
assertThat(term.getCount(), is(4));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(3);
|
||||
assertThat(term.getTerm(), is(JONATHAN_YAN));
|
||||
assertThat(term.getCount(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedAuthorsForGivenFilteredQuery() {
|
||||
|
||||
// given
|
||||
String facetName = "fauthors";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title","four")))
|
||||
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().withStringFields("authors").build()).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(RIZWAN_IDREES));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
|
||||
assertThat(term.getCount(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedAuthorsForGivenQueryOrderedByTerm() {
|
||||
|
||||
// given
|
||||
String facetName = "fauthors";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFacet(new TermFacetRequestBuilder(facetName).withStringFields("authors").ascTerm().build()).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(JONATHAN_YAN));
|
||||
assertThat(term.getCount(), is(1));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(3);
|
||||
assertThat(term.getTerm(), is(RIZWAN_IDREES));
|
||||
assertThat(term.getCount(), is(4));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedAuthorsForGivenQueryOrderedByCountAsc() {
|
||||
|
||||
// given
|
||||
String facetName = "fauthors";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFacet(new TermFacetRequestBuilder(facetName).withStringFields("authors").ascCount().build()).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(JONATHAN_YAN));
|
||||
assertThat(term.getCount(), is(1));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(3);
|
||||
assertThat(term.getTerm(), is(RIZWAN_IDREES));
|
||||
assertThat(term.getCount(), is(4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedYearsForGivenQuery() {
|
||||
|
||||
// given
|
||||
String facetName = "fyears";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFacet(new TermFacetRequestBuilder(facetName).withNumberFields("publishedYears").descCount().build()).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
assertThat(facet.getTerms().size(), is(equalTo(3)));
|
||||
|
||||
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2000)));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2001)));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2002)));
|
||||
assertThat(term.getCount(), is(1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldReturnSingleFacetOverYearsAndAuthorsForGivenQuery() {
|
||||
|
||||
// given
|
||||
String facetName = "fyears";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFacet(new TermFacetRequestBuilder(facetName).withNumberFields("publishedYears").withStringFields("authors").ascTerm().build()).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
assertThat(facet.getTerms().size(), is(equalTo(7)));
|
||||
|
||||
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2000)));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2001)));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2002)));
|
||||
assertThat(term.getCount(), is(1));
|
||||
|
||||
term = facet.getTerms().get(3);
|
||||
assertThat(term.getTerm(), is(ARTUR_KONCZAK));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(4);
|
||||
assertThat(term.getTerm(), is(JONATHAN_YAN));
|
||||
assertThat(term.getCount(), is(1));
|
||||
|
||||
term = facet.getTerms().get(5);
|
||||
assertThat(term.getTerm(), is(MOHSIN_HUSEN));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(6);
|
||||
assertThat(term.getTerm(), is(RIZWAN_IDREES));
|
||||
assertThat(term.getCount(), is(4));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedYearsAndFacetedAuthorsForGivenQuery() {
|
||||
|
||||
// given
|
||||
String numberFacetName = "fAuthors";
|
||||
String stringFacetName = "fyears";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFacet(new TermFacetRequestBuilder(numberFacetName).withNumberFields("publishedYears").ascTerm().build())
|
||||
.withFacet(new TermFacetRequestBuilder(stringFacetName).withStringFields("authors").ascTerm().build())
|
||||
.build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult numberFacet = (TermResult) result.getFacet(numberFacetName);
|
||||
assertThat(numberFacet.getTerms().size(), is(equalTo(3)));
|
||||
|
||||
Term numberTerm = numberFacet.getTerms().get(0);
|
||||
assertThat(numberTerm.getTerm(), is(Integer.toString(YEAR_2000)));
|
||||
assertThat(numberTerm.getCount(), is(3));
|
||||
|
||||
numberTerm = numberFacet.getTerms().get(1);
|
||||
assertThat(numberTerm.getTerm(), is(Integer.toString(YEAR_2001)));
|
||||
assertThat(numberTerm.getCount(), is(2));
|
||||
|
||||
numberTerm = numberFacet.getTerms().get(2);
|
||||
assertThat(numberTerm.getTerm(), is(Integer.toString(YEAR_2002)));
|
||||
assertThat(numberTerm.getCount(), is(1));
|
||||
|
||||
|
||||
TermResult stringFacet = (TermResult) result.getFacet(stringFacetName);
|
||||
Term stringTerm = stringFacet.getTerms().get(0);
|
||||
assertThat(stringTerm.getTerm(), is(ARTUR_KONCZAK));
|
||||
assertThat(stringTerm.getCount(), is(3));
|
||||
|
||||
stringTerm = stringFacet.getTerms().get(1);
|
||||
assertThat(stringTerm.getTerm(), is(JONATHAN_YAN));
|
||||
assertThat(stringTerm.getCount(), is(1));
|
||||
|
||||
stringTerm = stringFacet.getTerms().get(2);
|
||||
assertThat(stringTerm.getTerm(), is(MOHSIN_HUSEN));
|
||||
assertThat(stringTerm.getCount(), is(2));
|
||||
|
||||
stringTerm = stringFacet.getTerms().get(3);
|
||||
assertThat(stringTerm.getTerm(), is(RIZWAN_IDREES));
|
||||
assertThat(stringTerm.getCount(), is(4));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldReturnFacetedYearsForNativeFacet() {
|
||||
|
||||
// given
|
||||
String facetName = "fyears";
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withFacet(new NativeFacetRequest(FacetBuilders.termsFacet(facetName).field("publishedYears"))).build();
|
||||
// when
|
||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
||||
// then
|
||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||
|
||||
TermResult facet = (TermResult) result.getFacet(facetName);
|
||||
assertThat(facet.getTerms().size(), is(equalTo(3)));
|
||||
|
||||
|
||||
Term term = facet.getTerms().get(0);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2000)));
|
||||
assertThat(term.getCount(), is(3));
|
||||
|
||||
term = facet.getTerms().get(1);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2001)));
|
||||
assertThat(term.getCount(), is(2));
|
||||
|
||||
term = facet.getTerms().get(2);
|
||||
assertThat(term.getTerm(), is(Integer.toString(YEAR_2002)));
|
||||
assertThat(term.getCount(), is(1));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -465,12 +465,12 @@ public class ElasticsearchTemplateTests {
|
||||
// when
|
||||
Page<String> page = elasticsearchTemplate.queryForPage(searchQuery, new ResultsMapper<String>() {
|
||||
@Override
|
||||
public Page<String> mapResults(SearchResponse response) {
|
||||
public FacetedPage<String> mapResults(SearchResponse response) {
|
||||
List<String> values = new ArrayList<String>();
|
||||
for (SearchHit searchHit : response.getHits()) {
|
||||
values.add((String) searchHit.field("message").value());
|
||||
}
|
||||
return new PageImpl<String>(values);
|
||||
return new FacetedPageImpl<String>(values);
|
||||
}
|
||||
});
|
||||
// then
|
||||
@ -543,7 +543,7 @@ public class ElasticsearchTemplateTests {
|
||||
while (hasRecords) {
|
||||
Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L, new ResultsMapper<SampleEntity>() {
|
||||
@Override
|
||||
public Page<SampleEntity> mapResults(SearchResponse response) {
|
||||
public FacetedPage<SampleEntity> mapResults(SearchResponse response) {
|
||||
List<SampleEntity> chunk = new ArrayList<SampleEntity>();
|
||||
for (SearchHit searchHit : response.getHits()) {
|
||||
if (response.getHits().getHits().length <= 0) {
|
||||
@ -556,7 +556,7 @@ public class ElasticsearchTemplateTests {
|
||||
}
|
||||
if(chunk.size() > 0){
|
||||
|
||||
return new PageImpl<SampleEntity>(chunk);
|
||||
return new FacetedPageImpl<SampleEntity>(chunk);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user