diff --git a/pom.xml b/pom.xml index f25921b1c..3c66987ce 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 3.2.1 2.6 - 6.2.2 + 6.3.0 2.9.1 2.2.0.BUILD-SNAPSHOT spring.data.elasticsearch @@ -79,6 +79,18 @@ + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch} + + + commons-logging + commons-logging + + + + org.slf4j log4j-over-slf4j @@ -169,7 +181,7 @@ org.projectlombok lombok ${lombok} - test + provided diff --git a/src/main/java/org/springframework/data/elasticsearch/client/RestClientFactoryBean.java b/src/main/java/org/springframework/data/elasticsearch/client/RestClientFactoryBean.java new file mode 100644 index 000000000..8e2b9fa21 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/client/RestClientFactoryBean.java @@ -0,0 +1,95 @@ +/* + * Copyright 2018 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.client; + +import static org.apache.commons.lang.StringUtils.*; + +import lombok.extern.slf4j.Slf4j; + +import java.net.URL; +import java.util.ArrayList; + +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * RestClientFactoryBean + * + * @author Don Wellington + */ +@Slf4j +public class RestClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean { + + private RestHighLevelClient client; + private String hosts = "http://localhost:9200"; + static final String COMMA = ","; + + @Override + public void destroy() throws Exception { + try { + log.info("Closing elasticSearch client"); + if (client != null) { + client.close(); + } + } catch (final Exception e) { + log.error("Error closing ElasticSearch client: ", e); + } + } + + @Override + public void afterPropertiesSet() throws Exception { + buildClient(); + } + + @Override + public RestHighLevelClient getObject() throws Exception { + return client; + } + + @Override + public Class getObjectType() { + return RestHighLevelClient.class; + } + + @Override + public boolean isSingleton() { + return false; + } + + protected void buildClient() throws Exception { + + Assert.hasText(hosts, "[Assertion Failed] At least one host must be set."); + ArrayList httpHosts = new ArrayList(); + for (String host : split(hosts, COMMA)) { + URL hostUrl = new URL(host); + httpHosts.add(new HttpHost(hostUrl.getHost(), hostUrl.getPort(), hostUrl.getProtocol())); + } + client = new RestHighLevelClient(RestClient.builder(httpHosts.toArray(new HttpHost[httpHosts.size()]))); + } + + public void setHosts(String hosts) { + this.hosts = hosts; + } + + public String getHosts() { + return this.hosts; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandler.java b/src/main/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandler.java index 315020c6a..f33627516 100644 --- a/src/main/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandler.java +++ b/src/main/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2018 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. @@ -25,8 +25,8 @@ import org.springframework.data.repository.config.RepositoryConfigurationExtensi * * @author Rizwan Idrees * @author Mohsin Husen + * @author Don Wellington */ - public class ElasticsearchNamespaceHandler extends NamespaceHandlerSupport { @Override @@ -37,5 +37,6 @@ public class ElasticsearchNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("repositories", parser); registerBeanDefinitionParser("node-client", new NodeClientBeanDefinitionParser()); registerBeanDefinitionParser("transport-client", new TransportClientBeanDefinitionParser()); + registerBeanDefinitionParser("rest-client", new RestClientBeanDefinitionParser()); } } diff --git a/src/main/java/org/springframework/data/elasticsearch/config/RestClientBeanDefinitionParser.java b/src/main/java/org/springframework/data/elasticsearch/config/RestClientBeanDefinitionParser.java new file mode 100644 index 000000000..5fcdf1f47 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/config/RestClientBeanDefinitionParser.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018 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.config; + +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.elasticsearch.client.RestClientFactoryBean; +import org.w3c.dom.Element; + +/** + * @author Don Wellington + */ +public class RestClientBeanDefinitionParser extends AbstractBeanDefinitionParser { + + @Override + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(RestClientFactoryBean.class); + setConfigurations(element, builder); + return getSourcedBeanDefinition(builder, element, parserContext); + } + + private void setConfigurations(Element element, BeanDefinitionBuilder builder) { + builder.addPropertyValue("hosts", element.getAttribute("hosts")); + } + + private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source, + ParserContext context) { + AbstractBeanDefinition definition = builder.getBeanDefinition(); + definition.setSource(context.extractSource(source)); + return definition; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java index 65a409777..3b27d5cc6 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java @@ -1,577 +1,572 @@ -/* - * Copyright 2013-2016 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.action.update.UpdateResponse; -import org.elasticsearch.client.Client; -import org.elasticsearch.cluster.metadata.AliasMetaData; -import org.elasticsearch.common.Nullable; -import org.springframework.data.domain.Page; -import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.query.*; -import org.springframework.data.util.CloseableIterator; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * ElasticsearchOperations - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Kevin Leturc - */ -public interface ElasticsearchOperations { - - /** - * @return Converter in use - */ - ElasticsearchConverter getElasticsearchConverter(); - - /** - * @return elasticsearch client - */ - Client getClient(); - - /** - * Create an index for a class - * - * @param clazz - * @param - */ - boolean createIndex(Class clazz); - - /** - * Create an index for given indexName - * - * @param indexName - */ - boolean createIndex(String indexName); - - /** - * Create an index for given indexName and Settings - * - * @param indexName - * @param settings - */ - boolean createIndex(String indexName, Object settings); - - /** - * Create an index for given class and Settings - * - * @param clazz - * @param settings - */ - boolean createIndex(Class clazz, Object settings); - - /** - * Create mapping for a class - * - * @param clazz - * @param - */ - boolean putMapping(Class clazz); - - /** - * Create mapping for a given indexName and type - * - * @param indexName - * @param type - * @param mappings - */ - boolean putMapping(String indexName, String type, Object mappings); - - /** - * Create mapping for a class - * - * @param clazz - * @param mappings - */ - boolean putMapping(Class clazz, Object mappings); - - - /** - * Get mapping for a class - * - * @param clazz - * @param - */ - Map getMapping(Class clazz); - - /** - * Get mapping for a given indexName and type - * - * @param indexName - * @param type - */ - Map getMapping(String indexName, String type); - - /** - * Get settings for a given indexName - * - * @param indexName - */ - Map getSetting(String indexName); - - /** - * Get settings for a given class - * - * @param clazz - */ - Map getSetting(Class clazz); - - - /** - * Execute the query against elasticsearch and return the first returned object - * - * @param query - * @param clazz - * @return the first matching object - */ - T queryForObject(GetQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return the first returned object using custom mapper - * - * @param query - * @param clazz - * @param mapper - * @return the first matching object - */ - T queryForObject(GetQuery query, Class clazz, GetResultMapper mapper); - - /** - * Execute the query against elasticsearch and return the first returned object - * - * @param query - * @param clazz - * @return the first matching object - */ - T queryForObject(CriteriaQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return the first returned object - * - * @param query - * @param clazz - * @return the first matching object - */ - T queryForObject(StringQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return result as {@link Page} - * - * @param query - * @param clazz - * @return - */ - Page queryForPage(SearchQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return result as {@link Page} using custom mapper - * - * @param query - * @param clazz - * @return - */ - Page queryForPage(SearchQuery query, Class clazz, SearchResultMapper mapper); - - /** - * Execute the query against elasticsearch and return result as {@link Page} - * - * @param query - * @param clazz - * @return - */ - Page queryForPage(CriteriaQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return result as {@link Page} - * - * @param query - * @param clazz - * @return - */ - Page queryForPage(StringQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return result as {@link Page} using custom mapper - * - * @param query - * @param clazz - * @return - */ - Page queryForPage(StringQuery query, Class clazz, SearchResultMapper mapper); - - /** - * Executes the given {@link CriteriaQuery} against elasticsearch and return result as {@link CloseableIterator}. - *

- * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error. - * - * @param element return type - * @param query - * @param clazz - * @return - * @since 1.3 - */ - CloseableIterator stream(CriteriaQuery query, Class clazz); - - /** - * Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator}. - *

- * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error. - * - * @param element return type - * @param query - * @param clazz - * @return - * @since 1.3 - */ - CloseableIterator stream(SearchQuery query, Class clazz); - - /** - * Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator} using custom mapper. - *

- * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error. - * - * @param element return type - * @param query - * @param clazz - * @param mapper - * @return - * @since 1.3 - */ - CloseableIterator stream(SearchQuery query, Class clazz, SearchResultMapper mapper); - - /** - * Execute the criteria query against elasticsearch and return result as {@link List} - * - * @param query - * @param clazz - * @param - * @return - */ - List queryForList(CriteriaQuery query, Class clazz); - - /** - * Execute the string query against elasticsearch and return result as {@link List} - * - * @param query - * @param clazz - * @param - * @return - */ - List queryForList(StringQuery query, Class clazz); - - /** - * Execute the search query against elasticsearch and return result as {@link List} - * - * @param query - * @param clazz - * @param - * @return - */ - List queryForList(SearchQuery query, Class clazz); - - /** - * Execute the query against elasticsearch and return ids - * - * @param query - * @return - */ - List queryForIds(SearchQuery query); - - /** - * return number of elements found by given query - * - * @param query - * @param clazz - * @return - */ - long count(CriteriaQuery query, Class clazz); - - /** - * return number of elements found by given query - * - * @param query - * @return - */ - long count(CriteriaQuery query); - - /** - * return number of elements found by given query - * - * @param query - * @param clazz - * @return - */ - long count(SearchQuery query, Class clazz); - - /** - * return number of elements found by given query - * - * @param query - * @return - */ - long count(SearchQuery query); - - /** - * Execute a multiGet against elasticsearch for the given ids - * - * @param searchQuery - * @param clazz - * @return - */ - LinkedList multiGet(SearchQuery searchQuery, Class clazz); - - /** - * Execute a multiGet against elasticsearch for the given ids with MultiGetResultMapper - * - * @param searchQuery - * @param clazz - * @param multiGetResultMapper - * @return - */ - LinkedList multiGet(SearchQuery searchQuery, Class clazz, MultiGetResultMapper multiGetResultMapper); - - /** - * Index an object. Will do save or update - * - * @param query - * @return returns the document id - */ - String index(IndexQuery query); - - /** - * Partial update of the document - * - * @param updateQuery - * @return - */ - UpdateResponse update(UpdateQuery updateQuery); - - /** - * Bulk index all objects. Will do save or update - * - * @param queries - */ - void bulkIndex(List queries); - - /** - * Bulk update all objects. Will do update - * - * @param queries - */ - void bulkUpdate(List queries); - - /** - * Delete the one object with provided id - * - * @param indexName - * @param type - * @param id - * @return documentId of the document deleted - */ - String delete(String indexName, String type, String id); - - - /** - * Delete all records matching the criteria - * - * @param clazz - * @param criteriaQuery - */ - void delete(CriteriaQuery criteriaQuery, Class clazz); - /** - * Delete the one object with provided id - * - * @param clazz - * @param id - * @return documentId of the document deleted - */ - String delete(Class clazz, String id); - - /** - * Delete all records matching the query - * - * @param clazz - * @param query - */ - void delete(DeleteQuery query, Class clazz); - - /** - * Delete all records matching the query - * - * @param query - */ - void delete(DeleteQuery query); - - /** - * Deletes an index for given entity - * - * @param clazz - * @param - * @return - */ - boolean deleteIndex(Class clazz); - - /** - * Deletes an index for given indexName - * - * @param indexName - * @return - */ - boolean deleteIndex(String indexName); - - /** - * check if index is exists - * - * @param clazz - * @param - * @return - */ - boolean indexExists(Class clazz); - - /** - * check if index is exists for given IndexName - * - * @param indexName - * @return - */ - boolean indexExists(String indexName); - - /** - * check if type is exists in an index - * - * @param index - * @param type - * @return - */ - boolean typeExists(String index, String type); - - /** - * refresh the index - * - * @param indexName - * - */ - void refresh(String indexName); - - /** - * refresh the index - * - * @param clazz - * - */ - void refresh(Class clazz); - - /** - * Returns scrolled page for given query - * - * @param query The search query. - * @param scrollTimeInMillis The time in millisecond for scroll feature - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. - * @param clazz The class of entity to retrieve. - * @return The scan id for input query. - */ - Page startScroll(long scrollTimeInMillis, SearchQuery query, Class clazz); - - /** - * Returns scrolled page for given query - * - * @param query The search query. - * @param scrollTimeInMillis The time in millisecond for scroll feature - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. - * @param mapper Custom impl to map result to entities - * @return The scan id for input query. - */ - Page startScroll(long scrollTimeInMillis, SearchQuery query, Class clazz, SearchResultMapper mapper); - - /** - * Returns scrolled page for given query - * - * @param criteriaQuery The search query. - * @param scrollTimeInMillis The time in millisecond for scroll feature - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. - * @param clazz The class of entity to retrieve. - * @return The scan id for input query. - */ - Page startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class clazz); - - /** - * Returns scrolled page for given query - * - * @param criteriaQuery The search query. - * @param scrollTimeInMillis The time in millisecond for scroll feature - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. - * @param mapper Custom impl to map result to entities - * @return The scan id for input query. - */ - Page startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class clazz, SearchResultMapper mapper); - - - Page continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz); - Page continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz, SearchResultMapper mapper); - /** - * Clears the search contexts associated with specified scroll ids. - * - * @param scrollId - * - */ - void clearScroll(String scrollId); - - /** - * more like this query to search for documents that are "like" a specific document. - * - * @param query - * @param clazz - * @param - * @return - */ - Page moreLikeThis(MoreLikeThisQuery query, Class clazz); - - /** - * adding new alias - * - * @param query - * @return - */ - Boolean addAlias(AliasQuery query); - - /** - * removing previously created alias - * - * @param query - * @return - */ - Boolean removeAlias(AliasQuery query); - - /** - * get all the alias pointing to specified index - * - * @param indexName - * @return - */ - List queryForAlias(String indexName); - - - T query(SearchQuery query, ResultsExtractor resultsExtractor); - - - ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz); -} +/* + * Copyright 2013-2018 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.action.update.UpdateResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.common.Nullable; +import org.springframework.data.domain.Page; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.util.CloseableIterator; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * ElasticsearchOperations + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Kevin Leturc + */ +public interface ElasticsearchOperations { + + /** + * @return Converter in use + */ + ElasticsearchConverter getElasticsearchConverter(); + + /** + * Create an index for a class + * + * @param clazz + * @param + */ + boolean createIndex(Class clazz); + + /** + * Create an index for given indexName + * + * @param indexName + */ + boolean createIndex(String indexName); + + /** + * Create an index for given indexName and Settings + * + * @param indexName + * @param settings + */ + boolean createIndex(String indexName, Object settings); + + /** + * Create an index for given class and Settings + * + * @param clazz + * @param settings + */ + boolean createIndex(Class clazz, Object settings); + + /** + * Create mapping for a class + * + * @param clazz + * @param + */ + boolean putMapping(Class clazz); + + /** + * Create mapping for a given indexName and type + * + * @param indexName + * @param type + * @param mappings + */ + boolean putMapping(String indexName, String type, Object mappings); + + /** + * Create mapping for a class + * + * @param clazz + * @param mappings + */ + boolean putMapping(Class clazz, Object mappings); + + + /** + * Get mapping for a class + * + * @param clazz + * @param + */ + Map getMapping(Class clazz); + + /** + * Get mapping for a given indexName and type + * + * @param indexName + * @param type + */ + Map getMapping(String indexName, String type); + + /** + * Get settings for a given indexName + * + * @param indexName + */ + Map getSetting(String indexName); + + /** + * Get settings for a given class + * + * @param clazz + */ + Map getSetting(Class clazz); + + + /** + * Execute the query against elasticsearch and return the first returned object + * + * @param query + * @param clazz + * @return the first matching object + */ + T queryForObject(GetQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return the first returned object using custom mapper + * + * @param query + * @param clazz + * @param mapper + * @return the first matching object + */ + T queryForObject(GetQuery query, Class clazz, GetResultMapper mapper); + + /** + * Execute the query against elasticsearch and return the first returned object + * + * @param query + * @param clazz + * @return the first matching object + */ + T queryForObject(CriteriaQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return the first returned object + * + * @param query + * @param clazz + * @return the first matching object + */ + T queryForObject(StringQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return result as {@link Page} + * + * @param query + * @param clazz + * @return + */ + Page queryForPage(SearchQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return result as {@link Page} using custom mapper + * + * @param query + * @param clazz + * @return + */ + Page queryForPage(SearchQuery query, Class clazz, SearchResultMapper mapper); + + /** + * Execute the query against elasticsearch and return result as {@link Page} + * + * @param query + * @param clazz + * @return + */ + Page queryForPage(CriteriaQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return result as {@link Page} + * + * @param query + * @param clazz + * @return + */ + Page queryForPage(StringQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return result as {@link Page} using custom mapper + * + * @param query + * @param clazz + * @return + */ + Page queryForPage(StringQuery query, Class clazz, SearchResultMapper mapper); + + /** + * Executes the given {@link CriteriaQuery} against elasticsearch and return result as {@link CloseableIterator}. + *

+ * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error. + * + * @param element return type + * @param query + * @param clazz + * @return + * @since 1.3 + */ + CloseableIterator stream(CriteriaQuery query, Class clazz); + + /** + * Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator}. + *

+ * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error. + * + * @param element return type + * @param query + * @param clazz + * @return + * @since 1.3 + */ + CloseableIterator stream(SearchQuery query, Class clazz); + + /** + * Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator} using custom mapper. + *

+ * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error. + * + * @param element return type + * @param query + * @param clazz + * @param mapper + * @return + * @since 1.3 + */ + CloseableIterator stream(SearchQuery query, Class clazz, SearchResultMapper mapper); + + /** + * Execute the criteria query against elasticsearch and return result as {@link List} + * + * @param query + * @param clazz + * @param + * @return + */ + List queryForList(CriteriaQuery query, Class clazz); + + /** + * Execute the string query against elasticsearch and return result as {@link List} + * + * @param query + * @param clazz + * @param + * @return + */ + List queryForList(StringQuery query, Class clazz); + + /** + * Execute the search query against elasticsearch and return result as {@link List} + * + * @param query + * @param clazz + * @param + * @return + */ + List queryForList(SearchQuery query, Class clazz); + + /** + * Execute the query against elasticsearch and return ids + * + * @param query + * @return + */ + List queryForIds(SearchQuery query); + + /** + * return number of elements found by given query + * + * @param query + * @param clazz + * @return + */ + long count(CriteriaQuery query, Class clazz); + + /** + * return number of elements found by given query + * + * @param query + * @return + */ + long count(CriteriaQuery query); + + /** + * return number of elements found by given query + * + * @param query + * @param clazz + * @return + */ + long count(SearchQuery query, Class clazz); + + /** + * return number of elements found by given query + * + * @param query + * @return + */ + long count(SearchQuery query); + + /** + * Execute a multiGet against elasticsearch for the given ids + * + * @param searchQuery + * @param clazz + * @return + */ + LinkedList multiGet(SearchQuery searchQuery, Class clazz); + + /** + * Execute a multiGet against elasticsearch for the given ids with MultiGetResultMapper + * + * @param searchQuery + * @param clazz + * @param multiGetResultMapper + * @return + */ + LinkedList multiGet(SearchQuery searchQuery, Class clazz, MultiGetResultMapper multiGetResultMapper); + + /** + * Index an object. Will do save or update + * + * @param query + * @return returns the document id + */ + String index(IndexQuery query); + + /** + * Partial update of the document + * + * @param updateQuery + * @return + */ + UpdateResponse update(UpdateQuery updateQuery); + + /** + * Bulk index all objects. Will do save or update + * + * @param queries + */ + void bulkIndex(List queries); + + /** + * Bulk update all objects. Will do update + * + * @param queries + */ + void bulkUpdate(List queries); + + /** + * Delete the one object with provided id + * + * @param indexName + * @param type + * @param id + * @return documentId of the document deleted + */ + String delete(String indexName, String type, String id); + + + /** + * Delete all records matching the criteria + * + * @param clazz + * @param criteriaQuery + */ + void delete(CriteriaQuery criteriaQuery, Class clazz); + /** + * Delete the one object with provided id + * + * @param clazz + * @param id + * @return documentId of the document deleted + */ + String delete(Class clazz, String id); + + /** + * Delete all records matching the query + * + * @param clazz + * @param query + */ + void delete(DeleteQuery query, Class clazz); + + /** + * Delete all records matching the query + * + * @param query + */ + void delete(DeleteQuery query); + + /** + * Deletes an index for given entity + * + * @param clazz + * @param + * @return + */ + boolean deleteIndex(Class clazz); + + /** + * Deletes an index for given indexName + * + * @param indexName + * @return + */ + boolean deleteIndex(String indexName); + + /** + * check if index is exists + * + * @param clazz + * @param + * @return + */ + boolean indexExists(Class clazz); + + /** + * check if index is exists for given IndexName + * + * @param indexName + * @return + */ + boolean indexExists(String indexName); + + /** + * check if type is exists in an index + * + * @param index + * @param type + * @return + */ + boolean typeExists(String index, String type); + + /** + * refresh the index + * + * @param indexName + * + */ + void refresh(String indexName); + + /** + * refresh the index + * + * @param clazz + * + */ + void refresh(Class clazz); + + /** + * Returns scrolled page for given query + * + * @param query The search query. + * @param scrollTimeInMillis The time in millisecond for scroll feature + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. + * @param clazz The class of entity to retrieve. + * @return The scan id for input query. + */ + Page startScroll(long scrollTimeInMillis, SearchQuery query, Class clazz); + + /** + * Returns scrolled page for given query + * + * @param query The search query. + * @param scrollTimeInMillis The time in millisecond for scroll feature + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. + * @param mapper Custom impl to map result to entities + * @return The scan id for input query. + */ + Page startScroll(long scrollTimeInMillis, SearchQuery query, Class clazz, SearchResultMapper mapper); + + /** + * Returns scrolled page for given query + * + * @param criteriaQuery The search query. + * @param scrollTimeInMillis The time in millisecond for scroll feature + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. + * @param clazz The class of entity to retrieve. + * @return The scan id for input query. + */ + Page startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class clazz); + + /** + * Returns scrolled page for given query + * + * @param criteriaQuery The search query. + * @param scrollTimeInMillis The time in millisecond for scroll feature + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. + * @param mapper Custom impl to map result to entities + * @return The scan id for input query. + */ + Page startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class clazz, SearchResultMapper mapper); + + + Page continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz); + Page continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz, SearchResultMapper mapper); + /** + * Clears the search contexts associated with specified scroll ids. + * + * @param scrollId + * + */ + void clearScroll(String scrollId); + + /** + * more like this query to search for documents that are "like" a specific document. + * + * @param query + * @param clazz + * @param + * @return + */ + Page moreLikeThis(MoreLikeThisQuery query, Class clazz); + + /** + * adding new alias + * + * @param query + * @return + */ + Boolean addAlias(AliasQuery query); + + /** + * removing previously created alias + * + * @param query + * @return + */ + Boolean removeAlias(AliasQuery query); + + /** + * get all the alias pointing to specified index + * + * @param indexName + * @return + */ + List queryForAlias(String indexName); + + + T query(SearchQuery query, ResultsExtractor resultsExtractor); + + + ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java new file mode 100644 index 000000000..de7709ace --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java @@ -0,0 +1,1537 @@ +/* + * Copyright 2013-2018 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 static org.apache.commons.lang.StringUtils.isBlank; +import static org.apache.commons.lang.StringUtils.isNotBlank; +import static org.elasticsearch.client.Requests.refreshRequest; +import static org.elasticsearch.index.VersionType.EXTERNAL; +import static org.elasticsearch.index.query.QueryBuilders.moreLikeThisQuery; +import static org.elasticsearch.index.query.QueryBuilders.wrapperQuery; +import static org.springframework.data.elasticsearch.core.MappingBuilder.buildMapping; +import static org.springframework.util.CollectionUtils.isEmpty; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; +import java.util.stream.Collectors; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.action.ActionFuture; +import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; +import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions; +import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.get.GetIndexRequest; +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder; +import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; +import org.elasticsearch.action.bulk.BulkItemResponse; +import org.elasticsearch.action.bulk.BulkRequest; +import org.elasticsearch.action.bulk.BulkRequestBuilder; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.delete.DeleteRequest; +import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.get.MultiGetRequest; +import org.elasticsearch.action.get.MultiGetRequestBuilder; +import org.elasticsearch.action.get.MultiGetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.index.IndexRequestBuilder; +import org.elasticsearch.action.search.ClearScrollRequest; +import org.elasticsearch.action.search.ClearScrollResponse; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchRequestBuilder; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.SearchScrollRequest; +import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.action.update.UpdateRequestBuilder; +import org.elasticsearch.action.update.UpdateResponse; +import org.elasticsearch.client.Requests; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.collect.MapBuilder; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.DeprecationHandler; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.query.MoreLikeThisQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; +import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.FieldSortBuilder; +import org.elasticsearch.search.sort.SortBuilder; +import org.elasticsearch.search.sort.SortBuilders; +import org.elasticsearch.search.sort.SortOrder; +import org.elasticsearch.search.suggest.SuggestBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.io.ClassPathResource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +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.annotations.Mapping; +import org.springframework.data.elasticsearch.annotations.Setting; +import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; +import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; +import org.springframework.data.elasticsearch.core.client.support.AliasData; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; +import org.springframework.data.elasticsearch.core.facet.FacetRequest; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; +import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.util.CloseableIterator; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * ElasticsearchRestTemplate + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + * @author Kevin Leturc + * @author Mason Chan + * @author Young Gu + * @author Oliver Gierke + * @author Mark Janssen + * @author Chris White + * @author Mark Paluch + * @author Ilkang Na + * @author Alen Turkovic + * @author Sascha Woo + * @author Ted Liang + * @author Don Wellington + */ +public class ElasticsearchRestTemplate + implements ElasticsearchOperations, EsClient, ApplicationContextAware { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchRestTemplate.class); + private RestHighLevelClient client; + private ElasticsearchConverter elasticsearchConverter; + private ResultsMapper resultsMapper; + private String searchTimeout; + + public ElasticsearchRestTemplate(RestHighLevelClient client) { + this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext())); + } + + public ElasticsearchRestTemplate(RestHighLevelClient client, EntityMapper entityMapper) { + this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), entityMapper); + } + + public ElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter, + EntityMapper entityMapper) { + this(client, elasticsearchConverter, + new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper)); + } + + public ElasticsearchRestTemplate(RestHighLevelClient client, ResultsMapper resultsMapper) { + this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), resultsMapper); + } + + public ElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) { + this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext())); + } + + public ElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter, + ResultsMapper resultsMapper) { + + Assert.notNull(client, "Client must not be null!"); + Assert.notNull(elasticsearchConverter, "ElasticsearchConverter must not be null!"); + Assert.notNull(resultsMapper, "ResultsMapper must not be null!"); + + this.client = client; + this.elasticsearchConverter = elasticsearchConverter; + this.resultsMapper = resultsMapper; + } + + @Override + public RestHighLevelClient getClient() { + return client; + } + + public void setSearchTimeout(String searchTimeout) { + this.searchTimeout = searchTimeout; + } + + @Override + public boolean createIndex(Class clazz) { + return createIndexIfNotCreated(clazz); + } + + @Override + public boolean createIndex(String indexName) { + Assert.notNull(indexName, "No index defined for Query"); + try { + return client.indices().create(Requests.createIndexRequest(indexName)).isAcknowledged(); + } catch (Exception e) { + throw new ElasticsearchException("Failed to create index " + indexName, e); + } + } + + @Override + public boolean putMapping(Class clazz) { + if (clazz.isAnnotationPresent(Mapping.class)) { + String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath(); + if (isNotBlank(mappingPath)) { + String mappings = readFileFromClasspath(mappingPath); + if (isNotBlank(mappings)) { + return putMapping(clazz, mappings); + } + } else { + logger.info("mappingPath in @Mapping has to be defined. Building mappings using @Field"); + } + } + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz); + XContentBuilder xContentBuilder = null; + try { + + ElasticsearchPersistentProperty property = persistentEntity.getRequiredIdProperty(); + + xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), property.getFieldName(), + persistentEntity.getParentType()); + } catch (Exception e) { + throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e); + } + return putMapping(clazz, xContentBuilder); + } + + @Override + public boolean putMapping(Class clazz, Object mapping) { + return putMapping(getPersistentEntityFor(clazz).getIndexName(), getPersistentEntityFor(clazz).getIndexType(), + mapping); + } + + @Override + public boolean putMapping(String indexName, String type, Object mapping) { + Assert.notNull(indexName, "No index defined for putMapping()"); + Assert.notNull(type, "No type defined for putMapping()"); + PutMappingRequest request = new PutMappingRequest(indexName).type(type); + if (mapping instanceof String) { + request.source(String.valueOf(mapping), XContentType.JSON); + } else if (mapping instanceof Map) { + request.source((Map) mapping); + } else if (mapping instanceof XContentBuilder) { + request.source((XContentBuilder) mapping); + } + try { + return client.indices().putMapping(request).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("Failed to put mapping for " + indexName, e); + } + } + + @Override + public Map getMapping(String indexName, String type) { + Assert.notNull(indexName, "No index defined for putMapping()"); + Assert.notNull(type, "No type defined for putMapping()"); + Map mappings = null; + RestClient restClient = client.getLowLevelClient(); + try { + Response response = restClient.performRequest("GET", "/" + indexName + "/_mapping/" + type); + mappings = convertMappingResponse(EntityUtils.toString(response.getEntity())); + } catch (Exception e) { + throw new ElasticsearchException( + "Error while getting mapping for indexName : " + indexName + " type : " + type + " ", e); + } + return mappings; + } + + @Override + public Map getMapping(Class clazz) { + return getMapping(getPersistentEntityFor(clazz).getIndexName(), getPersistentEntityFor(clazz).getIndexType()); + } + + private Map convertMappingResponse(String mappingResponse) { + ObjectMapper mapper = new ObjectMapper(); + + try { + Map result = null; + JsonNode node = mapper.readTree(mappingResponse); + + node = node.findValue("settings"); + result = mapper.readValue(mapper.writeValueAsString(node), HashMap.class); + + return result; + } catch (IOException e) { + throw new ElasticsearchException("Could not map alias response : " + mappingResponse, e); + } + + } + + @Override + public ElasticsearchConverter getElasticsearchConverter() { + return elasticsearchConverter; + } + + @Override + public T queryForObject(GetQuery query, Class clazz) { + return queryForObject(query, clazz, resultsMapper); + } + + @Override + public T queryForObject(GetQuery query, Class clazz, GetResultMapper mapper) { + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz); + GetRequest request = new GetRequest(persistentEntity.getIndexName(), persistentEntity.getIndexType(), + query.getId()); + GetResponse response; + try { + response = client.get(request); + T entity = mapper.mapResult(response, clazz); + return entity; + } catch (IOException e) { + throw new ElasticsearchException("Error while getting for request: " + request.toString(), e); + } + } + + @Override + public T queryForObject(CriteriaQuery query, Class clazz) { + Page 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 queryForObject(StringQuery query, Class clazz) { + Page 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 AggregatedPage queryForPage(SearchQuery query, Class clazz) { + return queryForPage(query, clazz, resultsMapper); + } + + @Override + public AggregatedPage queryForPage(SearchQuery query, Class clazz, SearchResultMapper mapper) { + SearchResponse response = doSearch(prepareSearch(query, clazz), query); + return mapper.mapResults(response, clazz, query.getPageable()); + } + + @Override + public T query(SearchQuery query, ResultsExtractor resultsExtractor) { + SearchResponse response = doSearch(prepareSearch(query, Optional.ofNullable(query.getQuery())), query); + return resultsExtractor.extract(response); + } + + @Override + public List queryForList(CriteriaQuery query, Class clazz) { + return queryForPage(query, clazz).getContent(); + } + + @Override + public List queryForList(StringQuery query, Class clazz) { + return queryForPage(query, clazz).getContent(); + } + + @Override + public List queryForList(SearchQuery query, Class clazz) { + return queryForPage(query, clazz).getContent(); + } + + @Override + public List queryForIds(SearchQuery query) { + SearchRequest request = prepareSearch(query, Optional.ofNullable(query.getQuery())); + request.source().query(query.getQuery()); + if (query.getFilter() != null) { + request.source().postFilter(query.getFilter()); + } + SearchResponse response; + try { + response = client.search(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + request.toString(), e); + } + return extractIds(response); + } + + @Override + public Page queryForPage(CriteriaQuery criteriaQuery, Class clazz) { + QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria()); + QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor() + .createFilterFromCriteria(criteriaQuery.getCriteria()); + SearchRequest request = prepareSearch(criteriaQuery, clazz); + + if (elasticsearchQuery != null) { + request.source().query(elasticsearchQuery); + } else { + request.source().query(QueryBuilders.matchAllQuery()); + } + + if (criteriaQuery.getMinScore() > 0) { + request.source().minScore(criteriaQuery.getMinScore()); + } + + if (elasticsearchFilter != null) + request.source().postFilter(elasticsearchFilter); + if (logger.isDebugEnabled()) { + logger.debug("doSearch query:\n" + request.toString()); + } + + SearchResponse response; + try { + response = client.search(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + request.toString(), e); + } + return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable()); + } + + @Override + public Page queryForPage(StringQuery query, Class clazz) { + return queryForPage(query, clazz, resultsMapper); + } + + @Override + public Page queryForPage(StringQuery query, Class clazz, SearchResultMapper mapper) { + SearchRequest request = prepareSearch(query, clazz); + request.source().query((wrapperQuery(query.getSource()))); + SearchResponse response; + try { + response = client.search(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + request.toString(), e); + } + return mapper.mapResults(response, clazz, query.getPageable()); + } + + @Override + public CloseableIterator stream(CriteriaQuery query, Class clazz) { + final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); + return doStream(scrollTimeInMillis, (ScrolledPage) startScroll(scrollTimeInMillis, query, clazz), clazz, + resultsMapper); + } + + @Override + public CloseableIterator stream(SearchQuery query, Class clazz) { + return stream(query, clazz, resultsMapper); + } + + @Override + public CloseableIterator stream(SearchQuery query, final Class clazz, final SearchResultMapper mapper) { + final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); + return doStream(scrollTimeInMillis, (ScrolledPage) startScroll(scrollTimeInMillis, query, clazz, mapper), clazz, + mapper); + } + + private CloseableIterator doStream(final long scrollTimeInMillis, final ScrolledPage page, + final Class clazz, final SearchResultMapper mapper) { + return new CloseableIterator() { + + /** As we couldn't retrieve single result with scroll, store current hits. */ + private volatile Iterator currentHits = page.iterator(); + + /** The scroll id. */ + private volatile String scrollId = page.getScrollId(); + + /** If stream is finished (ie: cluster returns no results. */ + private volatile boolean finished = !currentHits.hasNext(); + + @Override + public void close() { + try { + // Clear scroll on cluster only in case of error (cause elasticsearch auto clear scroll when it's done) + if (!finished && scrollId != null && currentHits != null && currentHits.hasNext()) { + clearScroll(scrollId); + } + } finally { + currentHits = null; + scrollId = null; + } + } + + @Override + public boolean hasNext() { + // Test if stream is finished + if (finished) { + return false; + } + // Test if it remains hits + if (currentHits == null || !currentHits.hasNext()) { + // Do a new request + final ScrolledPage scroll = (ScrolledPage) continueScroll(scrollId, scrollTimeInMillis, clazz, mapper); + // Save hits and scroll id + currentHits = scroll.iterator(); + finished = !currentHits.hasNext(); + scrollId = scroll.getScrollId(); + } + return currentHits.hasNext(); + } + + @Override + public T next() { + if (hasNext()) { + return currentHits.next(); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove"); + } + }; + } + + @Override + public long count(CriteriaQuery criteriaQuery, Class clazz) { + QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria()); + QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor() + .createFilterFromCriteria(criteriaQuery.getCriteria()); + + if (elasticsearchFilter == null) { + return doCount(prepareCount(criteriaQuery, clazz), elasticsearchQuery); + } else { + // filter could not be set into CountRequestBuilder, convert request into search request + return doCount(prepareSearch(criteriaQuery, clazz), elasticsearchQuery, elasticsearchFilter); + } + } + + @Override + public long count(SearchQuery searchQuery, Class clazz) { + QueryBuilder elasticsearchQuery = searchQuery.getQuery(); + QueryBuilder elasticsearchFilter = searchQuery.getFilter(); + + if (elasticsearchFilter == null) { + return doCount(prepareCount(searchQuery, clazz), elasticsearchQuery); + } else { + // filter could not be set into CountRequestBuilder, convert request into search request + return doCount(prepareSearch(searchQuery, clazz), elasticsearchQuery, elasticsearchFilter); + } + } + + @Override + public long count(CriteriaQuery query) { + return count(query, null); + } + + @Override + public long count(SearchQuery query) { + return count(query, null); + } + + private long doCount(SearchRequest countRequest, QueryBuilder elasticsearchQuery) { + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); + if (elasticsearchQuery != null) { + sourceBuilder.query(elasticsearchQuery); + } + countRequest.source(sourceBuilder); + + try { + return client.search(countRequest).getHits().getTotalHits(); + } catch (IOException e) { + throw new ElasticsearchException("Error while searching for request: " + countRequest.toString(), e); + } + } + + private long doCount(SearchRequest searchRequest, QueryBuilder elasticsearchQuery, QueryBuilder elasticsearchFilter) { + if (elasticsearchQuery != null) { + searchRequest.source().query(elasticsearchQuery); + } else { + searchRequest.source().query(QueryBuilders.matchAllQuery()); + } + if (elasticsearchFilter != null) { + searchRequest.source().postFilter(elasticsearchFilter); + } + SearchResponse response; + try { + response = client.search(searchRequest); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); + } + return response.getHits().getTotalHits(); + } + + private SearchRequest prepareCount(Query query, Class clazz) { + String indexName[] = !isEmpty(query.getIndices()) + ? query.getIndices().toArray(new String[query.getIndices().size()]) + : retrieveIndexNameFromPersistentEntity(clazz); + String types[] = !isEmpty(query.getTypes()) ? query.getTypes().toArray(new String[query.getTypes().size()]) + : retrieveTypeFromPersistentEntity(clazz); + + Assert.notNull(indexName, "No index defined for Query"); + + SearchRequest countRequestBuilder = new SearchRequest(indexName); + + if (types != null) { + countRequestBuilder.types(types); + } + return countRequestBuilder; + } + + @Override + public LinkedList multiGet(SearchQuery searchQuery, Class clazz) { + return resultsMapper.mapResults(getMultiResponse(searchQuery, clazz), clazz); + } + + private MultiGetResponse getMultiResponse(Query searchQuery, Class clazz) { + + String indexName = !isEmpty(searchQuery.getIndices()) ? searchQuery.getIndices().get(0) + : getPersistentEntityFor(clazz).getIndexName(); + String type = !isEmpty(searchQuery.getTypes()) ? searchQuery.getTypes().get(0) + : getPersistentEntityFor(clazz).getIndexType(); + + Assert.notNull(indexName, "No index defined for Query"); + Assert.notNull(type, "No type define for Query"); + Assert.notEmpty(searchQuery.getIds(), "No Id define for Query"); + + MultiGetRequest request = new MultiGetRequest(); + + if (searchQuery.getFields() != null && !searchQuery.getFields().isEmpty()) { + searchQuery.addSourceFilter(new FetchSourceFilter(toArray(searchQuery.getFields()), null)); + } + + for (String id : searchQuery.getIds()) { + + MultiGetRequest.Item item = new MultiGetRequest.Item(indexName, type, id); + + if (searchQuery.getRoute() != null) { + item = item.routing(searchQuery.getRoute()); + } + + request.add(item); + } + try { + return client.multiGet(request); + } catch (IOException e) { + throw new ElasticsearchException("Error while multiget for request: " + request.toString(), e); + } + } + + @Override + public LinkedList multiGet(SearchQuery searchQuery, Class clazz, MultiGetResultMapper getResultMapper) { + return getResultMapper.mapResults(getMultiResponse(searchQuery, clazz), clazz); + } + + @Override + public String index(IndexQuery query) { + String documentId; + IndexRequest request = prepareIndex(query); + try { + documentId = client.index(request).getId(); + } catch (IOException e) { + throw new ElasticsearchException("Error while index for request: " + request.toString(), e); + } + // We should call this because we are not going through a mapper. + if (query.getObject() != null) { + setPersistentEntityId(query.getObject(), documentId); + } + return documentId; + } + + @Override + public UpdateResponse update(UpdateQuery query) { + UpdateRequest request = prepareUpdate(query); + try { + return client.update(request); + } catch (IOException e) { + throw new ElasticsearchException("Error while update for request: " + request.toString(), e); + } + } + + private UpdateRequest prepareUpdate(UpdateQuery query) { + String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() + : getPersistentEntityFor(query.getClazz()).getIndexName(); + String type = isNotBlank(query.getType()) ? query.getType() + : getPersistentEntityFor(query.getClazz()).getIndexType(); + Assert.notNull(indexName, "No index defined for Query"); + Assert.notNull(type, "No type define for Query"); + Assert.notNull(query.getId(), "No Id define for Query"); + Assert.notNull(query.getUpdateRequest(), "No IndexRequest define for Query"); + UpdateRequest updateRequest = new UpdateRequest(indexName, type, query.getId()); + updateRequest.routing(query.getUpdateRequest().routing()); + + if (query.getUpdateRequest().script() == null) { + // doc + if (query.DoUpsert()) { + updateRequest.docAsUpsert(true).doc(query.getUpdateRequest().doc()); + } else { + updateRequest.doc(query.getUpdateRequest().doc()); + } + } else { + // or script + updateRequest.script(query.getUpdateRequest().script()); + } + + return updateRequest; + } + + @Override + public void bulkIndex(List queries) { + BulkRequest bulkRequest = new BulkRequest(); + for (IndexQuery query : queries) { + bulkRequest.add(prepareIndex(query)); + } + try { + checkForBulkUpdateFailure(client.bulk(bulkRequest)); + } catch (IOException e) { + throw new ElasticsearchException("Error while bulk for request: " + bulkRequest.toString(), e); + } + } + + @Override + public void bulkUpdate(List queries) { + BulkRequest bulkRequest = new BulkRequest(); + for (UpdateQuery query : queries) { + bulkRequest.add(prepareUpdate(query)); + } + try { + checkForBulkUpdateFailure(client.bulk(bulkRequest)); + } catch (IOException e) { + throw new ElasticsearchException("Error while bulk for request: " + bulkRequest.toString(), e); + } + } + + private void checkForBulkUpdateFailure(BulkResponse bulkResponse) { + if (bulkResponse.hasFailures()) { + Map failedDocuments = new HashMap<>(); + 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 boolean indexExists(Class clazz) { + return indexExists(getPersistentEntityFor(clazz).getIndexName()); + } + + @Override + public boolean indexExists(String indexName) { + GetIndexRequest request = new GetIndexRequest(); + request.indices(indexName); + try { + return client.indices().exists(request); + } catch (IOException e) { + throw new ElasticsearchException("Error while for indexExists request: " + request.toString(), e); + } + } + + @Override + public boolean typeExists(String index, String type) { + RestClient restClient = client.getLowLevelClient(); + try { + Response response = restClient.performRequest("HEAD", index + "/_mapping/" + type); + return (response.getStatusLine().getStatusCode() == 200); + } catch (Exception e) { + throw new ElasticsearchException("Error while checking type exists for index: " + index + " type : " + type + " ", + e); + } + } + + @Override + public boolean deleteIndex(Class clazz) { + return deleteIndex(getPersistentEntityFor(clazz).getIndexName()); + } + + @Override + public boolean deleteIndex(String indexName) { + Assert.notNull(indexName, "No index defined for delete operation"); + if (indexExists(indexName)) { + DeleteIndexRequest request = new DeleteIndexRequest(indexName); + try { + return client.indices().delete(request).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("Error while deleting index request: " + request.toString(), e); + } + } + return false; + } + + @Override + public String delete(String indexName, String type, String id) { + DeleteRequest request = new DeleteRequest(indexName, type, id); + try { + return client.delete(request).getId(); + } catch (IOException e) { + throw new ElasticsearchException("Error while deleting item request: " + request.toString(), e); + } + } + + @Override + public String delete(Class clazz, String id) { + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz); + return delete(persistentEntity.getIndexName(), persistentEntity.getIndexType(), id); + } + + @Override + public void delete(DeleteQuery deleteQuery, Class clazz) { + + String indexName = isNotBlank(deleteQuery.getIndex()) ? deleteQuery.getIndex() + : getPersistentEntityFor(clazz).getIndexName(); + String typeName = isNotBlank(deleteQuery.getType()) ? deleteQuery.getType() + : getPersistentEntityFor(clazz).getIndexType(); + Integer pageSize = deleteQuery.getPageSize() != null ? deleteQuery.getPageSize() : 1000; + Long scrollTimeInMillis = deleteQuery.getScrollTimeInMillis() != null ? deleteQuery.getScrollTimeInMillis() + : 10000l; + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(deleteQuery.getQuery()).withIndices(indexName) + .withTypes(typeName).withPageable(PageRequest.of(0, pageSize)).build(); + + SearchResultMapper onlyIdResultMapper = new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List result = new ArrayList(); + for (SearchHit searchHit : response.getHits().getHits()) { + String id = searchHit.getId(); + result.add(id); + } + if (result.size() > 0) { + return new AggregatedPageImpl((List) result, response.getScrollId()); + } + return new AggregatedPageImpl(Collections.EMPTY_LIST, response.getScrollId()); + } + }; + + Page scrolledResult = startScroll(scrollTimeInMillis, searchQuery, String.class, onlyIdResultMapper); + BulkRequest request = new BulkRequest(); + List ids = new ArrayList(); + + do { + ids.addAll(scrolledResult.getContent()); + scrolledResult = continueScroll(((ScrolledPage) scrolledResult).getScrollId(), scrollTimeInMillis, + String.class, onlyIdResultMapper); + } while (scrolledResult.getContent().size() != 0); + + for (String id : ids) { + request.add(new DeleteRequest(indexName, typeName, id)); + } + + if (request.numberOfActions() > 0) { + BulkResponse response; + try { + response = client.bulk(request); + checkForBulkUpdateFailure(response); + } catch (IOException e) { + throw new ElasticsearchException("Error while deleting bulk: " + request.toString(), e); + } + } + + clearScroll(((ScrolledPage) scrolledResult).getScrollId()); + } + + @Override + public void delete(DeleteQuery deleteQuery) { + Assert.notNull(deleteQuery.getIndex(), "No index defined for Query"); + Assert.notNull(deleteQuery.getType(), "No type define for Query"); + delete(deleteQuery, null); + } + + @Override + public void delete(CriteriaQuery criteriaQuery, Class clazz) { + QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria()); + Assert.notNull(elasticsearchQuery, "Query can not be null."); + DeleteQuery deleteQuery = new DeleteQuery(); + deleteQuery.setQuery(elasticsearchQuery); + delete(deleteQuery, clazz); + } + + private SearchRequest prepareScroll(Query query, long scrollTimeInMillis, Class clazz) { + setPersistentEntityIndexAndType(query, clazz); + return prepareScroll(query, scrollTimeInMillis); + } + + private SearchRequest prepareScroll(Query query, long scrollTimeInMillis) { + SearchRequest request = new SearchRequest(toArray(query.getIndices())); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + request.types(toArray(query.getTypes())); + request.scroll(TimeValue.timeValueMillis(scrollTimeInMillis)); + + if (query.getPageable().isPaged()) { + searchSourceBuilder.size(query.getPageable().getPageSize()); + } + + if (!isEmpty(query.getFields())) { + searchSourceBuilder.fetchSource(toArray(query.getFields()), null); + } + request.source(searchSourceBuilder); + return request; + } + + private SearchResponse doScroll(SearchRequest request, CriteriaQuery criteriaQuery) { + Assert.notNull(criteriaQuery.getIndices(), "No index defined for Query"); + Assert.notNull(criteriaQuery.getTypes(), "No type define for Query"); + Assert.notNull(criteriaQuery.getPageable(), "Query.pageable is required for scan & scroll"); + + QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria()); + QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor() + .createFilterFromCriteria(criteriaQuery.getCriteria()); + + if (elasticsearchQuery != null) { + request.source().query(elasticsearchQuery); + } else { + request.source().query(QueryBuilders.matchAllQuery()); + } + + if (elasticsearchFilter != null) { + request.source().postFilter(elasticsearchFilter); + } + request.source().version(true); + + try { + return client.search(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e); + } + } + + private SearchResponse doScroll(SearchRequest request, SearchQuery searchQuery) { + 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"); + + if (searchQuery.getFilter() != null) { + request.source().postFilter(searchQuery.getFilter()); + } + request.source().version(true); + + try { + return client.search(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e); + } + } + + public Page startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class clazz) { + SearchResponse response = doScroll(prepareScroll(searchQuery, scrollTimeInMillis, clazz), searchQuery); + return resultsMapper.mapResults(response, clazz, null); + } + + public Page startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class clazz) { + SearchResponse response = doScroll(prepareScroll(criteriaQuery, scrollTimeInMillis, clazz), criteriaQuery); + return resultsMapper.mapResults(response, clazz, null); + } + + public Page startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class clazz, + SearchResultMapper mapper) { + SearchResponse response = doScroll(prepareScroll(searchQuery, scrollTimeInMillis, clazz), searchQuery); + return mapper.mapResults(response, clazz, null); + } + + public Page startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class clazz, + SearchResultMapper mapper) { + SearchResponse response = doScroll(prepareScroll(criteriaQuery, scrollTimeInMillis, clazz), criteriaQuery); + return mapper.mapResults(response, clazz, null); + } + + public Page continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz) { + SearchScrollRequest request = new SearchScrollRequest(scrollId); + request.scroll(TimeValue.timeValueMillis(scrollTimeInMillis)); + SearchResponse response; + try { + response = client.searchScroll(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e); + } + return resultsMapper.mapResults(response, clazz, Pageable.unpaged()); + } + + public Page continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz, + SearchResultMapper mapper) { + SearchScrollRequest request = new SearchScrollRequest(scrollId); + request.scroll(TimeValue.timeValueMillis(scrollTimeInMillis)); + SearchResponse response; + try { + response = client.searchScroll(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e); + } + return mapper.mapResults(response, clazz, Pageable.unpaged()); + } + + @Override + public void clearScroll(String scrollId) { + ClearScrollRequest request = new ClearScrollRequest(); + request.addScrollId(scrollId); + try { + // TODO: Something useful with the response. + ClearScrollResponse response = client.clearScroll(request); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e); + } + } + + @Override + public Page moreLikeThis(MoreLikeThisQuery query, Class clazz) { + + 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"); + + MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = moreLikeThisQuery( + toArray(new MoreLikeThisQueryBuilder.Item(indexName, type, query.getId()))); + + if (query.getMinTermFreq() != null) { + moreLikeThisQueryBuilder.minTermFreq(query.getMinTermFreq()); + } + if (query.getMaxQueryTerms() != null) { + moreLikeThisQueryBuilder.maxQueryTerms(query.getMaxQueryTerms()); + } + if (!isEmpty(query.getStopWords())) { + moreLikeThisQueryBuilder.stopWords(toArray(query.getStopWords())); + } + if (query.getMinDocFreq() != null) { + moreLikeThisQueryBuilder.minDocFreq(query.getMinDocFreq()); + } + if (query.getMaxDocFreq() != null) { + moreLikeThisQueryBuilder.maxDocFreq(query.getMaxDocFreq()); + } + if (query.getMinWordLen() != null) { + moreLikeThisQueryBuilder.minWordLength(query.getMinWordLen()); + } + if (query.getMaxWordLen() != null) { + moreLikeThisQueryBuilder.maxWordLength(query.getMaxWordLen()); + } + if (query.getBoostTerms() != null) { + moreLikeThisQueryBuilder.boostTerms(query.getBoostTerms()); + } + + return queryForPage(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).build(), clazz); + } + + private SearchResponse doSearch(SearchRequest searchRequest, SearchQuery searchQuery) { + if (searchQuery.getFilter() != null) { + searchRequest.source().postFilter(searchQuery.getFilter()); + } + + if (!isEmpty(searchQuery.getElasticsearchSorts())) { + for (SortBuilder sort : searchQuery.getElasticsearchSorts()) { + searchRequest.source().sort(sort); + } + } + + if (!searchQuery.getScriptFields().isEmpty()) { + // _source should be return all the time + // searchRequest.addStoredField("_source"); + for (ScriptField scriptedField : searchQuery.getScriptFields()) { + searchRequest.source().scriptField(scriptedField.fieldName(), scriptedField.script()); + } + } + + if (searchQuery.getHighlightFields() != null) { + HighlightBuilder highlightBuilder = new HighlightBuilder(); + for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) { + highlightBuilder.field(highlightField); + } + searchRequest.source().highlighter(highlightBuilder); + } + + if (!isEmpty(searchQuery.getIndicesBoost())) { + for (IndexBoost indexBoost : searchQuery.getIndicesBoost()) { + searchRequest.source().indexBoost(indexBoost.getIndexName(), indexBoost.getBoost()); + } + } + + if (!isEmpty(searchQuery.getAggregations())) { + for (AbstractAggregationBuilder aggregationBuilder : searchQuery.getAggregations()) { + searchRequest.source().aggregation(aggregationBuilder); + } + } + + if (!isEmpty(searchQuery.getFacets())) { + for (FacetRequest aggregatedFacet : searchQuery.getFacets()) { + searchRequest.source().aggregation(aggregatedFacet.getFacet()); + } + } + + try { + return client.search(searchRequest); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request with scroll: " + searchRequest.toString(), e); + } + } + + private SearchResponse getSearchResponse(ActionFuture response) { + return searchTimeout == null ? response.actionGet() : response.actionGet(searchTimeout); + } + + private boolean createIndexIfNotCreated(Class clazz) { + return indexExists(getPersistentEntityFor(clazz).getIndexName()) || createIndexWithSettings(clazz); + } + + private boolean createIndexWithSettings(Class clazz) { + if (clazz.isAnnotationPresent(Setting.class)) { + String settingPath = clazz.getAnnotation(Setting.class).settingPath(); + if (isNotBlank(settingPath)) { + String settings = readFileFromClasspath(settingPath); + if (isNotBlank(settings)) { + return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings); + } + } else { + logger.info("settingPath in @Setting has to be defined. Using default instead."); + } + } + return createIndex(getPersistentEntityFor(clazz).getIndexName(), getDefaultSettings(getPersistentEntityFor(clazz))); + } + + @Override + public boolean createIndex(String indexName, Object settings) { + CreateIndexRequest request = new CreateIndexRequest(indexName); + if (settings instanceof String) { + request.settings(String.valueOf(settings), Requests.INDEX_CONTENT_TYPE); + } else if (settings instanceof Map) { + request.settings((Map) settings); + } else if (settings instanceof XContentBuilder) { + request.settings((XContentBuilder) settings); + } + try { + return client.indices().create(request).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("Error for creating index: " + request.toString(), e); + } + } + + @Override + public boolean createIndex(Class clazz, Object settings) { + return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings); + } + + private Map getDefaultSettings(ElasticsearchPersistentEntity persistentEntity) { + + if (persistentEntity.isUseServerConfiguration()) + return new HashMap(); + + return new MapBuilder().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(); + } + + @Override + public Map getSetting(Class clazz) { + return getSetting(getPersistentEntityFor(clazz).getIndexName()); + } + + @Override // TODO change interface to return Settings. + public Map getSetting(String indexName) { + Assert.notNull(indexName, "No index defined for getSettings"); + ObjectMapper objMapper = new ObjectMapper(); + Map settings = null; + RestClient restClient = client.getLowLevelClient(); + try { + Response response = restClient.performRequest("GET", "/" + indexName + "/_settings"); + settings = convertSettingResponse(EntityUtils.toString(response.getEntity()), indexName); + + } catch (Exception e) { + throw new ElasticsearchException("Error while getting settings for indexName : " + indexName, e); + } + return settings; + } + + private Map convertSettingResponse(String settingResponse, String indexName) { + ObjectMapper mapper = new ObjectMapper(); + + try { + Settings settings = Settings.fromXContent(XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, + DeprecationHandler.THROW_UNSUPPORTED_OPERATION, settingResponse)); + String prefix = indexName + ".settings."; + // Backwards compatibility. TODO Change to return Settings object. + Map result = new HashMap(); + Set keySet = settings.keySet(); + for (String key : keySet) { + result.put(StringUtils.substringAfter(key, prefix), settings.get(key)); + } + return result; + } catch (IOException e) { + throw new ElasticsearchException("Could not map alias response : " + settingResponse, e); + } + + } + + private SearchRequest prepareSearch(Query query, Class clazz) { + setPersistentEntityIndexAndType(query, clazz); + return prepareSearch(query, Optional.empty()); + } + + private SearchRequest prepareSearch(SearchQuery query, Class clazz) { + setPersistentEntityIndexAndType(query, clazz); + return prepareSearch(query, Optional.ofNullable(query.getQuery())); + } + + private SearchRequest prepareSearch(Query query, Optional builder) { + Assert.notNull(query.getIndices(), "No index defined for Query"); + Assert.notNull(query.getTypes(), "No type defined for Query"); + + int startRecord = 0; + SearchRequest request = new SearchRequest(toArray(query.getIndices())); + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); + request.types(toArray(query.getTypes())); + sourceBuilder.version(true); + sourceBuilder.trackScores(query.getTrackScores()); + + if (builder.isPresent()) { + sourceBuilder.query(builder.get()); + } + + if (query.getSourceFilter() != null) { + SourceFilter sourceFilter = query.getSourceFilter(); + sourceBuilder.fetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes()); + } + + if (query.getPageable().isPaged()) { + startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize(); + sourceBuilder.size(query.getPageable().getPageSize()); + } + sourceBuilder.from(startRecord); + + if (!query.getFields().isEmpty()) { + sourceBuilder.fetchSource(toArray(query.getFields()), null); + } + + if (query.getIndicesOptions() != null) { + request.indicesOptions(query.getIndicesOptions()); + } + + if (query.getSort() != null) { + for (Sort.Order order : query.getSort()) { + FieldSortBuilder sort = SortBuilders.fieldSort(order.getProperty()) + .order(order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC); + if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) { + sort.missing("_first"); + } else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) { + sort.missing("_last"); + } + sourceBuilder.sort(sort); + } + } + + if (query.getMinScore() > 0) { + sourceBuilder.minScore(query.getMinScore()); + } + request.source(sourceBuilder); + return request; + } + + private IndexRequest 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(); + + IndexRequest indexRequest = null; + + if (query.getObject() != null) { + String id = isBlank(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId(); + // If we have a query id and a document id, do not ask ES to generate one. + if (id != null) { + indexRequest = new IndexRequest(indexName, type, id); + } else { + indexRequest = new IndexRequest(indexName, type); + } + indexRequest.source(resultsMapper.getEntityMapper().mapToString(query.getObject()), + Requests.INDEX_CONTENT_TYPE); + } else if (query.getSource() != null) { + indexRequest = new IndexRequest(indexName, type, query.getId()).source(query.getSource(), + Requests.INDEX_CONTENT_TYPE); + } else { + throw new ElasticsearchException( + "object or source is null, failed to index the document [id: " + query.getId() + "]"); + } + if (query.getVersion() != null) { + indexRequest.version(query.getVersion()); + indexRequest.versionType(EXTERNAL); + } + + if (query.getParentId() != null) { + indexRequest.parent(query.getParentId()); + } + + return indexRequest; + } catch (IOException e) { + throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e); + } + } + + @Override + public void refresh(String indexName) { + Assert.notNull(indexName, "No index defined for refresh()"); + try { + // TODO: Do something with the response. + client.indices().refresh(refreshRequest(indexName)); + } catch (IOException e) { + throw new ElasticsearchException("failed to refresh index: " + indexName, e); + } + } + + @Override + public void refresh(Class clazz) { + refresh(getPersistentEntityFor(clazz).getIndexName()); + } + + @Override + public Boolean addAlias(AliasQuery query) { + Assert.notNull(query.getIndexName(), "No index defined for Alias"); + Assert.notNull(query.getAliasName(), "No alias defined"); + final IndicesAliasesRequest.AliasActions aliasAction = IndicesAliasesRequest.AliasActions.add() + .alias(query.getAliasName()).index(query.getIndexName()); + + if (query.getFilterBuilder() != null) { + aliasAction.filter(query.getFilterBuilder()); + } else if (query.getFilter() != null) { + aliasAction.filter(query.getFilter()); + } else if (isNotBlank(query.getRouting())) { + aliasAction.routing(query.getRouting()); + } else if (isNotBlank(query.getSearchRouting())) { + aliasAction.searchRouting(query.getSearchRouting()); + } else if (isNotBlank(query.getIndexRouting())) { + aliasAction.indexRouting(query.getIndexRouting()); + } + + IndicesAliasesRequest request = new IndicesAliasesRequest(); + request.addAliasAction(aliasAction); + try { + return client.indices().updateAliases(request).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("failed to update aliases with request: " + request, e); + } + } + + @Override + public Boolean removeAlias(AliasQuery query) { + Assert.notNull(query.getIndexName(), "No index defined for Alias"); + Assert.notNull(query.getAliasName(), "No alias defined"); + IndicesAliasesRequest request = new IndicesAliasesRequest(); + AliasActions aliasAction = new AliasActions(AliasActions.Type.REMOVE); + request.addAliasAction(aliasAction); + try { + return client.indices().updateAliases(request).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("failed to update aliases with request: " + request, e); + } + } + + @Override + public List queryForAlias(String indexName) { + List aliases = null; + RestClient restClient = client.getLowLevelClient(); + Response response; + String aliasResponse; + + try { + response = restClient.performRequest("GET", "/" + indexName + "/_alias/*"); + aliasResponse = EntityUtils.toString(response.getEntity()); + } catch (Exception e) { + throw new ElasticsearchException("Error while getting mapping for indexName : " + indexName, e); + } + + return convertAliasResponse(aliasResponse); + } + + /** + * It takes two steps to create a List from the elasticsearch http response because the aliases field + * is actually a Map by alias name, but the alias name is on the AliasMetadata. + * + * @param aliasResponse + * @return + */ + List convertAliasResponse(String aliasResponse) { + ObjectMapper mapper = new ObjectMapper(); + + try { + JsonNode node = mapper.readTree(aliasResponse); + + Iterator names = node.fieldNames(); + String name = names.next(); + node = node.findValue("aliases"); + + Map aliasData = mapper.readValue(mapper.writeValueAsString(node), + new TypeReference>() {}); + + Iterable> aliasIter = aliasData.entrySet(); + List aliasMetaDataList = new ArrayList(); + + for (Map.Entry aliasentry : aliasIter) { + AliasData data = aliasentry.getValue(); + aliasMetaDataList.add(AliasMetaData.newAliasMetaDataBuilder(aliasentry.getKey()).filter(data.getFilter()) + .routing(data.getRouting()).searchRouting(data.getSearch_routing()).indexRouting(data.getIndex_routing()) + .build()); + } + return aliasMetaDataList; + } catch (IOException e) { + throw new ElasticsearchException("Could not map alias response : " + aliasResponse, e); + } + } + + @Override + public 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().getRequiredPersistentEntity(clazz); + } + + private String getPersistentEntityId(Object entity) { + + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); + Object identifier = persistentEntity.getIdentifierAccessor(entity).getIdentifier(); + + if (identifier != null) { + return identifier.toString(); + } + + return null; + } + + private void setPersistentEntityId(Object entity, String id) { + + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); + ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty(); + + // Only deal with text because ES generated Ids are strings ! + + if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) { + persistentEntity.getPropertyAccessor(entity).setProperty(idProperty, id); + } + } + + private void setPersistentEntityIndexAndType(Query query, Class clazz) { + if (query.getIndices().isEmpty()) { + query.addIndices(retrieveIndexNameFromPersistentEntity(clazz)); + } + if (query.getTypes().isEmpty()) { + query.addTypes(retrieveTypeFromPersistentEntity(clazz)); + } + } + + private String[] retrieveIndexNameFromPersistentEntity(Class clazz) { + if (clazz != null) { + return new String[] { getPersistentEntityFor(clazz).getIndexName() }; + } + return null; + } + + private String[] retrieveTypeFromPersistentEntity(Class clazz) { + if (clazz != null) { + return new String[] { getPersistentEntityFor(clazz).getIndexType() }; + } + return null; + } + + private List extractIds(SearchResponse response) { + List ids = new ArrayList<>(); + for (SearchHit hit : response.getHits()) { + if (hit != null) { + ids.add(hit.getId()); + } + } + return ids; + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + if (elasticsearchConverter instanceof ApplicationContextAware) { + ((ApplicationContextAware) elasticsearchConverter).setApplicationContext(context); + } + } + + private static String[] toArray(List values) { + String[] valuesAsArray = new String[values.size()]; + return values.toArray(valuesAsArray); + } + + private static MoreLikeThisQueryBuilder.Item[] toArray(MoreLikeThisQueryBuilder.Item... values) { + return values; + } + + protected ResultsMapper getResultsMapper() { + return resultsMapper; + } + + public static String readFileFromClasspath(String url) { + StringBuilder stringBuilder = new StringBuilder(); + + BufferedReader bufferedReader = null; + + try { + ClassPathResource classPathResource = new ClassPathResource(url); + InputStreamReader inputStreamReader = new InputStreamReader(classPathResource.getInputStream()); + bufferedReader = new BufferedReader(inputStreamReader); + String line; + + String lineSeparator = System.getProperty("line.separator"); + while ((line = bufferedReader.readLine()) != null) { + stringBuilder.append(line).append(lineSeparator); + } + } catch (Exception e) { + logger.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage())); + return null; + } finally { + if (bufferedReader != null) + try { + bufferedReader.close(); + } catch (IOException e) { + logger.debug(String.format("Unable to close buffered reader.. %s", e.getMessage())); + } + } + + return stringBuilder.toString(); + } + + public SearchResponse suggest(SuggestBuilder suggestion, String... indices) { + SearchRequest searchRequest = new SearchRequest(indices); + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); + sourceBuilder.suggest(suggestion); + searchRequest.source(sourceBuilder); + + try { + return client.search(searchRequest); + } catch (IOException e) { + throw new ElasticsearchException("Could not execute search request : " + searchRequest.toString(), e); + } + } + + public SearchResponse suggest(SuggestBuilder suggestion, Class clazz) { + return suggest(suggestion, retrieveIndexNameFromPersistentEntity(clazz)); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index a3f302a42..3aa71f8ad 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -136,7 +136,7 @@ import org.springframework.util.StringUtils; * @author Ted Liang * @author Jean-Baptiste Nizet */ -public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware { +public class ElasticsearchTemplate implements ElasticsearchOperations, EsClient, ApplicationContextAware { private static final Logger QUERY_LOGGER = LoggerFactory.getLogger("org.springframework.data.elasticsearch.core.QUERY"); private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchTemplate.class); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/EsClient.java b/src/main/java/org/springframework/data/elasticsearch/core/EsClient.java new file mode 100644 index 000000000..d5d253df5 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/EsClient.java @@ -0,0 +1,26 @@ +/* + * Copyright 2018 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; + +/** + * EsClient interface. Specify what client an ElasticSearchTemplate will return from getClient(). + * + * @author Don Wellington + * @param + */ +public interface EsClient { + C getClient(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/client/support/AliasData.java b/src/main/java/org/springframework/data/elasticsearch/core/client/support/AliasData.java new file mode 100644 index 000000000..e16e00475 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/client/support/AliasData.java @@ -0,0 +1,34 @@ +/* + * Copyright 2018 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.client.support; + +import lombok.Data; +import lombok.Getter; + +import org.elasticsearch.cluster.metadata.AliasMetaData; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown=true) +@Data +public class AliasData { + String filter = null; + String routing = null; + String search_routing = null; + String index_routing= null; +} diff --git a/src/main/resources/META-INF/spring.schemas b/src/main/resources/META-INF/spring.schemas index f99a37bab..c371d7c4d 100644 --- a/src/main/resources/META-INF/spring.schemas +++ b/src/main/resources/META-INF/spring.schemas @@ -1,2 +1,4 @@ -http\://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd=org/springframework/data/elasticsearch/config/spring-elasticsearch-1.0.xsd -http\://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd=org/springframework/data/elasticsearch/config/spring-elasticsearch-1.0.xsd +http\://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd=org/springframework/data/elasticsearch/config/spring-elasticsearch-1.0.xsd +http\://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.1.xsd=org/springframework/data/elasticsearch/config/spring-elasticsearch-1.1.xsd +http\://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd=org/springframework/data/elasticsearch/config/spring-elasticsearch-1.0.xsd +http\://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd=org/springframework/data/elasticsearch/config/spring-elasticsearch-1.1.xsd diff --git a/src/main/resources/org/springframework/data/elasticsearch/config/spring-elasticsearch-1.1.xsd b/src/main/resources/org/springframework/data/elasticsearch/config/spring-elasticsearch-1.1.xsd new file mode 100644 index 000000000..e11018a66 --- /dev/null +++ b/src/main/resources/org/springframework/data/elasticsearch/config/spring-elasticsearch-1.1.xsd @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandlerTests.java b/src/test/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandlerTests.java index ac9e1834d..9c948d7fd 100644 --- a/src/test/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandlerTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandlerTests.java @@ -1,55 +1,63 @@ -/* - * 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.config; - -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.data.elasticsearch.client.TransportClientFactoryBean; -import org.springframework.data.elasticsearch.repositories.sample.SampleElasticsearchRepository; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("namespace.xml") -public class ElasticsearchNamespaceHandlerTests { - - @Autowired - private ApplicationContext context; - - @Test - public void shouldCreateTransportClient() { - assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue())); - assertThat(context.getBean(TransportClientFactoryBean.class), is(instanceOf(TransportClientFactoryBean.class))); - } - - @Test - public void shouldCreateRepository() { - assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue())); - assertThat(context.getBean(SampleElasticsearchRepository.class), - is(instanceOf(SampleElasticsearchRepository.class))); - } -} +/* + * Copyright 2013-2018 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.config; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.elasticsearch.client.RestClientFactoryBean; +import org.springframework.data.elasticsearch.client.TransportClientFactoryBean; +import org.springframework.data.elasticsearch.repositories.sample.SampleElasticsearchRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Don Wellington + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("namespace.xml") +public class ElasticsearchNamespaceHandlerTests { + + @Autowired + private ApplicationContext context; + + @Test + public void shouldCreateTransportClient() { + assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue())); + assertThat(context.getBean(TransportClientFactoryBean.class), is(instanceOf(TransportClientFactoryBean.class))); + } + + @Test + public void shouldCreateRepository() { + assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue())); + assertThat(context.getBean(SampleElasticsearchRepository.class), + is(instanceOf(SampleElasticsearchRepository.class))); + } + + @Test + public void shouldCreateRestClient() { + assertThat(context.getBean(RestClientFactoryBean.class), is(notNullValue())); + assertThat(context.getBean(RestClientFactoryBean.class), is(instanceOf(RestClientFactoryBean.class))); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java new file mode 100644 index 000000000..ff9ea216c --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java @@ -0,0 +1,2085 @@ +/* + * Copyright 2014-2018 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpHost; +import org.elasticsearch.action.get.MultiGetItemResponse; +import org.elasticsearch.action.get.MultiGetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.index.engine.DocumentMissingException; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptType; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.SearchHits; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; +import org.elasticsearch.search.sort.FieldSortBuilder; +import org.elasticsearch.search.sort.SortBuilders; +import org.elasticsearch.search.sort.SortOrder; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.common.xcontent.XContentType; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +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.aggregation.AggregatedPage; +import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; +import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.elasticsearch.entities.HetroEntity1; +import org.springframework.data.elasticsearch.entities.HetroEntity2; +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.data.elasticsearch.entities.SampleMappingEntity; +import org.springframework.data.elasticsearch.entities.UseServerConfigurationEntity; +import org.springframework.data.util.CloseableIterator; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.apache.commons.lang.RandomStringUtils.*; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.springframework.data.elasticsearch.utils.IndexBuilder.*; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Franck Marchand + * @author Abdul Mohammed + * @author Kevin Leturc + * @author Mason Chan + * @author Chris White + * @author Ilkang Na + * @author Alen Turkovic + * @author Sascha Woo + * @author Don Wellington + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:elasticsearch-rest-template-test.xml") +public class ElasticsearchRestTemplateTests { + + private static final String INDEX_NAME = "test-index-sample"; + private static final String INDEX_1_NAME = "test-index-1"; + private static final String INDEX_2_NAME = "test-index-2"; + private static final String TYPE_NAME = "test-type"; + + @Autowired + private ElasticsearchRestTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.putMapping(SampleEntity.class); + elasticsearchTemplate.deleteIndex(INDEX_1_NAME); + elasticsearchTemplate.deleteIndex(INDEX_2_NAME); + elasticsearchTemplate.deleteIndex(UseServerConfigurationEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + } + + /* + DATAES-106 + */ + @Test + public void shouldReturnCountForGivenCriteriaQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + // when + long count = elasticsearchTemplate.count(criteriaQuery, SampleEntity.class); + // then + assertThat(count, is(equalTo(1L))); + } + + @Test + public void shouldReturnCountForGivenSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + // when + long count = elasticsearchTemplate.count(searchQuery, SampleEntity.class); + // then + assertThat(count, is(equalTo(1L))); + } + + @Test + public void shouldReturnObjectForGivenId() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + // when + GetQuery getQuery = new GetQuery(); + getQuery.setId(documentId); + SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(getQuery, SampleEntity.class); + // then + assertNotNull("entity can't be null....", sampleEntity1); + assertEquals(sampleEntity, sampleEntity1); + } + + @Test + public void shouldReturnObjectsForGivenIdsUsingMultiGet() { + // given + List indexQueries = new ArrayList<>(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message") + .version(System.currentTimeMillis()).build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2)); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + // when + SearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2)).build(); + LinkedList sampleEntities = elasticsearchTemplate.multiGet(query, SampleEntity.class); + // then + assertThat(sampleEntities.size(), is(equalTo(2))); + assertEquals(sampleEntities.get(0), sampleEntity1); + assertEquals(sampleEntities.get(1), sampleEntity2); + } + + @Test + public void shouldReturnObjectsForGivenIdsUsingMultiGetWithFields() { + // given + List indexQueries = new ArrayList<>(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message").type("type1") + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message").type("type2") + .version(System.currentTimeMillis()).build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2)); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + // when + SearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2)) + .withFields("message", "type").build(); + LinkedList sampleEntities = elasticsearchTemplate.multiGet(query, SampleEntity.class, + new MultiGetResultMapper() { + @Override + public LinkedList mapResults(MultiGetResponse responses, Class clazz) { + LinkedList list = new LinkedList<>(); + for (MultiGetItemResponse response : responses.getResponses()) { + SampleEntity entity = new SampleEntity(); + entity.setId(response.getResponse().getId()); + entity.setMessage((String) response.getResponse().getSource().get("message")); + entity.setType((String) response.getResponse().getSource().get("type")); + list.add((T) entity); + } + return list; + } + }); + // then + assertThat(sampleEntities.size(), is(equalTo(2))); + } + + @Test + public void shouldReturnPageForGivenSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities, is(notNullValue())); + assertThat(sampleEntities.getTotalElements(), greaterThanOrEqualTo(1L)); + } + + // DATAES-422 - Add support for IndicesOptions in search queries + @Test + public void shouldPassIndicesOptionsForGivenSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery idxQuery = new IndexQueryBuilder().withIndexName(INDEX_1_NAME).withId(sampleEntity.getId()) + .withObject(sampleEntity).build(); + + elasticsearchTemplate.index(idxQuery); + elasticsearchTemplate.refresh(INDEX_1_NAME); + + // when + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withIndices(INDEX_1_NAME, INDEX_2_NAME).withIndicesOptions(IndicesOptions.lenientExpandOpen()).build(); + Page entities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(entities, is(notNullValue())); + assertThat(entities.getTotalElements(), greaterThanOrEqualTo(1L)); + } + + @Test + public void shouldDoBulkIndex() { + // given + List indexQueries = new ArrayList<>(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some message") + .version(System.currentTimeMillis()).build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2)); + + // when + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + assertThat(sampleEntities.getTotalElements(), is(equalTo(2L))); + } + + @Test + public void shouldDoBulkUpdate() { + // given + String documentId = randomNumeric(5); + String messageBeforeUpdate = "some test message"; + String messageAfterUpdate = "test message"; + + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(messageBeforeUpdate) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + IndexRequest indexRequest = new IndexRequest(); + indexRequest.source("message", messageAfterUpdate); + UpdateQuery updateQuery = new UpdateQueryBuilder().withId(documentId).withClass(SampleEntity.class) + .withIndexRequest(indexRequest).build(); + + List queries = new ArrayList<>(); + queries.add(updateQuery); + + // when + elasticsearchTemplate.bulkUpdate(queries); + // then + GetQuery getQuery = new GetQuery(); + getQuery.setId(documentId); + SampleEntity indexedEntity = elasticsearchTemplate.queryForObject(getQuery, SampleEntity.class); + assertThat(indexedEntity.getMessage(), is(messageAfterUpdate)); + } + + @Test + public void shouldDeleteDocumentForGivenId() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + // when + elasticsearchTemplate.delete(INDEX_NAME, TYPE_NAME, documentId); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + } + + @Test + public void shouldDeleteEntityForGivenId() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + // when + elasticsearchTemplate.delete(SampleEntity.class, documentId); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + } + + @Test + public void shouldDeleteDocumentForGivenQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + // when + DeleteQuery deleteQuery = new DeleteQuery(); + deleteQuery.setQuery(termQuery("id", documentId)); + elasticsearchTemplate.delete(deleteQuery, SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + } + + @Test + public void shouldFilterSearchResultsForGivenFilter() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withFilter(boolQuery().filter(termQuery("id", documentId))).build(); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + } + + @Test + public void shouldSortResultsGivenSortCriteria() { + // given + List indexQueries = new ArrayList<>(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(10) + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5) + .version(System.currentTimeMillis()).build(); + + // third document + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("xyz").rate(15) + .version(System.currentTimeMillis()).build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withSort(new FieldSortBuilder("rate").order(SortOrder.ASC)).build(); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(3L)); + assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity2.getRate())); + } + + @Test + public void shouldSortResultsGivenMultipleSortCriteria() { + // given + List indexQueries = new ArrayList<>(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(10) + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5) + .version(System.currentTimeMillis()).build(); + + // third document + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("xyz").rate(15) + .version(System.currentTimeMillis()).build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withSort(new FieldSortBuilder("rate").order(SortOrder.ASC)) + .withSort(new FieldSortBuilder("message").order(SortOrder.ASC)).build(); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(3L)); + assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity2.getRate())); + assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage())); + } + + @Test // DATAES-312 + public void shouldSortResultsGivenNullFirstSortCriteria() { + // given + List indexQueries; + + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(15) + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5) + .version(System.currentTimeMillis()).build(); + + // third document + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).rate(10).version(System.currentTimeMillis()) + .build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsFirst()))).build(); + + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + + // then + assertThat(sampleEntities.getTotalElements(), equalTo(3L)); + assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity3.getRate())); + assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage())); + } + + @Test // DATAES-312 + public void shouldSortResultsGivenNullLastSortCriteria() { + // given + List indexQueries; + + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("abc").rate(15) + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("xyz").rate(5) + .version(System.currentTimeMillis()).build(); + + // third document + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).rate(10).version(System.currentTimeMillis()) + .build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsLast()))).build(); + + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + + // then + assertThat(sampleEntities.getTotalElements(), equalTo(3L)); + assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity1.getRate())); + assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity2.getMessage())); + } + + @Test + public void shouldExecuteStringQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + } + + @Test + public void shouldUseScriptedFields() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setRate(2); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId(documentId); + indexQuery.setObject(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + Map params = new HashMap<>(); + params.put("factor", 2); + // when + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withScriptField( + new ScriptField("scriptedRate", new Script(ScriptType.INLINE, "expression", "doc['rate'] * factor", params))) + .build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + assertThat(sampleEntities.getContent().get(0).getScriptedRate(), equalTo(4.0)); + } + + @Test + public void shouldReturnPageableResultsGivenStringQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + StringQuery stringQuery = new StringQuery(matchAllQuery().toString(), new PageRequest(0, 10)); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class); + + // then + assertThat(sampleEntities.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldReturnSortedPageableResultsGivenStringQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId(documentId); + indexQuery.setObject(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + StringQuery stringQuery = new StringQuery(matchAllQuery().toString(), new PageRequest(0, 10), + new Sort(new Sort.Order(Sort.Direction.ASC, "message"))); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldReturnObjectMatchingGivenStringQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + StringQuery stringQuery = new StringQuery(termQuery("id", documentId).toString()); + // when + SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(stringQuery, SampleEntity.class); + // then + assertThat(sampleEntity1, is(notNullValue())); + assertThat(sampleEntity1.getId(), is(equalTo(documentId))); + } + + @Test + public void shouldCreateIndexGivenEntityClass() { + // when + boolean created = elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.putMapping(SampleEntity.class); + final Map setting = elasticsearchTemplate.getSetting(SampleEntity.class); + // then + assertThat(created, is(true)); + assertThat(setting.get("index.number_of_shards"), Matchers. is("1")); + assertThat(setting.get("index.number_of_replicas"), Matchers. is("0")); + } + + @Test + public void shouldExecuteGivenCriteriaQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); + + // when + SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat(sampleEntity1, is(notNullValue())); + } + + @Test + public void shouldDeleteGivenCriteriaQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); + + // when + elasticsearchTemplate.delete(criteriaQuery, SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); + List sampleEntities = elasticsearchTemplate.queryForList(stringQuery, SampleEntity.class); + + assertThat(sampleEntities.size(), is(0)); + } + + @Test + public void shouldReturnSpecifiedFields() { + // given + String documentId = randomNumeric(5); + String message = "some test message"; + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes(TYPE_NAME).withFields("message").build(); + // when + Page page = elasticsearchTemplate.queryForPage(searchQuery, String.class, new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List values = new ArrayList<>(); + for (SearchHit searchHit : response.getHits()) { + values.add((String) searchHit.getSourceAsMap().get("message")); + } + return new AggregatedPageImpl<>((List) values); + } + }); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + assertThat(page.getContent().get(0), is(message)); + } + + @Test + public void shouldReturnFieldsBasedOnSourceFilter() { + // given + String documentId = randomNumeric(5); + String message = "some test message"; + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + FetchSourceFilterBuilder sourceFilter = new FetchSourceFilterBuilder(); + sourceFilter.withIncludes("message"); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes(TYPE_NAME).withSourceFilter(sourceFilter.build()).build(); + // when + Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + assertThat(page.getContent().get(0).getMessage(), is(message)); + } + + @Test + public void shouldReturnSimilarResultsGivenMoreLikeThisQuery() { + // given + String sampleMessage = "So we build a web site or an application and want to add search to it, " + + "and then it hits us: getting search working is hard. We want our search solution to be fast," + + " we want a painless setup and a completely free search schema, we want to be able to index data simply using JSON over HTTP, " + + "we want our search server to be always available, we want to be able to start with one machine and scale to hundreds, " + + "we want real-time search, we want simple multi-tenancy, and we want a solution that is built for the cloud."; + + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId1).message(sampleMessage) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + + String documentId2 = randomNumeric(5); + + elasticsearchTemplate.index(getIndexQuery( + SampleEntity.builder().id(documentId2).message(sampleMessage).version(System.currentTimeMillis()).build())); + elasticsearchTemplate.refresh(SampleEntity.class); + + MoreLikeThisQuery moreLikeThisQuery = new MoreLikeThisQuery(); + moreLikeThisQuery.setId(documentId2); + moreLikeThisQuery.addFields("message"); + moreLikeThisQuery.setMinDocFreq(1); + // when + Page sampleEntities = elasticsearchTemplate.moreLikeThis(moreLikeThisQuery, SampleEntity.class); + + // then + assertThat(sampleEntities.getTotalElements(), is(equalTo(1L))); + assertThat(sampleEntities.getContent(), hasItem(sampleEntity)); + } + + /* + DATAES-167 + */ + @Test + public void shouldReturnResultsWithScanAndScrollForGivenCriteriaQuery() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices(INDEX_NAME); + criteriaQuery.addTypes(TYPE_NAME); + criteriaQuery.setPageable(new PageRequest(0, 10)); + + ScrolledPage scroll = (ScrolledPage) elasticsearchTemplate.startScroll(1000, + criteriaQuery, SampleEntity.class); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scroll = (ScrolledPage) elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, + SampleEntity.class); + } + elasticsearchTemplate.clearScroll(scroll.getScrollId()); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + @Test + public void shouldReturnResultsWithScanAndScrollForGivenSearchQuery() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes(TYPE_NAME).withPageable(new PageRequest(0, 10)).build(); + + ScrolledPage scroll = (ScrolledPage) elasticsearchTemplate.startScroll(1000, + searchQuery, SampleEntity.class); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scroll = (ScrolledPage) elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, + SampleEntity.class); + } + elasticsearchTemplate.clearScroll(scroll.getScrollId()); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + final SearchResultMapper searchResultMapper = new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List result = new ArrayList(); + for (SearchHit searchHit : response.getHits()) { + if (response.getHits().getHits().length <= 0) { + return new AggregatedPageImpl(Collections.EMPTY_LIST, response.getScrollId()); + } + String message = (String) searchHit.getSourceAsMap().get("message"); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(searchHit.getId()); + sampleEntity.setMessage(message); + result.add(sampleEntity); + } + + if (result.size() > 0) { + return new AggregatedPageImpl((List) result, response.getScrollId()); + } + return new AggregatedPageImpl(Collections.EMPTY_LIST, response.getScrollId()); + } + }; + + /* + DATAES-167 + */ + @Test + public void shouldReturnResultsWithScanAndScrollForSpecifiedFieldsForCriteriaQuery() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices(INDEX_NAME); + criteriaQuery.addTypes(TYPE_NAME); + criteriaQuery.addFields("message"); + criteriaQuery.setPageable(new PageRequest(0, 10)); + + Page scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, + searchResultMapper); + String scrollId = ((ScrolledPage) scroll).getScrollId(); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scrollId = ((ScrolledPage) scroll).getScrollId(); + scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper); + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + /* + DATAES-84 + */ + @Test + public void shouldReturnResultsWithScanAndScrollForSpecifiedFieldsForSearchCriteria() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes(TYPE_NAME).withFields("message").withQuery(matchAllQuery()).withPageable(new PageRequest(0, 10)) + .build(); + + Page scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, + searchResultMapper); + String scrollId = ((ScrolledPage) scroll).getScrollId(); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scrollId = ((ScrolledPage) scroll).getScrollId(); + scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper); + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + /* + DATAES-167 + */ + @Test + public void shouldReturnResultsForScanAndScrollWithCustomResultMapperForGivenCriteriaQuery() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices(INDEX_NAME); + criteriaQuery.addTypes(TYPE_NAME); + criteriaQuery.setPageable(new PageRequest(0, 10)); + + Page scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, + searchResultMapper); + String scrollId = ((ScrolledPage) scroll).getScrollId(); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scrollId = ((ScrolledPage) scroll).getScrollId(); + scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper); + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + @Test + public void shouldReturnResultsForScanAndScrollWithCustomResultMapperForGivenSearchQuery() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes(TYPE_NAME).withPageable(new PageRequest(0, 10)).build(); + + Page scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, + searchResultMapper); + String scrollId = ((ScrolledPage) scroll).getScrollId(); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scrollId = ((ScrolledPage) scroll).getScrollId(); + scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper); + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + /* + DATAES-217 + */ + @Test + public void shouldReturnResultsWithScanAndScrollForGivenCriteriaQueryAndClass() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.setPageable(new PageRequest(0, 10)); + + Page scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class); + String scrollId = ((ScrolledPage) scroll).getScrollId(); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scrollId = ((ScrolledPage) scroll).getScrollId(); + scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + /* + DATAES-217 + */ + @Test + public void shouldReturnResultsWithScanAndScrollForGivenSearchQueryAndClass() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withPageable(new PageRequest(0, 10)).build(); + + Page scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class); + String scrollId = ((ScrolledPage) scroll).getScrollId(); + List sampleEntities = new ArrayList<>(); + while (scroll.hasContent()) { + sampleEntities.addAll(scroll.getContent()); + scrollId = ((ScrolledPage) scroll).getScrollId(); + scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + /* + DATAES-167 + */ + @Test + public void shouldReturnResultsWithStreamForGivenCriteriaQuery() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices(INDEX_NAME); + criteriaQuery.addTypes(TYPE_NAME); + criteriaQuery.setPageable(new PageRequest(0, 10)); + + CloseableIterator stream = elasticsearchTemplate.stream(criteriaQuery, SampleEntity.class); + List sampleEntities = new ArrayList<>(); + while (stream.hasNext()) { + sampleEntities.add(stream.next()); + } + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + private static List createSampleEntitiesWithMessage(String message, int numberOfEntities) { + List indexQueries = new ArrayList<>(); + for (int i = 0; i < numberOfEntities; i++) { + String documentId = UUID.randomUUID().toString(); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage(message); + sampleEntity.setRate(2); + sampleEntity.setVersion(System.currentTimeMillis()); + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId(documentId); + indexQuery.setObject(sampleEntity); + indexQueries.add(indexQuery); + } + return indexQueries; + } + + @Test + public void shouldReturnListForGivenCriteria() { + // given + List indexQueries = new ArrayList<>(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("test message") + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("test test").rate(5) + .version(System.currentTimeMillis()).build(); + + // third document + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("some message").rate(15) + .version(System.currentTimeMillis()).build(); + + indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + // when + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + // when + CriteriaQuery singleCriteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); + CriteriaQuery multipleCriteriaQuery = new CriteriaQuery( + new Criteria("message").contains("some").and("message").contains("message")); + List sampleEntitiesForSingleCriteria = elasticsearchTemplate.queryForList(singleCriteriaQuery, + SampleEntity.class); + List sampleEntitiesForAndCriteria = elasticsearchTemplate.queryForList(multipleCriteriaQuery, + SampleEntity.class); + // then + assertThat(sampleEntitiesForSingleCriteria.size(), is(2)); + assertThat(sampleEntitiesForAndCriteria.size(), is(1)); + } + + @Test + public void shouldReturnListForGivenStringQuery() { + // given + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId).message("test message") + .version(System.currentTimeMillis()).build(); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("test test").rate(5) + .version(System.currentTimeMillis()).build(); + + // third document + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = SampleEntity.builder().id(documentId3).message("some message").rate(15) + .version(System.currentTimeMillis()).build(); + + List indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + // when + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + // when + StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); + List sampleEntities = elasticsearchTemplate.queryForList(stringQuery, SampleEntity.class); + // then + assertThat(sampleEntities.size(), is(3)); + } + + @Test + public void shouldPutMappingForGivenEntity() throws Exception { + // given + Class entity = SampleMappingEntity.class; + elasticsearchTemplate.deleteIndex(entity); + elasticsearchTemplate.createIndex(entity); + // when + assertThat(elasticsearchTemplate.putMapping(entity), is(true)); + } + + @Test + public void shouldDeleteIndexForGivenEntity() { + // given + Class clazz = SampleEntity.class; + // when + elasticsearchTemplate.deleteIndex(clazz); + // then + assertThat(elasticsearchTemplate.indexExists(clazz), is(false)); + } + + @Test + public void shouldDoPartialUpdateForExistingDocument() { + // given + String documentId = randomNumeric(5); + String messageBeforeUpdate = "some test message"; + String messageAfterUpdate = "test message"; + + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(messageBeforeUpdate) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + IndexRequest indexRequest = new IndexRequest(); + indexRequest.source("message", messageAfterUpdate); + UpdateQuery updateQuery = new UpdateQueryBuilder().withId(documentId).withClass(SampleEntity.class) + .withIndexRequest(indexRequest).build(); + // when + elasticsearchTemplate.update(updateQuery); + // then + GetQuery getQuery = new GetQuery(); + getQuery.setId(documentId); + SampleEntity indexedEntity = elasticsearchTemplate.queryForObject(getQuery, SampleEntity.class); + assertThat(indexedEntity.getMessage(), is(messageAfterUpdate)); + } + + @Test + public void shouldDoUpsertIfDocumentDoesNotExist() { + // given + String documentId = randomNumeric(5); + String message = "test message"; + IndexRequest indexRequest = new IndexRequest(); + indexRequest.source("message", message); + UpdateQuery updateQuery = new UpdateQueryBuilder().withId(documentId).withDoUpsert(true) + .withClass(SampleEntity.class).withIndexRequest(indexRequest).build(); + // when + elasticsearchTemplate.update(updateQuery); + // then + GetQuery getQuery = new GetQuery(); + getQuery.setId(documentId); + SampleEntity indexedEntity = elasticsearchTemplate.queryForObject(getQuery, SampleEntity.class); + assertThat(indexedEntity.getMessage(), is(message)); + } + + @Test + public void shouldReturnHighlightedFieldsForGivenQueryAndFields() { + + // given + String documentId = randomNumeric(5); + String actualMessage = "some test message"; + String highlightedMessage = "some test message"; + + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(actualMessage) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + final List message = new HighlightBuilder().field("message").fields(); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("message", "test")) + .withHighlightFields(message.toArray(new HighlightBuilder.Field[message.size()])).build(); + + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, + new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List chunk = new ArrayList<>(); + SearchHits hits = response.getHits(); + for (SearchHit searchHit : hits.getHits()) { + SampleEntity user = new SampleEntity(); + user.setId(searchHit.getId()); + user.setMessage((String) searchHit.getSourceAsMap().get("message")); + user.setHighlightedMessage(searchHit.getHighlightFields().get("message").fragments()[0].toString()); + chunk.add(user); + } + if (chunk.size() > 0) { + return new AggregatedPageImpl<>((List) chunk); + } + return null; + } + }); + + assertThat(sampleEntities.getContent().get(0).getHighlightedMessage(), is(highlightedMessage)); + } + + @Test // DATAES-412 + public void shouldReturnMultipleHighlightFields() { + + // given + String documentId = randomNumeric(5); + String actualType = "some test type"; + String actualMessage = "some test message"; + String highlightedType = "some test type"; + String highlightedMessage = "some test message"; + + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).type(actualType).message(actualMessage) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(boolQuery().must(termQuery("type", "test")).must(termQuery("message", "test"))) + .withHighlightFields(new HighlightBuilder.Field("type"), new HighlightBuilder.Field("message")).build(); + + // when + elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + for (SearchHit searchHit : response.getHits()) { + Map highlightFields = searchHit.getHighlightFields(); + HighlightField highlightFieldType = highlightFields.get("type"); + HighlightField highlightFieldMessage = highlightFields.get("message"); + + // then + assertNotNull(highlightFieldType); + assertNotNull(highlightFieldMessage); + assertThat(highlightFieldType.fragments()[0].toString(), is(highlightedType)); + assertThat(highlightFieldMessage.fragments()[0].toString(), is(highlightedMessage)); + } + return null; + } + }); + } + + @Test + public void shouldDeleteDocumentBySpecifiedTypeUsingDeleteQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + // when + DeleteQuery deleteQuery = new DeleteQuery(); + deleteQuery.setQuery(termQuery("id", documentId)); + deleteQuery.setIndex(INDEX_NAME); + deleteQuery.setType(TYPE_NAME); + elasticsearchTemplate.delete(deleteQuery); + elasticsearchTemplate.refresh(INDEX_NAME); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + } + + @Test + public void shouldIndexDocumentForSpecifiedSource() { + + // given + String documentSource = "{\"id\":\"2333343434\",\"type\":null,\"message\":\"some message\",\"rate\":0,\"available\":false,\"highlightedMessage\":null,\"version\":1385208779482}"; + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId("2333343434"); + indexQuery.setSource(documentSource); + indexQuery.setIndexName(INDEX_NAME); + indexQuery.setType(TYPE_NAME); + // when + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", indexQuery.getId())) + .withIndices(INDEX_NAME).withTypes(TYPE_NAME).build(); + // then + Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, + new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List values = new ArrayList<>(); + for (SearchHit searchHit : response.getHits()) { + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(searchHit.getId()); + sampleEntity.setMessage((String) searchHit.getSourceAsMap().get("message")); + values.add(sampleEntity); + } + return new AggregatedPageImpl<>((List) values); + } + }); + assertThat(page, is(notNullValue())); + assertThat(page.getContent().size(), is(1)); + assertThat(page.getContent().get(0).getId(), is(indexQuery.getId())); + } + + @Test(expected = ElasticsearchException.class) + public void shouldThrowElasticsearchExceptionWhenNoDocumentSpecified() { + // given + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId("2333343434"); + indexQuery.setIndexName(INDEX_NAME); + indexQuery.setType(TYPE_NAME); + + // when + elasticsearchTemplate.index(indexQuery); + } + + @Test + public void shouldReturnIds() { + // given + List entities = createSampleEntitiesWithMessage("Test message", 30); + // when + elasticsearchTemplate.bulkIndex(entities); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "message")) + .withIndices(INDEX_NAME).withTypes(TYPE_NAME).withPageable(new PageRequest(0, 100)).build(); + // then + List ids = elasticsearchTemplate.queryForIds(searchQuery); + assertThat(ids, is(notNullValue())); + assertThat(ids.size(), is(30)); + } + + @Test + public void shouldReturnDocumentAboveMinimalScoreGivenQuery() { + // given + List indexQueries = new ArrayList<>(); + + indexQueries.add(buildIndex(SampleEntity.builder().id("1").message("ab").build())); + indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build())); + indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac").build())); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + // when + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(boolQuery().must(wildcardQuery("message", "*a*")).should(wildcardQuery("message", "*b*"))) + .withIndices(INDEX_NAME).withTypes(TYPE_NAME).withMinScore(2.0F).build(); + + Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(page.getTotalElements(), is(1L)); + assertThat(page.getContent().get(0).getMessage(), is("ab")); + } + + @Test // DATAES-462 + public void shouldReturnScores() { + + // given + List indexQueries = new ArrayList<>(); + + indexQueries.add(buildIndex(SampleEntity.builder().id("1").message("ab xz").build())); + indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build())); + indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac xz hi").build())); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + + // when + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "xz")) + .withSort(SortBuilders.fieldSort("message")).withTrackScores(true).build(); + + AggregatedPage page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + + // then + assertThat(page.getMaxScore(), greaterThan(0f)); + assertThat(page.getContent().get(0).getScore(), greaterThan(0f)); + } + + @Test + public void shouldDoIndexWithoutId() { + // given + // document + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setObject(sampleEntity); + // when + String documentId = elasticsearchTemplate.index(indexQuery); + // then + assertThat(sampleEntity.getId(), is(equalTo(documentId))); + + GetQuery getQuery = new GetQuery(); + getQuery.setId(documentId); + SampleEntity result = elasticsearchTemplate.queryForObject(getQuery, SampleEntity.class); + assertThat(result.getId(), is(equalTo(documentId))); + } + + @Test + public void shouldDoBulkIndexWithoutId() { + // given + List indexQueries = new ArrayList<>(); + // first document + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setMessage("some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setMessage("some message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + // when + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + assertThat(sampleEntities.getTotalElements(), is(equalTo(2L))); + + assertThat(sampleEntities.getContent().get(0).getId(), is(notNullValue())); + assertThat(sampleEntities.getContent().get(1).getId(), is(notNullValue())); + } + + @Test + public void shouldIndexMapWithIndexNameAndTypeAtRuntime() { + // given + Map person1 = new HashMap<>(); + person1.put("userId", "1"); + person1.put("email", "smhdiu@gmail.com"); + person1.put("title", "Mr"); + person1.put("firstName", "Mohsin"); + person1.put("lastName", "Husen"); + + Map person2 = new HashMap<>(); + person2.put("userId", "2"); + person2.put("email", "akonczak@gmail.com"); + person2.put("title", "Mr"); + person2.put("firstName", "Artur"); + person2.put("lastName", "Konczak"); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId("1"); + indexQuery1.setObject(person1); + indexQuery1.setIndexName(INDEX_NAME); + indexQuery1.setType(TYPE_NAME); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId("2"); + indexQuery2.setObject(person2); + indexQuery2.setIndexName(INDEX_NAME); + indexQuery2.setType(TYPE_NAME); + + List indexQueries = new ArrayList<>(); + indexQueries.add(indexQuery1); + indexQueries.add(indexQuery2); + + // when + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(INDEX_NAME); + + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(INDEX_NAME).withTypes(TYPE_NAME) + .withQuery(matchAllQuery()).build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, Map.class, new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List chunk = new ArrayList<>(); + for (SearchHit searchHit : response.getHits()) { + if (response.getHits().getHits().length <= 0) { + return null; + } + Map person = new HashMap<>(); + person.put("userId", searchHit.getSourceAsMap().get("userId")); + person.put("email", searchHit.getSourceAsMap().get("email")); + person.put("title", searchHit.getSourceAsMap().get("title")); + person.put("firstName", searchHit.getSourceAsMap().get("firstName")); + person.put("lastName", searchHit.getSourceAsMap().get("lastName")); + chunk.add(person); + } + if (chunk.size() > 0) { + return new AggregatedPageImpl<>((List) chunk); + } + return null; + } + }); + assertThat(sampleEntities.getTotalElements(), is(equalTo(2L))); + assertThat(sampleEntities.getContent().get(0).get("userId"), is(person1.get("userId"))); + assertThat(sampleEntities.getContent().get(1).get("userId"), is(person2.get("userId"))); + } + + @Test + public void shouldIndexSampleEntityWithIndexAndTypeAtRuntime() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = new IndexQueryBuilder().withId(documentId).withIndexName(INDEX_NAME).withType(TYPE_NAME) + .withObject(sampleEntity).build(); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(INDEX_NAME); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(INDEX_NAME).withTypes(TYPE_NAME) + .withQuery(matchAllQuery()).build(); + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities, is(notNullValue())); + assertThat(sampleEntities.getTotalElements(), greaterThanOrEqualTo(1L)); + } + + /* + DATAES-106 + */ + @Test + public void shouldReturnCountForGivenCriteriaQueryWithGivenIndexUsingCriteriaQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices(INDEX_NAME); + // when + long count = elasticsearchTemplate.count(criteriaQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-67 + */ + @Test + public void shouldReturnCountForGivenSearchQueryWithGivenIndexUsingSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME).build(); + // when + long count = elasticsearchTemplate.count(searchQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldReturnCountForGivenCriteriaQueryWithGivenIndexAndTypeUsingCriteriaQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices(INDEX_NAME); + criteriaQuery.addTypes("test-type"); + // when + long count = elasticsearchTemplate.count(criteriaQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-67 + */ + @Test + public void shouldReturnCountForGivenSearchQueryWithGivenIndexAndTypeUsingSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes("test-type").build(); + // when + long count = elasticsearchTemplate.count(searchQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldReturnCountForGivenCriteriaQueryWithGivenMultiIndices() { + // given + cleanUpIndices(); + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withIndexName("test-index-1") + .withObject(sampleEntity1).build(); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withIndexName("test-index-2") + .withObject(sampleEntity2).build(); + + elasticsearchTemplate.bulkIndex(Arrays.asList(indexQuery1, indexQuery2)); + elasticsearchTemplate.refresh("test-index-1"); + elasticsearchTemplate.refresh("test-index-2"); + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices("test-index-1", "test-index-2"); + // when + long count = elasticsearchTemplate.count(criteriaQuery); + // then + assertThat(count, is(equalTo(2L))); + } + + /* + DATAES-67 + */ + @Test + public void shouldReturnCountForGivenSearchQueryWithGivenMultiIndices() { + // given + cleanUpIndices(); + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withIndexName("test-index-1") + .withObject(sampleEntity1).build(); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withIndexName("test-index-2") + .withObject(sampleEntity2).build(); + + elasticsearchTemplate.bulkIndex(Arrays.asList(indexQuery1, indexQuery2)); + elasticsearchTemplate.refresh("test-index-1"); + elasticsearchTemplate.refresh("test-index-2"); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withIndices("test-index-1", "test-index-2").build(); + // when + long count = elasticsearchTemplate.count(searchQuery); + // then + assertThat(count, is(equalTo(2L))); + } + + private void cleanUpIndices() { + elasticsearchTemplate.deleteIndex("test-index-1"); + elasticsearchTemplate.deleteIndex("test-index-2"); + elasticsearchTemplate.createIndex("test-index-1"); + elasticsearchTemplate.createIndex("test-index-2"); + elasticsearchTemplate.refresh("test-index-1"); + elasticsearchTemplate.refresh("test-index-2"); + } + + /* + DATAES-71 + */ + @Test + public void shouldCreatedIndexWithSpecifiedIndexName() { + // given + elasticsearchTemplate.deleteIndex("test-index"); + // when + elasticsearchTemplate.createIndex("test-index"); + // then + assertThat(elasticsearchTemplate.indexExists("test-index"), is(true)); + } + + /* + DATAES-72 + */ + @Test + public void shouldDeleteIndexForSpecifiedIndexName() { + // given + elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + + // when + elasticsearchTemplate.deleteIndex("test-index"); + // then + assertThat(elasticsearchTemplate.indexExists("test-index"), is(false)); + } + + /* + DATAES-106 + */ + @Test + public void shouldReturnCountForGivenCriteriaQueryWithGivenIndexNameForSpecificIndex() { + // given + cleanUpIndices(); + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withIndexName("test-index-1") + .withObject(sampleEntity1).build(); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withIndexName("test-index-2") + .withObject(sampleEntity2).build(); + + elasticsearchTemplate.bulkIndex(Arrays.asList(indexQuery1, indexQuery2)); + elasticsearchTemplate.refresh("test-index-1"); + elasticsearchTemplate.refresh("test-index-2"); + + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + criteriaQuery.addIndices("test-index-1"); + // when + long count = elasticsearchTemplate.count(criteriaQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-67 + */ + @Test + public void shouldReturnCountForGivenSearchQueryWithGivenIndexNameForSpecificIndex() { + // given + cleanUpIndices(); + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withIndexName("test-index-1") + .withObject(sampleEntity1).build(); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withIndexName("test-index-2") + .withObject(sampleEntity2).build(); + + elasticsearchTemplate.bulkIndex(Arrays.asList(indexQuery1, indexQuery2)); + elasticsearchTemplate.refresh("test-index-1"); + elasticsearchTemplate.refresh("test-index-2"); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices("test-index-1") + .build(); + // when + long count = elasticsearchTemplate.count(searchQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowAnExceptionForGivenCriteriaQueryWhenNoIndexSpecifiedForCountQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); + // when + long count = elasticsearchTemplate.count(criteriaQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-67 + */ + @Test(expected = IllegalArgumentException.class) + public void shouldThrowAnExceptionForGivenSearchQueryWhenNoIndexSpecifiedForCountQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + // when + long count = elasticsearchTemplate.count(searchQuery); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-71 + */ + @Test + public void shouldCreateIndexWithGivenSettings() { + // given + String settings = "{\n" + " \"index\": {\n" + " \"number_of_shards\": \"1\",\n" + + " \"number_of_replicas\": \"0\",\n" + " \"analysis\": {\n" + + " \"analyzer\": {\n" + " \"emailAnalyzer\": {\n" + + " \"type\": \"custom\",\n" + + " \"tokenizer\": \"uax_url_email\"\n" + " }\n" + + " }\n" + " }\n" + " }\n" + "}"; + + elasticsearchTemplate.deleteIndex("test-index"); + // when + elasticsearchTemplate.createIndex("test-index", settings); + // then + Map map = elasticsearchTemplate.getSetting("test-index"); + boolean hasAnalyzer = map.containsKey("index.analysis.analyzer.emailAnalyzer.tokenizer"); + String emailAnalyzer = (String) map.get("index.analysis.analyzer.emailAnalyzer.tokenizer"); + assertThat(elasticsearchTemplate.indexExists("test-index"), is(true)); + assertThat(hasAnalyzer, is(true)); + assertThat(emailAnalyzer, is("uax_url_email")); + } + + /* + DATAES-71 + */ + @Test + public void shouldCreateGivenSettingsForGivenIndex() { + // given + // delete , create and apply mapping in before method + + // then + Map map = elasticsearchTemplate.getSetting(SampleEntity.class); + assertThat(elasticsearchTemplate.indexExists("test-index"), is(true)); + assertThat(map.containsKey("index.refresh_interval"), is(true)); + assertThat(map.containsKey("index.number_of_replicas"), is(true)); + assertThat(map.containsKey("index.number_of_shards"), is(true)); + assertThat(map.containsKey("index.store.type"), is(true)); + assertThat((String) map.get("index.refresh_interval"), is("-1")); + assertThat((String) map.get("index.number_of_replicas"), is("0")); + assertThat((String) map.get("index.number_of_shards"), is("1")); + assertThat((String) map.get("index.store.type"), is("fs")); + } + + /* + DATAES-88 + */ + @Test + public void shouldCreateIndexWithGivenClassAndSettings() { + // given + String settings = "{\n" + " \"index\": {\n" + " \"number_of_shards\": \"1\",\n" + + " \"number_of_replicas\": \"0\",\n" + " \"analysis\": {\n" + + " \"analyzer\": {\n" + " \"emailAnalyzer\": {\n" + + " \"type\": \"custom\",\n" + + " \"tokenizer\": \"uax_url_email\"\n" + " }\n" + + " }\n" + " }\n" + " }\n" + "}"; + + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(SampleEntity.class, settings); + elasticsearchTemplate.putMapping(SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + + // then + Map map = elasticsearchTemplate.getSetting(SampleEntity.class); + assertThat(elasticsearchTemplate.indexExists(INDEX_NAME), is(true)); + assertThat(map.containsKey("index.number_of_replicas"), is(true)); + assertThat(map.containsKey("index.number_of_shards"), is(true)); + assertThat((String) map.get("index.number_of_replicas"), is("0")); + assertThat((String) map.get("index.number_of_shards"), is("1")); + } + + @Test + public void shouldTestResultsAcrossMultipleIndices() { + // given + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = SampleEntity.builder().id(documentId1).message("some message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery1 = new IndexQueryBuilder().withId(sampleEntity1.getId()).withIndexName("test-index-1") + .withObject(sampleEntity1).build(); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = SampleEntity.builder().id(documentId2).message("some test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withIndexName("test-index-2") + .withObject(sampleEntity2).build(); + + elasticsearchTemplate.bulkIndex(Arrays.asList(indexQuery1, indexQuery2)); + elasticsearchTemplate.refresh("test-index-1"); + elasticsearchTemplate.refresh("test-index-2"); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withIndices("test-index-1", "test-index-2").build(); + // when + List sampleEntities = elasticsearchTemplate.queryForList(searchQuery, SampleEntity.class); + + // then + assertThat(sampleEntities.size(), is(equalTo(2))); + } + + @Test + /** + * This is basically a demonstration to show composing entities out of heterogeneous indexes. + */ + public void shouldComposeObjectsReturnedFromHeterogeneousIndexes() { + + // Given + + HetroEntity1 entity1 = new HetroEntity1(randomNumeric(3), "aFirstName"); + HetroEntity2 entity2 = new HetroEntity2(randomNumeric(4), "aLastName"); + + IndexQuery idxQuery1 = new IndexQueryBuilder().withIndexName(INDEX_1_NAME).withId(entity1.getId()) + .withObject(entity1).build(); + IndexQuery idxQuery2 = new IndexQueryBuilder().withIndexName(INDEX_2_NAME).withId(entity2.getId()) + .withObject(entity2).build(); + + elasticsearchTemplate.bulkIndex(Arrays.asList(idxQuery1, idxQuery2)); + elasticsearchTemplate.refresh(INDEX_1_NAME); + elasticsearchTemplate.refresh(INDEX_2_NAME); + + // When + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withTypes("hetro") + .withIndices(INDEX_1_NAME, INDEX_2_NAME).build(); + Page page = elasticsearchTemplate.queryForPage(searchQuery, ResultAggregator.class, + new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List values = new ArrayList<>(); + for (SearchHit searchHit : response.getHits()) { + String id = String.valueOf(searchHit.getSourceAsMap().get("id")); + String firstName = StringUtils.isNotEmpty((String) searchHit.getSourceAsMap().get("firstName")) + ? (String) searchHit.getSourceAsMap().get("firstName") + : ""; + String lastName = StringUtils.isNotEmpty((String) searchHit.getSourceAsMap().get("lastName")) + ? (String) searchHit.getSourceAsMap().get("lastName") + : ""; + values.add(new ResultAggregator(id, firstName, lastName)); + } + return new AggregatedPageImpl<>((List) values); + } + }); + + assertThat(page.getTotalElements(), is(2l)); + } + + @Test + public void shouldCreateIndexUsingServerDefaultConfiguration() { + // given + + // when + boolean created = elasticsearchTemplate.createIndex(UseServerConfigurationEntity.class); + // then + assertThat(created, is(true)); + final Map setting = elasticsearchTemplate.getSetting(UseServerConfigurationEntity.class); + assertThat(setting.get("index.number_of_shards"), Matchers. is("5")); + assertThat(setting.get("index.number_of_replicas"), Matchers. is("1")); + } + + @Test + public void shouldReadFileFromClasspathRetainingNewlines() { + // given + String settingsFile = "/settings/test-settings.yml"; + + // when + String content = ElasticsearchTemplate.readFileFromClasspath(settingsFile); + + // then + assertThat(content, + is("index:\n" + " number_of_shards: 1\n" + " number_of_replicas: 0\n" + " analysis:\n" + " analyzer:\n" + + " emailAnalyzer:\n" + " type: custom\n" + " tokenizer: uax_url_email\n")); + } + + private IndexQuery getIndexQuery(SampleEntity sampleEntity) { + return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity) + .withVersion(sampleEntity.getVersion()).build(); + } + + private List getIndexQueries(List sampleEntities) { + List indexQueries = new ArrayList<>(); + for (SampleEntity sampleEntity : sampleEntities) { + indexQueries.add(getIndexQuery(sampleEntity)); + } + return indexQueries; + } + + @Document(indexName = INDEX_2_NAME, replicas = 0, shards = 1) + class ResultAggregator { + + private String id; + private String firstName; + private String lastName; + + ResultAggregator(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java b/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java index ebd1754d5..7d2c4f462 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2016 the original author or authors. + * Copyright 2013-2018 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. @@ -21,6 +21,7 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.springframework.data.elasticsearch.utils.IndexBuilder.*; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.util.Date; @@ -45,13 +46,19 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @author Mohsin Husen * @author Keivn Leturc * @author Nordine Bittich + * @author Don Wellington */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:elasticsearch-template-test.xml") public class MappingBuilderTests { - @Autowired - private ElasticsearchTemplate elasticsearchTemplate; + @Autowired private ElasticsearchTemplate elasticsearchTemplate; + + private String xContentBuilderToString(XContentBuilder builder) { + builder.close(); + ByteArrayOutputStream bos = (ByteArrayOutputStream) builder.getOutputStream(); + return bos.toString(); + } @Test public void shouldNotFailOnCircularReference() { @@ -63,43 +70,43 @@ public class MappingBuilderTests { @Test public void testInfiniteLoopAvoidance() throws IOException { - final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" + - "type\":\"text\",\"index\":false," + - "\"analyzer\":\"standard\"}}}}"; + final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" + + "type\":\"text\",\"index\":false," + "\"analyzer\":\"standard\"}}}}"; XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleTransientEntity.class, "mapping", "id", null); - assertThat(xContentBuilder.string(), is(expected)); + assertThat(xContentBuilderToString(xContentBuilder), is(expected)); } @Test public void shouldUseValueFromAnnotationType() throws IOException { - //Given + // Given final String expected = "{\"mapping\":{\"properties\":{\"price\":{\"store\":false,\"type\":\"double\"}}}}"; - //When + // When XContentBuilder xContentBuilder = MappingBuilder.buildMapping(StockPrice.class, "mapping", "id", null); - //Then - assertThat(xContentBuilder.string(), is(expected)); + // Then + assertThat(xContentBuilderToString(xContentBuilder), is(expected)); } @Test public void shouldAddStockPriceDocumentToIndex() throws IOException { - //Given + // Given - //When + // When elasticsearchTemplate.deleteIndex(StockPrice.class); elasticsearchTemplate.createIndex(StockPrice.class); elasticsearchTemplate.putMapping(StockPrice.class); String symbol = "AU"; double price = 2.34; String id = "abc"; - elasticsearchTemplate.index(buildIndex(StockPrice.builder().id(id).symbol(symbol).price(new BigDecimal(price)).build())); + elasticsearchTemplate + .index(buildIndex(StockPrice.builder().id(id).symbol(symbol).price(new BigDecimal(price)).build())); elasticsearchTemplate.refresh(StockPrice.class); SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); List result = elasticsearchTemplate.queryForList(searchQuery, StockPrice.class); - //Then + // Then assertThat(result.size(), is(1)); StockPrice entry = result.get(0); assertThat(entry.getSymbol(), is(symbol)); @@ -110,7 +117,7 @@ public class MappingBuilderTests { public void shouldCreateMappingForSpecifiedParentType() throws IOException { final String expected = "{\"mapping\":{\"_parent\":{\"type\":\"parentType\"},\"properties\":{}}}"; XContentBuilder xContentBuilder = MappingBuilder.buildMapping(MinimalEntity.class, "mapping", "id", "parentType"); - assertThat(xContentBuilder.string(), is(expected)); + assertThat(xContentBuilderToString(xContentBuilder), is(expected)); } /* @@ -118,13 +125,12 @@ public class MappingBuilderTests { */ @Test public void shouldBuildMappingWithSuperclass() throws IOException { - final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" + - "type\":\"text\",\"index\":false,\"analyzer\":\"standard\"}" + - ",\"createdDate\":{\"store\":false," + - "\"type\":\"date\",\"index\":false}}}}"; + final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" + + "type\":\"text\",\"index\":false,\"analyzer\":\"standard\"}" + ",\"createdDate\":{\"store\":false," + + "\"type\":\"date\",\"index\":false}}}}"; XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleInheritedEntity.class, "mapping", "id", null); - assertThat(xContentBuilder.string(), is(expected)); + assertThat(xContentBuilderToString(xContentBuilder), is(expected)); } /* @@ -132,21 +138,22 @@ public class MappingBuilderTests { */ @Test public void shouldAddSampleInheritedEntityDocumentToIndex() throws IOException { - //Given + // Given - //When + // When elasticsearchTemplate.deleteIndex(SampleInheritedEntity.class); elasticsearchTemplate.createIndex(SampleInheritedEntity.class); elasticsearchTemplate.putMapping(SampleInheritedEntity.class); Date createdDate = new Date(); String message = "msg"; String id = "abc"; - elasticsearchTemplate.index(new SampleInheritedEntityBuilder(id).createdDate(createdDate).message(message).buildIndex()); + elasticsearchTemplate + .index(new SampleInheritedEntityBuilder(id).createdDate(createdDate).message(message).buildIndex()); elasticsearchTemplate.refresh(SampleInheritedEntity.class); SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); List result = elasticsearchTemplate.queryForList(searchQuery, SampleInheritedEntity.class); - //Then + // Then assertThat(result.size(), is(1)); SampleInheritedEntity entry = result.get(0); assertThat(entry.getCreatedDate(), is(createdDate)); @@ -155,13 +162,13 @@ public class MappingBuilderTests { @Test public void shouldBuildMappingsForGeoPoint() throws IOException { - //given + // given - //when + // when XContentBuilder xContentBuilder = MappingBuilder.buildMapping(GeoEntity.class, "mapping", "id", null); - //then - final String result = xContentBuilder.string(); + // then + final String result = xContentBuilderToString(xContentBuilder); assertThat(result, containsString("\"pointA\":{\"type\":\"geo_point\"")); assertThat(result, containsString("\"pointB\":{\"type\":\"geo_point\"")); @@ -174,40 +181,40 @@ public class MappingBuilderTests { */ @Test public void shouldHandleReverseRelationship() { - //given + // given elasticsearchTemplate.createIndex(User.class); elasticsearchTemplate.putMapping(User.class); elasticsearchTemplate.createIndex(Group.class); elasticsearchTemplate.putMapping(Group.class); - //when + // when - //then + // then } @Test public void shouldMapBooks() { - //given + // given elasticsearchTemplate.createIndex(Book.class); elasticsearchTemplate.putMapping(Book.class); - //when - //then + // when + // then } @Test // DATAES-420 public void shouldUseBothAnalyzer() { - //given + // given elasticsearchTemplate.deleteIndex(Book.class); elasticsearchTemplate.createIndex(Book.class); elasticsearchTemplate.putMapping(Book.class); - //when + // when Map mapping = elasticsearchTemplate.getMapping(Book.class); Map descriptionMapping = (Map) ((Map) mapping.get("properties")).get("description"); Map prefixDescription = (Map) ((Map) descriptionMapping.get("fields")).get("prefix"); - //then + // then assertThat(prefixDescription.size(), is(3)); assertThat(prefixDescription.get("type"), equalTo("text")); assertThat(prefixDescription.get("analyzer"), equalTo("stop")); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/SimpleElasticsearchDateMappingTests.java b/src/test/java/org/springframework/data/elasticsearch/core/SimpleElasticsearchDateMappingTests.java index 7ea2d1311..1262e201f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/SimpleElasticsearchDateMappingTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/SimpleElasticsearchDateMappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2018 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. @@ -16,6 +16,7 @@ package org.springframework.data.elasticsearch.core; import java.beans.IntrospectionException; +import java.io.ByteArrayOutputStream; import java.io.IOException; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -26,6 +27,7 @@ import org.springframework.data.elasticsearch.entities.SampleDateMappingEntity; /** * @author Jakub Vavrik * @author Mohsin Husen + * @author Don Wellington */ public class SimpleElasticsearchDateMappingTests { @@ -37,6 +39,9 @@ public class SimpleElasticsearchDateMappingTests { @Test public void testCorrectDateMappings() throws NoSuchFieldException, IntrospectionException, IOException { XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleDateMappingEntity.class, "mapping", "id", null); - Assert.assertEquals(EXPECTED_MAPPING, xContentBuilder.string()); + xContentBuilder.close(); + ByteArrayOutputStream bos = (ByteArrayOutputStream) xContentBuilder.getOutputStream(); + String result = bos.toString(); + Assert.assertEquals(EXPECTED_MAPPING, result); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryBaseTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryBaseTests.java new file mode 100644 index 000000000..76d4b9611 --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryBaseTests.java @@ -0,0 +1,1202 @@ +/* + * Copyright 2013-2018 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.repositories; + +import static org.apache.commons.lang.RandomStringUtils.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.data.elasticsearch.repositories.custom.SampleCustomMethodRepository; +import org.springframework.data.geo.Box; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Metrics; +import org.springframework.data.geo.Point; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Franck Marchand + * @author Kevin Leturc + * @author Christoph Strobl + * @author Don Wellington + */ + +public abstract class CustomMethodRepositoryBaseTests { + + @Autowired private SampleCustomMethodRepository repository; + + @Test + public void shouldExecuteCustomMethod() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("some message"); + repository.save(sampleEntity); + // when + Page page = repository.findByType("test", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForNot() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("some"); + sampleEntity.setMessage("some message"); + repository.save(sampleEntity); + // when + Page page = repository.findByTypeNot("test", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + String searchTerm = "customQuery"; + sampleEntity.setMessage(searchTerm); + repository.save(sampleEntity); + // when + Page page = repository.findByMessage(searchTerm.toLowerCase(), new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithLessThan() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(9); + sampleEntity.setMessage("some message"); + repository.save(sampleEntity); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setRate(20); + sampleEntity2.setMessage("some message"); + repository.save(sampleEntity2); + + // when + Page page = repository.findByRateLessThan(10, new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithBefore() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("some message"); + repository.save(sampleEntity); + + // when + Page page = repository.findByRateBefore(10, new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithAfter() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("some message"); + repository.save(sampleEntity); + + // when + Page page = repository.findByRateAfter(10, new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithLike() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // when + Page page = repository.findByMessageLike("fo", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForStartingWith() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // when + Page page = repository.findByMessageStartingWith("fo", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForEndingWith() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // when + Page page = repository.findByMessageEndingWith("o", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForContains() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // when + Page page = repository.findByMessageContaining("fo", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForIn() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + repository.save(sampleEntity2); + + List ids = Arrays.asList(documentId, documentId2); + + // when + Page page = repository.findByIdIn(ids, new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(2L))); + } + + @Test + public void shouldExecuteCustomMethodForNotIn() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + repository.save(sampleEntity2); + + List ids = Arrays.asList(documentId); + + // when + Page page = repository.findByIdNotIn(ids, new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + assertThat(page.getContent().get(0).getId(), is(documentId2)); + } + + @Test + public void shouldExecuteCustomMethodForTrue() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + // when + Page page = repository.findByAvailableTrue(new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForFalse() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + // when + Page page = repository.findByAvailableFalse(new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodForOrderBy() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("abc"); + sampleEntity.setMessage("test"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // document 2 + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("xyz"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + + // document 3 + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId3); + sampleEntity3.setType("def"); + sampleEntity3.setMessage("foo"); + sampleEntity3.setAvailable(false); + repository.save(sampleEntity3); + + // when + Page page = repository.findByMessageOrderByTypeAsc("foo", new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithBooleanParameter() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + // when + Page page = repository.findByAvailable(false, new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldReturnPageableResultsWithQueryAnnotationExpectedPageSize() { + // given + for (int i = 0; i < 30; i++) { + String documentId = String.valueOf(i); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("message"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + } + // when + Page pageResult = repository.findByMessage("message", new PageRequest(0, 23)); + // then + assertThat(pageResult.getTotalElements(), is(equalTo(30L))); + assertThat(pageResult.getContent().size(), is(equalTo(23))); + } + + @Test + public void shouldReturnPageableResultsWithGivenSortingOrder() { + // given + String documentId = random(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("abc"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("abd"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity2); + + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId3); + sampleEntity3.setMessage("abe"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity3); + // when + Page pageResult = repository.findByMessageContaining("a", + new PageRequest(0, 23, new Sort(new Sort.Order(Sort.Direction.DESC, "message")))); + // then + assertThat(pageResult.getContent().isEmpty(), is(false)); + assertThat(pageResult.getContent().get(0).getMessage(), is(sampleEntity3.getMessage())); + } + + @Test + public void shouldReturnListForMessage() { + // given + String documentId = random(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("abc"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("abd"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity2); + + String documentId3 = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId3); + sampleEntity3.setMessage("abe"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity3); + // when + List sampleEntities = repository.findByMessage("abc"); + // then + assertThat(sampleEntities.isEmpty(), is(false)); + assertThat(sampleEntities.size(), is(1)); + } + + @Test + public void shouldExecuteCustomMethodWithGeoPoint() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + // when + Page page = repository.findByLocation(new GeoPoint(45.7806d, 3.0875d), new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithGeoPointAndString() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(48.7806d, 3.0875d)); + + repository.save(sampleEntity); + + // when + Page page = repository.findByLocationAndMessage(new GeoPoint(45.7806d, 3.0875d), "foo", + new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithWithinGeoPoint() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + // when + Page page = repository.findByLocationWithin(new GeoPoint(45.7806d, 3.0875d), "2km", + new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithWithinPoint() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + // when + Page page = repository.findByLocationWithin(new Point(45.7806d, 3.0875d), + new Distance(2, Metrics.KILOMETERS), new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithNearBox() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test2"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("foo"); + sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); + + repository.save(sampleEntity2); + + // when + Page pageAll = repository.findAll(new PageRequest(0, 10)); + // then + assertThat(pageAll, is(notNullValue())); + assertThat(pageAll.getTotalElements(), is(equalTo(2L))); + + // when + Page page = repository.findByLocationNear(new Box(new Point(46d, 3d), new Point(45d, 4d)), + new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldExecuteCustomMethodWithNearPointAndDistance() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + // when + Page page = repository.findByLocationNear(new Point(45.7806d, 3.0875d), + new Distance(2, Metrics.KILOMETERS), new PageRequest(0, 10)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + /* + DATAES-165 + */ + @Test + public void shouldAllowReturningJava8StreamInCustomQuery() { + // given + List entities = createSampleEntities("abc", 30); + repository.saveAll(entities); + + // when + Stream stream = repository.findByType("abc"); + // then + assertThat(stream, is(notNullValue())); + assertThat(stream.count(), is(equalTo(30L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethod() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("some message"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test2"); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByType("test"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForNot() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("some"); + sampleEntity.setMessage("some message"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByTypeNot("test"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithBooleanParameter() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + // when + long count = repository.countByAvailable(false); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithLessThan() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(9); + sampleEntity.setMessage("some message"); + repository.save(sampleEntity); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setRate(20); + sampleEntity2.setMessage("some message"); + repository.save(sampleEntity2); + + // when + long count = repository.countByRateLessThan(10); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithBefore() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("some message"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(20); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByRateBefore(10); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithAfter() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("some message"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(0); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByRateAfter(10); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithLike() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByMessageLike("fo"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForStartingWith() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByMessageStartingWith("fo"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForEndingWith() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByMessageEndingWith("o"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForContains() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("some message"); + + repository.save(sampleEntity2); + + // when + long count = repository.countByMessageContaining("fo"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForIn() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + repository.save(sampleEntity2); + + List ids = Arrays.asList(documentId, documentId2); + + // when + long count = repository.countByIdIn(ids); + // then + assertThat(count, is(equalTo(2L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForNotIn() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + repository.save(sampleEntity2); + + List ids = Arrays.asList(documentId); + + // when + long count = repository.countByIdNotIn(ids); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForTrue() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + // when + long count = repository.countByAvailableTrue(); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodForFalse() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setMessage("foo"); + sampleEntity.setAvailable(true); + repository.save(sampleEntity); + + // given + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setType("test"); + sampleEntity2.setMessage("bar"); + sampleEntity2.setAvailable(false); + repository.save(sampleEntity2); + // when + long count = repository.countByAvailableFalse(); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithWithinGeoPoint() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("foo"); + sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); + + repository.save(sampleEntity2); + + // when + long count = repository.countByLocationWithin(new GeoPoint(45.7806d, 3.0875d), "2km"); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithWithinPoint() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("foo"); + sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); + + repository.save(sampleEntity2); + + // when + long count = repository.countByLocationWithin(new Point(45.7806d, 3.0875d), new Distance(2, Metrics.KILOMETERS)); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithNearBox() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test2"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("foo"); + sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); + + repository.save(sampleEntity2); + + // when + long count = repository.countByLocationNear(new Box(new Point(46d, 3d), new Point(45d, 4d))); + // then + assertThat(count, is(equalTo(1L))); + } + + /* + DATAES-106 + */ + @Test + public void shouldCountCustomMethodWithNearPointAndDistance() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setType("test"); + sampleEntity.setRate(10); + sampleEntity.setMessage("foo"); + sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); + + repository.save(sampleEntity); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("test"); + sampleEntity2.setRate(10); + sampleEntity2.setMessage("foo"); + sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); + + repository.save(sampleEntity2); + + // when + long count = repository.countByLocationNear(new Point(45.7806d, 3.0875d), new Distance(2, Metrics.KILOMETERS)); + // then + assertThat(count, is(equalTo(1L))); + } + + private List createSampleEntities(String type, int numberOfEntities) { + List entities = new ArrayList<>(); + for (int i = 0; i < numberOfEntities; i++) { + SampleEntity entity = new SampleEntity(); + entity.setId(randomNumeric(numberOfEntities)); + entity.setAvailable(true); + entity.setMessage("Message"); + entity.setType(type); + entities.add(entity); + } + return entities; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryRestTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryRestTests.java new file mode 100644 index 000000000..5c3de1026 --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryRestTests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 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.repositories; + +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * + * @author Don Wellington + * + */ +@RunWith(SpringRunner.class) +@ContextConfiguration("classpath:custom-method-repository-rest-test.xml") +public class CustomMethodRepositoryRestTests extends CustomMethodRepositoryBaseTests { + @Autowired private ElasticsearchRestTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.putMapping(SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java index d890b4a05..42a1ff426 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java @@ -1,1212 +1,43 @@ -/* - * Copyright 2013-2017 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.repositories; - -import static org.apache.commons.lang.RandomStringUtils.*; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Stream; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.core.geo.GeoPoint; -import org.springframework.data.elasticsearch.entities.SampleEntity; -import org.springframework.data.elasticsearch.repositories.custom.SampleCustomMethodRepository; -import org.springframework.data.geo.Box; -import org.springframework.data.geo.Distance; -import org.springframework.data.geo.Metrics; -import org.springframework.data.geo.Point; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Franck Marchand - * @author Kevin Leturc - * @author Christoph Strobl - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:custom-method-repository-test.xml") -public class CustomMethodRepositoryTests { - - @Autowired private SampleCustomMethodRepository repository; - - @Autowired private ElasticsearchTemplate elasticsearchTemplate; - - @Before - public void before() { - elasticsearchTemplate.deleteIndex(SampleEntity.class); - elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.putMapping(SampleEntity.class); - elasticsearchTemplate.refresh(SampleEntity.class); - } - - @Test - public void shouldExecuteCustomMethod() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("some message"); - repository.save(sampleEntity); - // when - Page page = repository.findByType("test", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForNot() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("some"); - sampleEntity.setMessage("some message"); - repository.save(sampleEntity); - // when - Page page = repository.findByTypeNot("test", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithQuery() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - String searchTerm = "customQuery"; - sampleEntity.setMessage(searchTerm); - repository.save(sampleEntity); - // when - Page page = repository.findByMessage(searchTerm.toLowerCase(), new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithLessThan() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(9); - sampleEntity.setMessage("some message"); - repository.save(sampleEntity); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setRate(20); - sampleEntity2.setMessage("some message"); - repository.save(sampleEntity2); - - // when - Page page = repository.findByRateLessThan(10, new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithBefore() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("some message"); - repository.save(sampleEntity); - - // when - Page page = repository.findByRateBefore(10, new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithAfter() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("some message"); - repository.save(sampleEntity); - - // when - Page page = repository.findByRateAfter(10, new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithLike() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // when - Page page = repository.findByMessageLike("fo", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForStartingWith() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // when - Page page = repository.findByMessageStartingWith("fo", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForEndingWith() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // when - Page page = repository.findByMessageEndingWith("o", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForContains() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // when - Page page = repository.findByMessageContaining("fo", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForIn() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - repository.save(sampleEntity2); - - List ids = Arrays.asList(documentId, documentId2); - - // when - Page page = repository.findByIdIn(ids, new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(2L))); - } - - @Test - public void shouldExecuteCustomMethodForNotIn() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - repository.save(sampleEntity2); - - List ids = Arrays.asList(documentId); - - // when - Page page = repository.findByIdNotIn(ids, new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - assertThat(page.getContent().get(0).getId(), is(documentId2)); - } - - @Test - public void shouldExecuteCustomMethodForTrue() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - // when - Page page = repository.findByAvailableTrue(new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForFalse() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - // when - Page page = repository.findByAvailableFalse(new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodForOrderBy() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("abc"); - sampleEntity.setMessage("test"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // document 2 - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("xyz"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - - // document 3 - String documentId3 = randomNumeric(5); - SampleEntity sampleEntity3 = new SampleEntity(); - sampleEntity3.setId(documentId3); - sampleEntity3.setType("def"); - sampleEntity3.setMessage("foo"); - sampleEntity3.setAvailable(false); - repository.save(sampleEntity3); - - // when - Page page = repository.findByMessageOrderByTypeAsc("foo", new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithBooleanParameter() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - // when - Page page = repository.findByAvailable(false, new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldReturnPageableResultsWithQueryAnnotationExpectedPageSize() { - // given - for (int i = 0; i < 30; i++) { - String documentId = String.valueOf(i); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("message"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - } - // when - Page pageResult = repository.findByMessage("message", new PageRequest(0, 23)); - // then - assertThat(pageResult.getTotalElements(), is(equalTo(30L))); - assertThat(pageResult.getContent().size(), is(equalTo(23))); - } - - @Test - public void shouldReturnPageableResultsWithGivenSortingOrder() { - // given - String documentId = random(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("abc"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("abd"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity2); - - String documentId3 = randomNumeric(5); - SampleEntity sampleEntity3 = new SampleEntity(); - sampleEntity3.setId(documentId3); - sampleEntity3.setMessage("abe"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity3); - // when - Page pageResult = repository.findByMessageContaining("a", - new PageRequest(0, 23, new Sort(new Sort.Order(Sort.Direction.DESC, "message")))); - // then - assertThat(pageResult.getContent().isEmpty(), is(false)); - assertThat(pageResult.getContent().get(0).getMessage(), is(sampleEntity3.getMessage())); - } - - @Test - public void shouldReturnListForMessage() { - // given - String documentId = random(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("abc"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("abd"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity2); - - String documentId3 = randomNumeric(5); - SampleEntity sampleEntity3 = new SampleEntity(); - sampleEntity3.setId(documentId3); - sampleEntity3.setMessage("abe"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity3); - // when - List sampleEntities = repository.findByMessage("abc"); - // then - assertThat(sampleEntities.isEmpty(), is(false)); - assertThat(sampleEntities.size(), is(1)); - } - - @Test - public void shouldExecuteCustomMethodWithGeoPoint() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - // when - Page page = repository.findByLocation(new GeoPoint(45.7806d, 3.0875d), new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithGeoPointAndString() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(48.7806d, 3.0875d)); - - repository.save(sampleEntity); - - // when - Page page = repository.findByLocationAndMessage(new GeoPoint(45.7806d, 3.0875d), "foo", - new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithWithinGeoPoint() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - // when - Page page = repository.findByLocationWithin(new GeoPoint(45.7806d, 3.0875d), "2km", - new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithWithinPoint() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - // when - Page page = repository.findByLocationWithin(new Point(45.7806d, 3.0875d), - new Distance(2, Metrics.KILOMETERS), new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithNearBox() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test2"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("foo"); - sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); - - repository.save(sampleEntity2); - - // when - Page pageAll = repository.findAll(new PageRequest(0, 10)); - // then - assertThat(pageAll, is(notNullValue())); - assertThat(pageAll.getTotalElements(), is(equalTo(2L))); - - // when - Page page = repository.findByLocationNear(new Box(new Point(46d, 3d), new Point(45d, 4d)), - new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldExecuteCustomMethodWithNearPointAndDistance() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - // when - Page page = repository.findByLocationNear(new Point(45.7806d, 3.0875d), - new Distance(2, Metrics.KILOMETERS), new PageRequest(0, 10)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - /* - DATAES-165 - */ - @Test - public void shouldAllowReturningJava8StreamInCustomQuery() { - // given - List entities = createSampleEntities("abc", 30); - repository.saveAll(entities); - - // when - Stream stream = repository.findByType("abc"); - // then - assertThat(stream, is(notNullValue())); - assertThat(stream.count(), is(equalTo(30L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethod() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("some message"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test2"); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByType("test"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForNot() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("some"); - sampleEntity.setMessage("some message"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByTypeNot("test"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithBooleanParameter() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - // when - long count = repository.countByAvailable(false); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithLessThan() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(9); - sampleEntity.setMessage("some message"); - repository.save(sampleEntity); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setRate(20); - sampleEntity2.setMessage("some message"); - repository.save(sampleEntity2); - - // when - long count = repository.countByRateLessThan(10); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithBefore() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("some message"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(20); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByRateBefore(10); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithAfter() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("some message"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(0); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByRateAfter(10); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithLike() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByMessageLike("fo"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForStartingWith() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByMessageStartingWith("fo"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForEndingWith() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByMessageEndingWith("o"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForContains() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("some message"); - - repository.save(sampleEntity2); - - // when - long count = repository.countByMessageContaining("fo"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForIn() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - repository.save(sampleEntity2); - - List ids = Arrays.asList(documentId, documentId2); - - // when - long count = repository.countByIdIn(ids); - // then - assertThat(count, is(equalTo(2L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForNotIn() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - repository.save(sampleEntity2); - - List ids = Arrays.asList(documentId); - - // when - long count = repository.countByIdNotIn(ids); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForTrue() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - // when - long count = repository.countByAvailableTrue(); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodForFalse() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setMessage("foo"); - sampleEntity.setAvailable(true); - repository.save(sampleEntity); - - // given - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setType("test"); - sampleEntity2.setMessage("bar"); - sampleEntity2.setAvailable(false); - repository.save(sampleEntity2); - // when - long count = repository.countByAvailableFalse(); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithWithinGeoPoint() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("foo"); - sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); - - repository.save(sampleEntity2); - - // when - long count = repository.countByLocationWithin(new GeoPoint(45.7806d, 3.0875d), "2km"); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithWithinPoint() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("foo"); - sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); - - repository.save(sampleEntity2); - - // when - long count = repository.countByLocationWithin(new Point(45.7806d, 3.0875d), new Distance(2, Metrics.KILOMETERS)); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithNearBox() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test2"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("foo"); - sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); - - repository.save(sampleEntity2); - - // when - long count = repository.countByLocationNear(new Box(new Point(46d, 3d), new Point(45d, 4d))); - // then - assertThat(count, is(equalTo(1L))); - } - - /* - DATAES-106 - */ - @Test - public void shouldCountCustomMethodWithNearPointAndDistance() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setType("test"); - sampleEntity.setRate(10); - sampleEntity.setMessage("foo"); - sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d)); - - repository.save(sampleEntity); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("test"); - sampleEntity2.setRate(10); - sampleEntity2.setMessage("foo"); - sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d)); - - repository.save(sampleEntity2); - - // when - long count = repository.countByLocationNear(new Point(45.7806d, 3.0875d), new Distance(2, Metrics.KILOMETERS)); - // then - assertThat(count, is(equalTo(1L))); - } - - private List createSampleEntities(String type, int numberOfEntities) { - List entities = new ArrayList<>(); - for (int i = 0; i < numberOfEntities; i++) { - SampleEntity entity = new SampleEntity(); - entity.setId(randomNumeric(numberOfEntities)); - entity.setAvailable(true); - entity.setMessage("Message"); - entity.setType(type); - entities.add(entity); - } - return entities; - } -} +/* + * Copyright 2018 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.repositories; + +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * + * @author Don Wellington + * + */ +@RunWith(SpringRunner.class) +@ContextConfiguration("classpath:custom-method-repository-test.xml") +public class CustomMethodRepositoryTests extends CustomMethodRepositoryBaseTests { + @Autowired private ElasticsearchTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.putMapping(SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + } +} diff --git a/src/test/resources/custom-method-repository-rest-test.xml b/src/test/resources/custom-method-repository-rest-test.xml new file mode 100644 index 000000000..9412130b6 --- /dev/null +++ b/src/test/resources/custom-method-repository-rest-test.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/elasticsearch-rest-template-test.xml b/src/test/resources/elasticsearch-rest-template-test.xml new file mode 100644 index 000000000..500592010 --- /dev/null +++ b/src/test/resources/elasticsearch-rest-template-test.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/infrastructure.xml b/src/test/resources/infrastructure.xml index f656d6892..23f181426 100644 --- a/src/test/resources/infrastructure.xml +++ b/src/test/resources/infrastructure.xml @@ -6,7 +6,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> diff --git a/src/test/resources/org/springframework/data/elasticsearch/config/namespace.xml b/src/test/resources/org/springframework/data/elasticsearch/config/namespace.xml index 946270894..dce9784de 100644 --- a/src/test/resources/org/springframework/data/elasticsearch/config/namespace.xml +++ b/src/test/resources/org/springframework/data/elasticsearch/config/namespace.xml @@ -2,7 +2,7 @@ + + \ No newline at end of file diff --git a/src/test/resources/test-home-dir/modules/lang-expression/plugin-descriptor.properties b/src/test/resources/test-home-dir/modules/lang-expression/plugin-descriptor.properties index 6ed2760a4..fdae6037d 100644 --- a/src/test/resources/test-home-dir/modules/lang-expression/plugin-descriptor.properties +++ b/src/test/resources/test-home-dir/modules/lang-expression/plugin-descriptor.properties @@ -37,7 +37,7 @@ classname=org.elasticsearch.script.expression.ExpressionPlugin java.version=1.8 # # 'elasticsearch.version': version of elasticsearch compiled against -elasticsearch.version=6.2.2 +elasticsearch.version=6.3.0 ### optional elements for plugins: # # 'extended.plugins': other plugins this plugin extends through SPI @@ -47,4 +47,4 @@ extended.plugins= has.native.controller=false # # 'requires.keystore': whether or not the plugin needs the elasticsearch keystore be created -requires.keystore=false +#requires.keystore=false