diff --git a/.gitignore b/.gitignore index 20068080..ce5bc267 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,21 @@ -atlassian-ide-plugin.xml - -## Ignore svn files -.svn - -## ignore any target dir -target - -##ignore only top level data dir - local node data files for unit tests -/data - -## Ignore project files created by Eclipse -.settings -.project -.classpath - -## Ignore project files created by IntelliJ IDEA -*.iml -*.ipr -*.iws -.idea +atlassian-ide-plugin.xml + +## Ignore svn files +.svn + +## ignore any target dir +target + +##ignore only top level data dir - local node data files for unit tests +/data + +## Ignore project files created by Eclipse +.settings +.project +.classpath + +## Ignore project files created by IntelliJ IDEA +*.iml +*.ipr +*.iws +.idea diff --git a/src/main/java/org/springframework/data/elasticsearch/ElasticsearchException.java b/src/main/java/org/springframework/data/elasticsearch/ElasticsearchException.java index b3b0ddb2..88ea9964 100644 --- a/src/main/java/org/springframework/data/elasticsearch/ElasticsearchException.java +++ b/src/main/java/org/springframework/data/elasticsearch/ElasticsearchException.java @@ -1,51 +1,51 @@ -/* - * 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; - -import java.util.Map; - -/** - * ElasticsearchException - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class ElasticsearchException extends RuntimeException { - - private Map failedDocuments; - - public ElasticsearchException(String message) { - super(message); - } - - public ElasticsearchException(String message, Throwable cause) { - super(message, cause); - } - - public ElasticsearchException(String message, Throwable cause, Map failedDocuments) { - super(message, cause); - this.failedDocuments = failedDocuments; - } - - public ElasticsearchException(String message, Map failedDocuments) { - super(message); - this.failedDocuments = failedDocuments; - } - - public Map getFailedDocuments() { - return failedDocuments; - } -} +/* + * 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; + +import java.util.Map; + +/** + * ElasticsearchException + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class ElasticsearchException extends RuntimeException { + + private Map failedDocuments; + + public ElasticsearchException(String message) { + super(message); + } + + public ElasticsearchException(String message, Throwable cause) { + super(message, cause); + } + + public ElasticsearchException(String message, Throwable cause, Map failedDocuments) { + super(message, cause); + this.failedDocuments = failedDocuments; + } + + public ElasticsearchException(String message, Map failedDocuments) { + super(message); + this.failedDocuments = failedDocuments; + } + + public Map getFailedDocuments() { + return failedDocuments; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java index e494afaa..5e0712b1 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java @@ -1,51 +1,51 @@ -/* - * 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.annotations; - -import java.lang.annotation.*; - -import org.springframework.data.annotation.Persistent; - -/** - * Document - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Mason Chan - */ - -@Persistent -@Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Document { - - String indexName(); - - String type() default ""; - - boolean useServerConfiguration() default false; - - short shards() default 5; - - short replicas() default 1; - - String refreshInterval() default "1s"; - - String indexStoreType() default "fs"; - - boolean createIndex() default true; -} +/* + * 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.annotations; + +import java.lang.annotation.*; + +import org.springframework.data.annotation.Persistent; + +/** + * Document + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Mason Chan + */ + +@Persistent +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Document { + + String indexName(); + + String type() default ""; + + boolean useServerConfiguration() default false; + + short shards() default 5; + + short replicas() default 1; + + String refreshInterval() default "1s"; + + String indexStoreType() default "fs"; + + boolean createIndex() default true; +} diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java index 29dcdf2f..9a69ff60 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java @@ -1,56 +1,56 @@ -/* - * 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.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - * @author Jonathan Yan - * @author Jakub Vavrik - * @author Kevin Leturc - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Documented -@Inherited -public @interface Field { - - FieldType type() default FieldType.Auto; - - FieldIndex index() default FieldIndex.analyzed; - - DateFormat format() default DateFormat.none; - - String pattern() default ""; - - boolean store() default false; - - String searchAnalyzer() default ""; - - String analyzer() default ""; - - String[] ignoreFields() default {}; - - boolean includeInParent() default false; -} +/* + * 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.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + * @author Jonathan Yan + * @author Jakub Vavrik + * @author Kevin Leturc + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Documented +@Inherited +public @interface Field { + + FieldType type() default FieldType.Auto; + + FieldIndex index() default FieldIndex.analyzed; + + DateFormat format() default DateFormat.none; + + String pattern() default ""; + + boolean store() default false; + + String searchAnalyzer() default ""; + + String analyzer() default ""; + + String[] ignoreFields() default {}; + + boolean includeInParent() default false; +} diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java index 3c91cdf2..d1fc2f3f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Query.java @@ -1,45 +1,45 @@ -/* - * 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.annotations; - -import java.lang.annotation.*; - -/** - * Query - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -@Documented -public @interface Query { - - /** - * Elasticsearch query to be used when executing query. May contain placeholders eg. ?0 - * - * @return - */ - String value() default ""; - - /** - * Named Query Named looked up by repository. - * - * @return - */ - String name() default ""; -} +/* + * 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.annotations; + +import java.lang.annotation.*; + +/** + * Query + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Documented +public @interface Query { + + /** + * Elasticsearch query to be used when executing query. May contain placeholders eg. ?0 + * + * @return + */ + String value() default ""; + + /** + * Named Query Named looked up by repository. + * + * @return + */ + String name() default ""; +} diff --git a/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java b/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java index fc8dd259..963a3043 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/NodeClientFactoryBean.java @@ -1,127 +1,127 @@ -/* - * Copyright 2015 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.elasticsearch.node.NodeBuilder.*; - -import java.io.InputStream; -import org.apache.commons.lang.StringUtils; -import org.elasticsearch.client.Client; -import org.elasticsearch.client.node.NodeClient; -import org.elasticsearch.common.settings.Settings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; - -/** - * NodeClientFactoryBean - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class NodeClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean { - - private static final Logger logger = LoggerFactory.getLogger(NodeClientFactoryBean.class); - private boolean local; - private boolean enableHttp; - private String clusterName; - private NodeClient nodeClient; - private String pathData; - private String pathHome; - private String pathConfiguration; - - NodeClientFactoryBean() { - } - - public NodeClientFactoryBean(boolean local) { - this.local = local; - } - - @Override - public NodeClient getObject() throws Exception { - return nodeClient; - } - - @Override - public Class getObjectType() { - return NodeClient.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - @Override - public void afterPropertiesSet() throws Exception { - nodeClient = (NodeClient) nodeBuilder().settings(Settings.builder().put(loadConfig()) - .put("http.enabled", String.valueOf(this.enableHttp)) - .put("path.home", this.pathHome) - .put("path.data", this.pathData)) - .clusterName(this.clusterName).local(this.local).node() - .client(); - } - - private Settings loadConfig() { - if (StringUtils.isNotBlank(pathConfiguration)) { - InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration); - if (stream != null) { - return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration)).build(); - } - logger.error(String.format("Unable to read node configuration from file [%s]", pathConfiguration)); - } - return Settings.builder().build(); - } - - public void setLocal(boolean local) { - this.local = local; - } - - public void setEnableHttp(boolean enableHttp) { - this.enableHttp = enableHttp; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public void setPathData(String pathData) { - this.pathData = pathData; - } - - public void setPathHome(String pathHome) { - this.pathHome = pathHome; - } - - public void setPathConfiguration(String configuration) { - this.pathConfiguration = configuration; - } - - @Override - public void destroy() throws Exception { - try { - logger.info("Closing elasticSearch client"); - if (nodeClient != null) { - nodeClient.close(); - } - } catch (final Exception e) { - logger.error("Error closing ElasticSearch client: ", e); - } - } -} +/* + * Copyright 2015 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.elasticsearch.node.NodeBuilder.*; + +import java.io.InputStream; +import org.apache.commons.lang.StringUtils; +import org.elasticsearch.client.Client; +import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.settings.Settings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +/** + * NodeClientFactoryBean + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class NodeClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean { + + private static final Logger logger = LoggerFactory.getLogger(NodeClientFactoryBean.class); + private boolean local; + private boolean enableHttp; + private String clusterName; + private NodeClient nodeClient; + private String pathData; + private String pathHome; + private String pathConfiguration; + + NodeClientFactoryBean() { + } + + public NodeClientFactoryBean(boolean local) { + this.local = local; + } + + @Override + public NodeClient getObject() throws Exception { + return nodeClient; + } + + @Override + public Class getObjectType() { + return NodeClient.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public void afterPropertiesSet() throws Exception { + nodeClient = (NodeClient) nodeBuilder().settings(Settings.builder().put(loadConfig()) + .put("http.enabled", String.valueOf(this.enableHttp)) + .put("path.home", this.pathHome) + .put("path.data", this.pathData)) + .clusterName(this.clusterName).local(this.local).node() + .client(); + } + + private Settings loadConfig() { + if (StringUtils.isNotBlank(pathConfiguration)) { + InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration); + if (stream != null) { + return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration)).build(); + } + logger.error(String.format("Unable to read node configuration from file [%s]", pathConfiguration)); + } + return Settings.builder().build(); + } + + public void setLocal(boolean local) { + this.local = local; + } + + public void setEnableHttp(boolean enableHttp) { + this.enableHttp = enableHttp; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public void setPathData(String pathData) { + this.pathData = pathData; + } + + public void setPathHome(String pathHome) { + this.pathHome = pathHome; + } + + public void setPathConfiguration(String configuration) { + this.pathConfiguration = configuration; + } + + @Override + public void destroy() throws Exception { + try { + logger.info("Closing elasticSearch client"); + if (nodeClient != null) { + nodeClient.close(); + } + } catch (final Exception e) { + logger.error("Error closing ElasticSearch client: ", e); + } + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/client/TransportClientFactoryBean.java b/src/main/java/org/springframework/data/elasticsearch/client/TransportClientFactoryBean.java index 881d0f8f..84bbcc31 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/TransportClientFactoryBean.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/TransportClientFactoryBean.java @@ -1,154 +1,154 @@ -/* - * 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.client; - -import static org.apache.commons.lang.StringUtils.*; - -import java.net.InetAddress; -import java.util.Properties; - -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.transport.InetSocketTransportAddress; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * TransportClientFactoryBean - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Jakub Vavrik - * @author Piotr Betkier - */ - -public class TransportClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean { - - private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class); - private String clusterNodes = "127.0.0.1:9300"; - private String clusterName = "elasticsearch"; - private Boolean clientTransportSniff = true; - private Boolean clientIgnoreClusterName = Boolean.FALSE; - private String clientPingTimeout = "5s"; - private String clientNodesSamplerInterval = "5s"; - private TransportClient client; - private Properties properties; - static final String COLON = ":"; - static final String COMMA = ","; - - @Override - public void destroy() throws Exception { - try { - logger.info("Closing elasticSearch client"); - if (client != null) { - client.close(); - } - } catch (final Exception e) { - logger.error("Error closing ElasticSearch client: ", e); - } - } - - @Override - public TransportClient getObject() throws Exception { - return client; - } - - @Override - public Class getObjectType() { - return TransportClient.class; - } - - @Override - public boolean isSingleton() { - return false; - } - - @Override - public void afterPropertiesSet() throws Exception { - buildClient(); - } - - protected void buildClient() throws Exception { - client = TransportClient.builder().settings(settings()).build(); - Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing."); - for (String clusterNode : split(clusterNodes, COMMA)) { - String hostName = substringBeforeLast(clusterNode, COLON); - String port = substringAfterLast(clusterNode, COLON); - Assert.hasText(hostName, "[Assertion failed] missing host name in 'clusterNodes'"); - Assert.hasText(port, "[Assertion failed] missing port in 'clusterNodes'"); - logger.info("adding transport node : " + clusterNode); - client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port))); - } - client.connectedNodes(); - } - - private Settings settings() { - if (properties != null) { - return Settings.builder().put(properties).build(); - } - return Settings.builder() - .put("cluster.name", clusterName) - .put("client.transport.sniff", clientTransportSniff) - .put("client.transport.ignore_cluster_name", clientIgnoreClusterName) - .put("client.transport.ping_timeout", clientPingTimeout) - .put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval) - .build(); - } - - public void setClusterNodes(String clusterNodes) { - this.clusterNodes = clusterNodes; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public void setClientTransportSniff(Boolean clientTransportSniff) { - this.clientTransportSniff = clientTransportSniff; - } - - public String getClientNodesSamplerInterval() { - return clientNodesSamplerInterval; - } - - public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) { - this.clientNodesSamplerInterval = clientNodesSamplerInterval; - } - - public String getClientPingTimeout() { - return clientPingTimeout; - } - - public void setClientPingTimeout(String clientPingTimeout) { - this.clientPingTimeout = clientPingTimeout; - } - - public Boolean getClientIgnoreClusterName() { - return clientIgnoreClusterName; - } - - public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) { - this.clientIgnoreClusterName = clientIgnoreClusterName; - } - - public void setProperties(Properties properties) { - this.properties = properties; - } -} +/* + * 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.client; + +import static org.apache.commons.lang.StringUtils.*; + +import java.net.InetAddress; +import java.util.Properties; + +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.InetSocketTransportAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * TransportClientFactoryBean + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Jakub Vavrik + * @author Piotr Betkier + */ + +public class TransportClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean { + + private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class); + private String clusterNodes = "127.0.0.1:9300"; + private String clusterName = "elasticsearch"; + private Boolean clientTransportSniff = true; + private Boolean clientIgnoreClusterName = Boolean.FALSE; + private String clientPingTimeout = "5s"; + private String clientNodesSamplerInterval = "5s"; + private TransportClient client; + private Properties properties; + static final String COLON = ":"; + static final String COMMA = ","; + + @Override + public void destroy() throws Exception { + try { + logger.info("Closing elasticSearch client"); + if (client != null) { + client.close(); + } + } catch (final Exception e) { + logger.error("Error closing ElasticSearch client: ", e); + } + } + + @Override + public TransportClient getObject() throws Exception { + return client; + } + + @Override + public Class getObjectType() { + return TransportClient.class; + } + + @Override + public boolean isSingleton() { + return false; + } + + @Override + public void afterPropertiesSet() throws Exception { + buildClient(); + } + + protected void buildClient() throws Exception { + client = TransportClient.builder().settings(settings()).build(); + Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing."); + for (String clusterNode : split(clusterNodes, COMMA)) { + String hostName = substringBeforeLast(clusterNode, COLON); + String port = substringAfterLast(clusterNode, COLON); + Assert.hasText(hostName, "[Assertion failed] missing host name in 'clusterNodes'"); + Assert.hasText(port, "[Assertion failed] missing port in 'clusterNodes'"); + logger.info("adding transport node : " + clusterNode); + client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port))); + } + client.connectedNodes(); + } + + private Settings settings() { + if (properties != null) { + return Settings.builder().put(properties).build(); + } + return Settings.builder() + .put("cluster.name", clusterName) + .put("client.transport.sniff", clientTransportSniff) + .put("client.transport.ignore_cluster_name", clientIgnoreClusterName) + .put("client.transport.ping_timeout", clientPingTimeout) + .put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval) + .build(); + } + + public void setClusterNodes(String clusterNodes) { + this.clusterNodes = clusterNodes; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public void setClientTransportSniff(Boolean clientTransportSniff) { + this.clientTransportSniff = clientTransportSniff; + } + + public String getClientNodesSamplerInterval() { + return clientNodesSamplerInterval; + } + + public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) { + this.clientNodesSamplerInterval = clientNodesSamplerInterval; + } + + public String getClientPingTimeout() { + return clientPingTimeout; + } + + public void setClientPingTimeout(String clientPingTimeout) { + this.clientPingTimeout = clientPingTimeout; + } + + public Boolean getClientIgnoreClusterName() { + return clientIgnoreClusterName; + } + + public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) { + this.clientIgnoreClusterName = clientIgnoreClusterName; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } +} 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 bfb65686..315020c6 100644 --- a/src/main/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandler.java +++ b/src/main/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandler.java @@ -1,41 +1,41 @@ -/* - * 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 org.springframework.beans.factory.xml.NamespaceHandlerSupport; -import org.springframework.data.elasticsearch.repository.config.ElasticsearchRepositoryConfigExtension; -import org.springframework.data.repository.config.RepositoryBeanDefinitionParser; -import org.springframework.data.repository.config.RepositoryConfigurationExtension; - -/** - * ElasticsearchNamespaceHandler - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class ElasticsearchNamespaceHandler extends NamespaceHandlerSupport { - - @Override - public void init() { - RepositoryConfigurationExtension extension = new ElasticsearchRepositoryConfigExtension(); - RepositoryBeanDefinitionParser parser = new RepositoryBeanDefinitionParser(extension); - - registerBeanDefinitionParser("repositories", parser); - registerBeanDefinitionParser("node-client", new NodeClientBeanDefinitionParser()); - registerBeanDefinitionParser("transport-client", new TransportClientBeanDefinitionParser()); - } -} +/* + * 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 org.springframework.beans.factory.xml.NamespaceHandlerSupport; +import org.springframework.data.elasticsearch.repository.config.ElasticsearchRepositoryConfigExtension; +import org.springframework.data.repository.config.RepositoryBeanDefinitionParser; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +/** + * ElasticsearchNamespaceHandler + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class ElasticsearchNamespaceHandler extends NamespaceHandlerSupport { + + @Override + public void init() { + RepositoryConfigurationExtension extension = new ElasticsearchRepositoryConfigExtension(); + RepositoryBeanDefinitionParser parser = new RepositoryBeanDefinitionParser(extension); + + registerBeanDefinitionParser("repositories", parser); + registerBeanDefinitionParser("node-client", new NodeClientBeanDefinitionParser()); + registerBeanDefinitionParser("transport-client", new TransportClientBeanDefinitionParser()); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/config/NodeClientBeanDefinitionParser.java b/src/main/java/org/springframework/data/elasticsearch/config/NodeClientBeanDefinitionParser.java index b2878040..96cad2e1 100644 --- a/src/main/java/org/springframework/data/elasticsearch/config/NodeClientBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/elasticsearch/config/NodeClientBeanDefinitionParser.java @@ -1,57 +1,57 @@ -/* - * Copyright 2015 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.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.data.elasticsearch.client.NodeClientFactoryBean; -import org.w3c.dom.Element; - -/** - * NodeClientBeanDefinitionParser - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class NodeClientBeanDefinitionParser extends AbstractBeanDefinitionParser { - - @Override - protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(NodeClientFactoryBean.class); - setLocalSettings(element, builder); - return getSourcedBeanDefinition(builder, element, parserContext); - } - - private void setLocalSettings(Element element, BeanDefinitionBuilder builder) { - builder.addPropertyValue("local", Boolean.valueOf(element.getAttribute("local"))); - builder.addPropertyValue("clusterName", element.getAttribute("cluster-name")); - builder.addPropertyValue("enableHttp", Boolean.valueOf(element.getAttribute("http-enabled"))); - builder.addPropertyValue("pathData", element.getAttribute("path-data")); - builder.addPropertyValue("pathHome", element.getAttribute("path-home")); - builder.addPropertyValue("pathConfiguration", element.getAttribute("path-configuration")); - } - - private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source, - ParserContext context) { - AbstractBeanDefinition definition = builder.getBeanDefinition(); - definition.setSource(context.extractSource(source)); - return definition; - } -} +/* + * Copyright 2015 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.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.elasticsearch.client.NodeClientFactoryBean; +import org.w3c.dom.Element; + +/** + * NodeClientBeanDefinitionParser + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class NodeClientBeanDefinitionParser extends AbstractBeanDefinitionParser { + + @Override + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(NodeClientFactoryBean.class); + setLocalSettings(element, builder); + return getSourcedBeanDefinition(builder, element, parserContext); + } + + private void setLocalSettings(Element element, BeanDefinitionBuilder builder) { + builder.addPropertyValue("local", Boolean.valueOf(element.getAttribute("local"))); + builder.addPropertyValue("clusterName", element.getAttribute("cluster-name")); + builder.addPropertyValue("enableHttp", Boolean.valueOf(element.getAttribute("http-enabled"))); + builder.addPropertyValue("pathData", element.getAttribute("path-data")); + builder.addPropertyValue("pathHome", element.getAttribute("path-home")); + builder.addPropertyValue("pathConfiguration", element.getAttribute("path-configuration")); + } + + 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/config/TransportClientBeanDefinitionParser.java b/src/main/java/org/springframework/data/elasticsearch/config/TransportClientBeanDefinitionParser.java index 54679fa3..200f830c 100644 --- a/src/main/java/org/springframework/data/elasticsearch/config/TransportClientBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/elasticsearch/config/TransportClientBeanDefinitionParser.java @@ -1,56 +1,56 @@ -/* - * 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 org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.data.elasticsearch.client.TransportClientFactoryBean; -import org.w3c.dom.Element; - -/** - * TransportClientBeanDefinitionParser - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class TransportClientBeanDefinitionParser extends AbstractBeanDefinitionParser { - - @Override - protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TransportClientFactoryBean.class); - setConfigurations(element, builder); - return getSourcedBeanDefinition(builder, element, parserContext); - } - - private void setConfigurations(Element element, BeanDefinitionBuilder builder) { - builder.addPropertyValue("clusterNodes", element.getAttribute("cluster-nodes")); - builder.addPropertyValue("clusterName", element.getAttribute("cluster-name")); - builder.addPropertyValue("clientTransportSniff", Boolean.valueOf(element.getAttribute("client-transport-sniff"))); - builder.addPropertyValue("clientIgnoreClusterName", Boolean.valueOf(element.getAttribute("client-transport-ignore-cluster-name"))); - builder.addPropertyValue("clientPingTimeout", element.getAttribute("client-transport-ping-timeout")); - builder.addPropertyValue("clientNodesSamplerInterval", element.getAttribute("client-transport-nodes-sampler-interval")); - } - - private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source, - ParserContext context) { - AbstractBeanDefinition definition = builder.getBeanDefinition(); - definition.setSource(context.extractSource(source)); - return definition; - } -} +/* + * 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 org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.elasticsearch.client.TransportClientFactoryBean; +import org.w3c.dom.Element; + +/** + * TransportClientBeanDefinitionParser + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class TransportClientBeanDefinitionParser extends AbstractBeanDefinitionParser { + + @Override + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TransportClientFactoryBean.class); + setConfigurations(element, builder); + return getSourcedBeanDefinition(builder, element, parserContext); + } + + private void setConfigurations(Element element, BeanDefinitionBuilder builder) { + builder.addPropertyValue("clusterNodes", element.getAttribute("cluster-nodes")); + builder.addPropertyValue("clusterName", element.getAttribute("cluster-name")); + builder.addPropertyValue("clientTransportSniff", Boolean.valueOf(element.getAttribute("client-transport-sniff"))); + builder.addPropertyValue("clientIgnoreClusterName", Boolean.valueOf(element.getAttribute("client-transport-ignore-cluster-name"))); + builder.addPropertyValue("clientPingTimeout", element.getAttribute("client-transport-ping-timeout")); + builder.addPropertyValue("clientNodesSamplerInterval", element.getAttribute("client-transport-nodes-sampler-interval")); + } + + 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/CriteriaQueryProcessor.java b/src/main/java/org/springframework/data/elasticsearch/core/CriteriaQueryProcessor.java index e0207d90..659a5ac5 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/CriteriaQueryProcessor.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/CriteriaQueryProcessor.java @@ -1,210 +1,210 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core; - -import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.springframework.data.elasticsearch.core.query.Criteria.*; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; - -import org.apache.lucene.queryparser.flexible.core.util.StringUtils; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.BoostableQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.index.query.QueryStringQueryBuilder; -import org.springframework.data.elasticsearch.core.query.Criteria; -import org.springframework.util.Assert; - -/** - * CriteriaQueryProcessor - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Franck Marchand - * @author Artur Konczak - */ -class CriteriaQueryProcessor { - - - QueryBuilder createQueryFromCriteria(Criteria criteria) { - if (criteria == null) - return null; - - List shouldQueryBuilderList = new LinkedList(); - List mustNotQueryBuilderList = new LinkedList(); - List mustQueryBuilderList = new LinkedList(); - - ListIterator chainIterator = criteria.getCriteriaChain().listIterator(); - - QueryBuilder firstQuery = null; - boolean negateFirstQuery = false; - - while (chainIterator.hasNext()) { - Criteria chainedCriteria = chainIterator.next(); - QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria); - if (queryFragmentForCriteria != null) { - if (firstQuery == null) { - firstQuery = queryFragmentForCriteria; - negateFirstQuery = chainedCriteria.isNegating(); - continue; - } - if (chainedCriteria.isOr()) { - shouldQueryBuilderList.add(queryFragmentForCriteria); - } else if (chainedCriteria.isNegating()) { - mustNotQueryBuilderList.add(queryFragmentForCriteria); - } else { - mustQueryBuilderList.add(queryFragmentForCriteria); - } - } - } - - if (firstQuery != null) { - if (!shouldQueryBuilderList.isEmpty() && mustNotQueryBuilderList.isEmpty() && mustQueryBuilderList.isEmpty()) { - shouldQueryBuilderList.add(0, firstQuery); - } else { - if (negateFirstQuery) { - mustNotQueryBuilderList.add(0, firstQuery); - } else { - mustQueryBuilderList.add(0, firstQuery); - } - } - } - - BoolQueryBuilder query = null; - - if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) { - - query = boolQuery(); - - for (QueryBuilder qb : shouldQueryBuilderList) { - query.should(qb); - } - for (QueryBuilder qb : mustNotQueryBuilderList) { - query.mustNot(qb); - } - for (QueryBuilder qb : mustQueryBuilderList) { - query.must(qb); - } - } - - return query; - } - - - private QueryBuilder createQueryFragmentForCriteria(Criteria chainedCriteria) { - if (chainedCriteria.getQueryCriteriaEntries().isEmpty()) - return null; - - Iterator it = chainedCriteria.getQueryCriteriaEntries().iterator(); - boolean singeEntryCriteria = (chainedCriteria.getQueryCriteriaEntries().size() == 1); - - String fieldName = chainedCriteria.getField().getName(); - Assert.notNull(fieldName, "Unknown field"); - QueryBuilder query = null; - - if (singeEntryCriteria) { - Criteria.CriteriaEntry entry = it.next(); - query = processCriteriaEntry(entry, fieldName); - } else { - query = boolQuery(); - while (it.hasNext()) { - Criteria.CriteriaEntry entry = it.next(); - ((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName)); - } - } - - addBoost(query, chainedCriteria.getBoost()); - return query; - } - - - private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) { - Object value = entry.getValue(); - if (value == null) { - return null; - } - OperationKey key = entry.getKey(); - QueryBuilder query = null; - - String searchText = StringUtils.toString(value); - - Iterable collection = null; - - switch (key) { - case EQUALS: - query = queryStringQuery(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND); - break; - case CONTAINS: - query = queryStringQuery("*" + searchText + "*").field(fieldName).analyzeWildcard(true); - break; - case STARTS_WITH: - query = queryStringQuery(searchText + "*").field(fieldName).analyzeWildcard(true); - break; - case ENDS_WITH: - query = queryStringQuery("*" + searchText).field(fieldName).analyzeWildcard(true); - break; - case EXPRESSION: - query = queryStringQuery(searchText).field(fieldName); - break; - case LESS_EQUAL: - query = rangeQuery(fieldName).lte(value); - break; - case GREATER_EQUAL: - query = rangeQuery(fieldName).gte(value); - break; - case BETWEEN: - Object[] ranges = (Object[]) value; - query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]); - break; - case LESS: - query = rangeQuery(fieldName).lt(value); - break; - case GREATER: - query = rangeQuery(fieldName).gt(value); - break; - case FUZZY: - query = fuzzyQuery(fieldName, searchText); - break; - case IN: - query = boolQuery(); - collection = (Iterable) value; - for (Object item : collection) { - ((BoolQueryBuilder) query).should(queryStringQuery(item.toString()).field(fieldName)); - } - break; - case NOT_IN: - query = boolQuery(); - collection = (Iterable) value; - for (Object item : collection) { - ((BoolQueryBuilder) query).mustNot(queryStringQuery(item.toString()).field(fieldName)); - } - break; - } - return query; - } - - private void addBoost(QueryBuilder query, float boost) { - if (Float.isNaN(boost)) { - return; - } - if (query instanceof BoostableQueryBuilder) { - ((BoostableQueryBuilder) query).boost(boost); - } - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.springframework.data.elasticsearch.core.query.Criteria.*; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import org.apache.lucene.queryparser.flexible.core.util.StringUtils; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.BoostableQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryStringQueryBuilder; +import org.springframework.data.elasticsearch.core.query.Criteria; +import org.springframework.util.Assert; + +/** + * CriteriaQueryProcessor + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Franck Marchand + * @author Artur Konczak + */ +class CriteriaQueryProcessor { + + + QueryBuilder createQueryFromCriteria(Criteria criteria) { + if (criteria == null) + return null; + + List shouldQueryBuilderList = new LinkedList(); + List mustNotQueryBuilderList = new LinkedList(); + List mustQueryBuilderList = new LinkedList(); + + ListIterator chainIterator = criteria.getCriteriaChain().listIterator(); + + QueryBuilder firstQuery = null; + boolean negateFirstQuery = false; + + while (chainIterator.hasNext()) { + Criteria chainedCriteria = chainIterator.next(); + QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria); + if (queryFragmentForCriteria != null) { + if (firstQuery == null) { + firstQuery = queryFragmentForCriteria; + negateFirstQuery = chainedCriteria.isNegating(); + continue; + } + if (chainedCriteria.isOr()) { + shouldQueryBuilderList.add(queryFragmentForCriteria); + } else if (chainedCriteria.isNegating()) { + mustNotQueryBuilderList.add(queryFragmentForCriteria); + } else { + mustQueryBuilderList.add(queryFragmentForCriteria); + } + } + } + + if (firstQuery != null) { + if (!shouldQueryBuilderList.isEmpty() && mustNotQueryBuilderList.isEmpty() && mustQueryBuilderList.isEmpty()) { + shouldQueryBuilderList.add(0, firstQuery); + } else { + if (negateFirstQuery) { + mustNotQueryBuilderList.add(0, firstQuery); + } else { + mustQueryBuilderList.add(0, firstQuery); + } + } + } + + BoolQueryBuilder query = null; + + if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) { + + query = boolQuery(); + + for (QueryBuilder qb : shouldQueryBuilderList) { + query.should(qb); + } + for (QueryBuilder qb : mustNotQueryBuilderList) { + query.mustNot(qb); + } + for (QueryBuilder qb : mustQueryBuilderList) { + query.must(qb); + } + } + + return query; + } + + + private QueryBuilder createQueryFragmentForCriteria(Criteria chainedCriteria) { + if (chainedCriteria.getQueryCriteriaEntries().isEmpty()) + return null; + + Iterator it = chainedCriteria.getQueryCriteriaEntries().iterator(); + boolean singeEntryCriteria = (chainedCriteria.getQueryCriteriaEntries().size() == 1); + + String fieldName = chainedCriteria.getField().getName(); + Assert.notNull(fieldName, "Unknown field"); + QueryBuilder query = null; + + if (singeEntryCriteria) { + Criteria.CriteriaEntry entry = it.next(); + query = processCriteriaEntry(entry, fieldName); + } else { + query = boolQuery(); + while (it.hasNext()) { + Criteria.CriteriaEntry entry = it.next(); + ((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName)); + } + } + + addBoost(query, chainedCriteria.getBoost()); + return query; + } + + + private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) { + Object value = entry.getValue(); + if (value == null) { + return null; + } + OperationKey key = entry.getKey(); + QueryBuilder query = null; + + String searchText = StringUtils.toString(value); + + Iterable collection = null; + + switch (key) { + case EQUALS: + query = queryStringQuery(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND); + break; + case CONTAINS: + query = queryStringQuery("*" + searchText + "*").field(fieldName).analyzeWildcard(true); + break; + case STARTS_WITH: + query = queryStringQuery(searchText + "*").field(fieldName).analyzeWildcard(true); + break; + case ENDS_WITH: + query = queryStringQuery("*" + searchText).field(fieldName).analyzeWildcard(true); + break; + case EXPRESSION: + query = queryStringQuery(searchText).field(fieldName); + break; + case LESS_EQUAL: + query = rangeQuery(fieldName).lte(value); + break; + case GREATER_EQUAL: + query = rangeQuery(fieldName).gte(value); + break; + case BETWEEN: + Object[] ranges = (Object[]) value; + query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]); + break; + case LESS: + query = rangeQuery(fieldName).lt(value); + break; + case GREATER: + query = rangeQuery(fieldName).gt(value); + break; + case FUZZY: + query = fuzzyQuery(fieldName, searchText); + break; + case IN: + query = boolQuery(); + collection = (Iterable) value; + for (Object item : collection) { + ((BoolQueryBuilder) query).should(queryStringQuery(item.toString()).field(fieldName)); + } + break; + case NOT_IN: + query = boolQuery(); + collection = (Iterable) value; + for (Object item : collection) { + ((BoolQueryBuilder) query).mustNot(queryStringQuery(item.toString()).field(fieldName)); + } + break; + } + return query; + } + + private void addBoost(QueryBuilder query, float boost) { + if (Float.isNaN(boost)) { + return; + } + if (query instanceof BoostableQueryBuilder) { + ((BoostableQueryBuilder) query).boost(boost); + } + } +} 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 26a1dda3..9c0e054f 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java @@ -1,603 +1,603 @@ -/* - * 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.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 scroll id for criteria query - * - * @param query The criteria query. - * @param scrollTimeInMillis The time in millisecond for scroll feature - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. - * @param noFields The no fields support - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. - * @return The scan id for input query. - */ - String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields); - - /** - * Returns scroll id for criteria query - * - * @param query The criteria query. - * @param scrollTimeInMillis The time in millisecond for scroll feature - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. - * @param noFields The no fields support - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. - * @param clazz The class of entity to retrieve. - * @param The type of entity to retrieve. - * @return The scan id for input query. - */ - String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields, Class clazz); - - /** - * Returns scroll id for scan 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 noFields The no fields support - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. - * @return The scan id for input query. - */ - String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields); - - /** - * Returns scroll id for scan 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 noFields The no fields support - * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. - * @param clazz The class of entity to retrieve. - * @param The type of entity to retrieve. - * @return The scan id for input query. - */ - String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields, Class clazz); - - /** - * Scrolls the results for give scroll id - * - * @param scrollId - * @param scrollTimeInMillis - * @param clazz - * @param - * @return - */ - Page scroll(String scrollId, long scrollTimeInMillis, Class clazz); - - /** - * Scrolls the results for give scroll id using custom result mapper - * - * @param scrollId - * @param scrollTimeInMillis - * @param mapper - * @param - * @return - */ - Page scroll(String scrollId, long scrollTimeInMillis, 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-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.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 scroll id for criteria query + * + * @param query The criteria query. + * @param scrollTimeInMillis The time in millisecond for scroll feature + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. + * @param noFields The no fields support + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. + * @return The scan id for input query. + */ + String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields); + + /** + * Returns scroll id for criteria query + * + * @param query The criteria query. + * @param scrollTimeInMillis The time in millisecond for scroll feature + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}. + * @param noFields The no fields support + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. + * @param clazz The class of entity to retrieve. + * @param The type of entity to retrieve. + * @return The scan id for input query. + */ + String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields, Class clazz); + + /** + * Returns scroll id for scan 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 noFields The no fields support + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. + * @return The scan id for input query. + */ + String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields); + + /** + * Returns scroll id for scan 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 noFields The no fields support + * {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}. + * @param clazz The class of entity to retrieve. + * @param The type of entity to retrieve. + * @return The scan id for input query. + */ + String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields, Class clazz); + + /** + * Scrolls the results for give scroll id + * + * @param scrollId + * @param scrollTimeInMillis + * @param clazz + * @param + * @return + */ + Page scroll(String scrollId, long scrollTimeInMillis, Class clazz); + + /** + * Scrolls the results for give scroll id using custom result mapper + * + * @param scrollId + * @param scrollTimeInMillis + * @param mapper + * @param + * @return + */ + Page scroll(String scrollId, long scrollTimeInMillis, 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/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index 87a994cb..c504fb44 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -1,1204 +1,1204 @@ -/* - * 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 static org.apache.commons.lang.StringUtils.isNotBlank; -import static org.apache.commons.lang.StringUtils.isBlank; -import static org.elasticsearch.action.search.SearchType.*; -import static org.elasticsearch.client.Requests.*; -import static org.elasticsearch.cluster.metadata.AliasAction.Type.*; -import static org.elasticsearch.index.VersionType.*; -import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.springframework.data.elasticsearch.core.MappingBuilder.*; -import static org.springframework.util.CollectionUtils.isEmpty; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.util.*; - -import org.elasticsearch.action.ListenableActionFuture; -import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; -import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; -import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; -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.BulkRequestBuilder; -import org.elasticsearch.action.bulk.BulkResponse; -import org.elasticsearch.action.count.CountRequestBuilder; -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.IndexRequestBuilder; -import org.elasticsearch.action.search.SearchRequestBuilder; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.action.search.SearchType; -import org.elasticsearch.action.suggest.SuggestRequestBuilder; -import org.elasticsearch.action.suggest.SuggestResponse; -import org.elasticsearch.action.update.UpdateRequestBuilder; -import org.elasticsearch.action.update.UpdateResponse; -import org.elasticsearch.client.Client; -import org.elasticsearch.client.Requests; -import org.elasticsearch.cluster.metadata.AliasAction; -import org.elasticsearch.cluster.metadata.AliasMetaData; -import org.elasticsearch.common.collect.MapBuilder; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.XContentBuilder; -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.highlight.HighlightBuilder; -import org.elasticsearch.search.sort.SortBuilder; -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.*; -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.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.SimpleElasticsearchMappingContext; -import org.springframework.data.elasticsearch.core.query.*; -import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.util.CloseableIterator; -import org.springframework.util.Assert; - -/** - * ElasticsearchTemplate - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - * @author Kevin Leturc - * @author Mason Chan - * @author Young Gu - * @author Oliver Gierke - * @author Mark Janssen - */ - -public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware { - - private static final Logger logger = LoggerFactory.getLogger(ElasticsearchTemplate.class); - private Client client; - private ElasticsearchConverter elasticsearchConverter; - private ResultsMapper resultsMapper; - private String searchTimeout; - - public ElasticsearchTemplate(Client client) { - this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext())); - } - - public ElasticsearchTemplate(Client client, EntityMapper entityMapper) { - this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), entityMapper); - } - - public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, EntityMapper entityMapper) { - this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper)); - } - - public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) { - this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), resultsMapper); - } - - public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) { - this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext())); - } - - public ElasticsearchTemplate(Client 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 Client 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"); - return client.admin().indices() - .create(Requests.createIndexRequest(indexName)) - .actionGet().isAcknowledged(); - } - - @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 { - xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), persistentEntity - .getIdProperty().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()"); - PutMappingRequestBuilder requestBuilder = client.admin().indices() - .preparePutMapping(indexName).setType(type); - if (mapping instanceof String) { - requestBuilder.setSource(String.valueOf(mapping)); - } else if (mapping instanceof Map) { - requestBuilder.setSource((Map) mapping); - } else if (mapping instanceof XContentBuilder) { - requestBuilder.setSource((XContentBuilder) mapping); - } - return requestBuilder.execute().actionGet().isAcknowledged(); - } - - @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; - try { - mappings = client.admin().indices().getMappings(new GetMappingsRequest().indices(indexName).types(type)) - .actionGet().getMappings().get(indexName).get(type).getSourceAsMap(); - } catch (Exception e) { - throw new ElasticsearchException("Error while getting mapping for indexName : " + indexName + " type : " + type + " " + e.getMessage()); - } - return mappings; - } - - @Override - public Map getMapping(Class clazz) { - return getMapping(getPersistentEntityFor(clazz).getIndexName(), getPersistentEntityFor(clazz).getIndexType()); - } - - @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); - GetResponse response = client - .prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute() - .actionGet(); - - T entity = mapper.mapResult(response, clazz); - return entity; - } - - @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), 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) { - SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields(); - if (query.getFilter() != null) { - request.setPostFilter(query.getFilter()); - } - SearchResponse response = getSearchResponse(request.execute()); - 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()); - SearchRequestBuilder searchRequestBuilder = prepareSearch(criteriaQuery, clazz); - - if (elasticsearchQuery != null) { - searchRequestBuilder.setQuery(elasticsearchQuery); - } else { - searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery()); - } - - if (criteriaQuery.getMinScore() > 0) { - searchRequestBuilder.setMinScore(criteriaQuery.getMinScore()); - } - - if (elasticsearchFilter != null) - searchRequestBuilder.setPostFilter(elasticsearchFilter); - if (logger.isDebugEnabled()) { - logger.debug("doSearch query:\n" + searchRequestBuilder.toString()); - } - - SearchResponse response = getSearchResponse(searchRequestBuilder - .execute()); - 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) { - SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(query.getSource()).execute()); - return mapper.mapResults(response, clazz, query.getPageable()); - } - - @Override - public CloseableIterator stream(CriteriaQuery query, Class clazz) { - final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); - final String initScrollId = scan(query, scrollTimeInMillis, false, clazz); - return doStream(initScrollId, scrollTimeInMillis, 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(); - final String initScrollId = scan(query, scrollTimeInMillis, false, clazz); - return doStream(initScrollId, scrollTimeInMillis, clazz, mapper); - } - - private CloseableIterator doStream(final String initScrollId, final long scrollTimeInMillis, 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; - - /** The scroll id. */ - private volatile String scrollId = initScrollId; - - /** If stream is finished (ie: cluster returns no results. */ - private volatile boolean finished; - - @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()) { - client.prepareClearScroll().addScrollId(scrollId).execute().actionGet(); - } - } 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 - SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId) - .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute()); - // Save hits and scroll id - currentHits = mapper.mapResults(response, clazz, null).iterator(); - finished = !currentHits.hasNext(); - scrollId = response.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(CountRequestBuilder countRequestBuilder, QueryBuilder elasticsearchQuery) { - if (elasticsearchQuery != null) { - countRequestBuilder.setQuery(elasticsearchQuery); - } - return countRequestBuilder.execute().actionGet().getCount(); - } - - private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, QueryBuilder elasticsearchFilter) { - if (elasticsearchQuery != null) { - searchRequestBuilder.setQuery(elasticsearchQuery); - } else { - searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery()); - } - if (elasticsearchFilter != null) { - searchRequestBuilder.setPostFilter(elasticsearchFilter); - } - searchRequestBuilder.setSearchType(SearchType.COUNT); - return searchRequestBuilder.execute().actionGet().getHits().getTotalHits(); - } - - private CountRequestBuilder 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"); - - CountRequestBuilder countRequestBuilder = client.prepareCount(indexName); - - if (types != null) { - countRequestBuilder.setTypes(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"); - - MultiGetRequestBuilder builder = client.prepareMultiGet(); - - for (String id : searchQuery.getIds()) { - - MultiGetRequest.Item item = new MultiGetRequest.Item(indexName, type, id); - - if (searchQuery.getRoute() != null) { - item = item.routing(searchQuery.getRoute()); - } - - if (searchQuery.getFields() != null && !searchQuery.getFields().isEmpty()) { - item = item.fields(toArray(searchQuery.getFields())); - } - builder.add(item); - } - return builder.execute().actionGet(); - } - - @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 = prepareIndex(query).execute().actionGet().getId(); - // 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) { - return this.prepareUpdate(query).execute().actionGet(); - } - - private UpdateRequestBuilder 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"); - UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(indexName, type, query.getId()); - updateRequestBuilder.setRouting(query.getUpdateRequest().routing()); - - if (query.getUpdateRequest().script() == null) { - // doc - if (query.DoUpsert()) { - updateRequestBuilder.setDocAsUpsert(true) - .setDoc(query.getUpdateRequest().doc()); - } else { - updateRequestBuilder.setDoc(query.getUpdateRequest().doc()); - } - } else { - // or script - updateRequestBuilder.setScript(query.getUpdateRequest().script()); - } - - return updateRequestBuilder; - } - - @Override - public void bulkIndex(List queries) { - BulkRequestBuilder bulkRequest = client.prepareBulk(); - for (IndexQuery query : queries) { - bulkRequest.add(prepareIndex(query)); - } - BulkResponse bulkResponse = bulkRequest.execute().actionGet(); - 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 void bulkUpdate(List queries) { - BulkRequestBuilder bulkRequest = client.prepareBulk(); - for (UpdateQuery query : queries) { - bulkRequest.add(prepareUpdate(query)); - } - BulkResponse bulkResponse = bulkRequest.execute().actionGet(); - 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) { - return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists(); - } - - @Override - public boolean typeExists(String index, String type) { - return client.admin().cluster().prepareState().execute().actionGet() - .getState().metaData().index(index).getMappings().containsKey(type); - } - - @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)) { - return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged(); - } - return false; - } - - @Override - public String delete(String indexName, String type, String id) { - return client.prepareDelete(indexName, type, id).execute().actionGet().getId(); - } - - @Override - public String delete(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(new PageRequest(0, pageSize)) - .build(); - - String scrollId = scan(searchQuery, scrollTimeInMillis, true); - - BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); - List ids = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = scroll(scrollId, scrollTimeInMillis, new SearchResultMapper() { - @Override - public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { - List result = new ArrayList(); - for (SearchHit searchHit : response.getHits()) { - String id = searchHit.getId(); - result.add(id); - } - if (result.size() > 0) { - return new AggregatedPageImpl((List) result); - } - return null; - } - }); - if (page != null && page.getContent().size() > 0) { - ids.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - - for(String id : ids) { - bulkRequestBuilder.add(client.prepareDelete(indexName, typeName, id)); - } - - if(bulkRequestBuilder.numberOfActions() > 0) { - bulkRequestBuilder.execute().actionGet(); - } - - clearScroll(scrollId); - } - - @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); - } - - @Override - public String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields) { - return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields), criteriaQuery); - } - - @Override - public String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields, Class clazz) { - return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields, clazz), criteriaQuery); - } - - @Override - public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) { - return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields), searchQuery); - } - - @Override - public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields, Class clazz) { - return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields, clazz), searchQuery); - } - - private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields, Class clazz) { - setPersistentEntityIndexAndType(query, clazz); - return prepareScan(query, scrollTimeInMillis, noFields); - } - - private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields) { - SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices())).setSearchType(SCAN) - .setTypes(toArray(query.getTypes())) - .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0) - .setSize(query.getPageable().getPageSize()); - - if (!isEmpty(query.getFields())) { - requestBuilder.addFields(toArray(query.getFields())); - } - - if (noFields) { - requestBuilder.setNoFields(); - } - return requestBuilder; - } - - private String doScan(SearchRequestBuilder requestBuilder, 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) { - requestBuilder.setQuery(elasticsearchQuery); - } else { - requestBuilder.setQuery(QueryBuilders.matchAllQuery()); - } - - if (elasticsearchFilter != null) { - requestBuilder.setPostFilter(elasticsearchFilter); - } - - return getSearchResponse(requestBuilder.execute()).getScrollId(); - } - - private String doScan(SearchRequestBuilder requestBuilder, 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) { - requestBuilder.setPostFilter(searchQuery.getFilter()); - } - - return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()).execute()).getScrollId(); - } - - @Override - public Page scroll(String scrollId, long scrollTimeInMillis, Class clazz) { - SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId) - .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute()); - return resultsMapper.mapResults(response, clazz, null); - } - - @Override - public Page scroll(String scrollId, long scrollTimeInMillis, SearchResultMapper mapper) { - SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId) - .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute()); - return mapper.mapResults(response, null, null); - } - - @Override - public void clearScroll(String scrollId) { - client.prepareClearScroll().addScrollId(scrollId).execute().actionGet(); - } - - @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() - .addLikeItem(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(SearchRequestBuilder searchRequest, SearchQuery searchQuery) { - if (searchQuery.getFilter() != null) { - searchRequest.setPostFilter(searchQuery.getFilter()); - } - - if (!isEmpty(searchQuery.getElasticsearchSorts())) { - for (SortBuilder sort : searchQuery.getElasticsearchSorts()) { - searchRequest.addSort(sort); - } - } - - if (!searchQuery.getScriptFields().isEmpty()) { - searchRequest.addField("_source"); - for (ScriptField scriptedField : searchQuery.getScriptFields()) { - searchRequest.addScriptField(scriptedField.fieldName(), scriptedField.script()); - } - } - - if (searchQuery.getHighlightFields() != null) { - for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) { - searchRequest.addHighlightedField(highlightField); - } - } - - if (!isEmpty(searchQuery.getIndicesBoost())) { - for (IndexBoost indexBoost : searchQuery.getIndicesBoost()) { - searchRequest.addIndexBoost(indexBoost.getIndexName(), indexBoost.getBoost()); - } - } - - if (!isEmpty(searchQuery.getAggregations())) { - for (AbstractAggregationBuilder aggregationBuilder : searchQuery.getAggregations()) { - searchRequest.addAggregation(aggregationBuilder); - } - } - - if (!isEmpty(searchQuery.getFacets())) { - for (FacetRequest aggregatedFacet : searchQuery.getFacets()) { - searchRequest.addAggregation(aggregatedFacet.getFacet()); - } - } - return getSearchResponse(searchRequest.setQuery(searchQuery.getQuery()).execute()); - } - - private SearchResponse getSearchResponse(ListenableActionFuture 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) { - CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName); - if (settings instanceof String) { - createIndexRequestBuilder.setSettings(String.valueOf(settings)); - } else if (settings instanceof Map) { - createIndexRequestBuilder.setSettings((Map) settings); - } else if (settings instanceof XContentBuilder) { - createIndexRequestBuilder.setSettings((XContentBuilder) settings); - } - return createIndexRequestBuilder.execute().actionGet().isAcknowledged(); - } - - @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 - public Map getSetting(String indexName) { - Assert.notNull(indexName, "No index defined for getSettings"); - return client.admin().indices().getSettings(new GetSettingsRequest()) - .actionGet().getIndexToSettings().get(indexName).getAsMap(); - } - - private SearchRequestBuilder prepareSearch(Query query, Class clazz) { - setPersistentEntityIndexAndType(query, clazz); - return prepareSearch(query); - } - - private SearchRequestBuilder prepareSearch(Query query) { - Assert.notNull(query.getIndices(), "No index defined for Query"); - Assert.notNull(query.getTypes(), "No type defined for Query"); - - int startRecord = 0; - SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices())) - .setSearchType(query.getSearchType()).setTypes(toArray(query.getTypes())); - - if (query.getSourceFilter() != null) { - SourceFilter sourceFilter = query.getSourceFilter(); - searchRequestBuilder.setFetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes()); - } - - if (query.getPageable() != null) { - startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize(); - searchRequestBuilder.setSize(query.getPageable().getPageSize()); - } - searchRequestBuilder.setFrom(startRecord); - - if (!query.getFields().isEmpty()) { - searchRequestBuilder.addFields(toArray(query.getFields())); - } - - if (query.getSort() != null) { - for (Sort.Order order : query.getSort()) { - searchRequestBuilder.addSort(order.getProperty(), order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC - : SortOrder.ASC); - } - } - - if (query.getMinScore() > 0) { - searchRequestBuilder.setMinScore(query.getMinScore()); - } - return searchRequestBuilder; - } - - private IndexRequestBuilder prepareIndex(IndexQuery query) { - try { - String indexName = isBlank(query.getIndexName()) ? retrieveIndexNameFromPersistentEntity(query.getObject() - .getClass())[0] : query.getIndexName(); - String type = isBlank(query.getType()) ? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0] - : query.getType(); - - IndexRequestBuilder indexRequestBuilder = 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) { - indexRequestBuilder = client.prepareIndex(indexName, type, id); - } else { - indexRequestBuilder = client.prepareIndex(indexName, type); - } - indexRequestBuilder.setSource(resultsMapper.getEntityMapper().mapToString(query.getObject())); - } else if (query.getSource() != null) { - indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource()); - } else { - throw new ElasticsearchException("object or source is null, failed to index the document [id: " + query.getId() + "]"); - } - if (query.getVersion() != null) { - indexRequestBuilder.setVersion(query.getVersion()); - indexRequestBuilder.setVersionType(EXTERNAL); - } - - if (query.getParentId() != null) { - indexRequestBuilder.setParent(query.getParentId()); - } - - return indexRequestBuilder; - } 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()"); - client.admin().indices().refresh(refreshRequest(indexName)).actionGet(); - } - - @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"); - AliasAction aliasAction = new AliasAction(ADD, query.getIndexName(), query.getAliasName()); - 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()); - } - return client.admin().indices().prepareAliases().addAliasAction(aliasAction).execute().actionGet().isAcknowledged(); - } - - @Override - public Boolean removeAlias(AliasQuery query) { - Assert.notNull(query.getIndexName(), "No index defined for Alias"); - Assert.notNull(query.getAliasName(), "No alias defined"); - return client.admin().indices().prepareAliases().removeAlias(query.getIndexName(), query.getAliasName()) - .execute().actionGet().isAcknowledged(); - } - - @Override - public List queryForAlias(String indexName) { - return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName)) - .actionGet().getAliases().get(indexName); - } - - @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().getPersistentEntity(clazz); - } - - private String getPersistentEntityId(Object entity) { - - ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); - Object identifier = persistentEntity.getIdentifierAccessor(entity).getIdentifier(); - - return identifier == null ? null : String.valueOf(identifier); - } - - private void setPersistentEntityId(Object entity, String id) { - - ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); - PersistentProperty idProperty = persistentEntity.getIdProperty(); - - // Only deal with String 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); - } - - 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 SuggestResponse suggest(SuggestBuilder.SuggestionBuilder suggestion, String... indices) { - SuggestRequestBuilder suggestRequestBuilder = client.prepareSuggest(indices); - suggestRequestBuilder.addSuggestion(suggestion); - return suggestRequestBuilder.execute().actionGet(); - } - - public SuggestResponse suggest(SuggestBuilder.SuggestionBuilder suggestion, Class clazz) { - return suggest(suggestion, retrieveIndexNameFromPersistentEntity(clazz)); - } -} +/* + * 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 static org.apache.commons.lang.StringUtils.isNotBlank; +import static org.apache.commons.lang.StringUtils.isBlank; +import static org.elasticsearch.action.search.SearchType.*; +import static org.elasticsearch.client.Requests.*; +import static org.elasticsearch.cluster.metadata.AliasAction.Type.*; +import static org.elasticsearch.index.VersionType.*; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.springframework.data.elasticsearch.core.MappingBuilder.*; +import static org.springframework.util.CollectionUtils.isEmpty; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.util.*; + +import org.elasticsearch.action.ListenableActionFuture; +import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; +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.BulkRequestBuilder; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.count.CountRequestBuilder; +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.IndexRequestBuilder; +import org.elasticsearch.action.search.SearchRequestBuilder; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.SearchType; +import org.elasticsearch.action.suggest.SuggestRequestBuilder; +import org.elasticsearch.action.suggest.SuggestResponse; +import org.elasticsearch.action.update.UpdateRequestBuilder; +import org.elasticsearch.action.update.UpdateResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.client.Requests; +import org.elasticsearch.cluster.metadata.AliasAction; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.common.collect.MapBuilder; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentBuilder; +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.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.SortBuilder; +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.*; +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.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.SimpleElasticsearchMappingContext; +import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.util.CloseableIterator; +import org.springframework.util.Assert; + +/** + * ElasticsearchTemplate + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + * @author Kevin Leturc + * @author Mason Chan + * @author Young Gu + * @author Oliver Gierke + * @author Mark Janssen + */ + +public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware { + + private static final Logger logger = LoggerFactory.getLogger(ElasticsearchTemplate.class); + private Client client; + private ElasticsearchConverter elasticsearchConverter; + private ResultsMapper resultsMapper; + private String searchTimeout; + + public ElasticsearchTemplate(Client client) { + this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext())); + } + + public ElasticsearchTemplate(Client client, EntityMapper entityMapper) { + this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), entityMapper); + } + + public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, EntityMapper entityMapper) { + this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper)); + } + + public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) { + this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), resultsMapper); + } + + public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) { + this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext())); + } + + public ElasticsearchTemplate(Client 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 Client 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"); + return client.admin().indices() + .create(Requests.createIndexRequest(indexName)) + .actionGet().isAcknowledged(); + } + + @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 { + xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(), persistentEntity + .getIdProperty().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()"); + PutMappingRequestBuilder requestBuilder = client.admin().indices() + .preparePutMapping(indexName).setType(type); + if (mapping instanceof String) { + requestBuilder.setSource(String.valueOf(mapping)); + } else if (mapping instanceof Map) { + requestBuilder.setSource((Map) mapping); + } else if (mapping instanceof XContentBuilder) { + requestBuilder.setSource((XContentBuilder) mapping); + } + return requestBuilder.execute().actionGet().isAcknowledged(); + } + + @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; + try { + mappings = client.admin().indices().getMappings(new GetMappingsRequest().indices(indexName).types(type)) + .actionGet().getMappings().get(indexName).get(type).getSourceAsMap(); + } catch (Exception e) { + throw new ElasticsearchException("Error while getting mapping for indexName : " + indexName + " type : " + type + " " + e.getMessage()); + } + return mappings; + } + + @Override + public Map getMapping(Class clazz) { + return getMapping(getPersistentEntityFor(clazz).getIndexName(), getPersistentEntityFor(clazz).getIndexType()); + } + + @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); + GetResponse response = client + .prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute() + .actionGet(); + + T entity = mapper.mapResult(response, clazz); + return entity; + } + + @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), 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) { + SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields(); + if (query.getFilter() != null) { + request.setPostFilter(query.getFilter()); + } + SearchResponse response = getSearchResponse(request.execute()); + 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()); + SearchRequestBuilder searchRequestBuilder = prepareSearch(criteriaQuery, clazz); + + if (elasticsearchQuery != null) { + searchRequestBuilder.setQuery(elasticsearchQuery); + } else { + searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery()); + } + + if (criteriaQuery.getMinScore() > 0) { + searchRequestBuilder.setMinScore(criteriaQuery.getMinScore()); + } + + if (elasticsearchFilter != null) + searchRequestBuilder.setPostFilter(elasticsearchFilter); + if (logger.isDebugEnabled()) { + logger.debug("doSearch query:\n" + searchRequestBuilder.toString()); + } + + SearchResponse response = getSearchResponse(searchRequestBuilder + .execute()); + 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) { + SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(query.getSource()).execute()); + return mapper.mapResults(response, clazz, query.getPageable()); + } + + @Override + public CloseableIterator stream(CriteriaQuery query, Class clazz) { + final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); + final String initScrollId = scan(query, scrollTimeInMillis, false, clazz); + return doStream(initScrollId, scrollTimeInMillis, 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(); + final String initScrollId = scan(query, scrollTimeInMillis, false, clazz); + return doStream(initScrollId, scrollTimeInMillis, clazz, mapper); + } + + private CloseableIterator doStream(final String initScrollId, final long scrollTimeInMillis, 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; + + /** The scroll id. */ + private volatile String scrollId = initScrollId; + + /** If stream is finished (ie: cluster returns no results. */ + private volatile boolean finished; + + @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()) { + client.prepareClearScroll().addScrollId(scrollId).execute().actionGet(); + } + } 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 + SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId) + .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute()); + // Save hits and scroll id + currentHits = mapper.mapResults(response, clazz, null).iterator(); + finished = !currentHits.hasNext(); + scrollId = response.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(CountRequestBuilder countRequestBuilder, QueryBuilder elasticsearchQuery) { + if (elasticsearchQuery != null) { + countRequestBuilder.setQuery(elasticsearchQuery); + } + return countRequestBuilder.execute().actionGet().getCount(); + } + + private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, QueryBuilder elasticsearchFilter) { + if (elasticsearchQuery != null) { + searchRequestBuilder.setQuery(elasticsearchQuery); + } else { + searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery()); + } + if (elasticsearchFilter != null) { + searchRequestBuilder.setPostFilter(elasticsearchFilter); + } + searchRequestBuilder.setSearchType(SearchType.COUNT); + return searchRequestBuilder.execute().actionGet().getHits().getTotalHits(); + } + + private CountRequestBuilder 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"); + + CountRequestBuilder countRequestBuilder = client.prepareCount(indexName); + + if (types != null) { + countRequestBuilder.setTypes(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"); + + MultiGetRequestBuilder builder = client.prepareMultiGet(); + + for (String id : searchQuery.getIds()) { + + MultiGetRequest.Item item = new MultiGetRequest.Item(indexName, type, id); + + if (searchQuery.getRoute() != null) { + item = item.routing(searchQuery.getRoute()); + } + + if (searchQuery.getFields() != null && !searchQuery.getFields().isEmpty()) { + item = item.fields(toArray(searchQuery.getFields())); + } + builder.add(item); + } + return builder.execute().actionGet(); + } + + @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 = prepareIndex(query).execute().actionGet().getId(); + // 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) { + return this.prepareUpdate(query).execute().actionGet(); + } + + private UpdateRequestBuilder 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"); + UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(indexName, type, query.getId()); + updateRequestBuilder.setRouting(query.getUpdateRequest().routing()); + + if (query.getUpdateRequest().script() == null) { + // doc + if (query.DoUpsert()) { + updateRequestBuilder.setDocAsUpsert(true) + .setDoc(query.getUpdateRequest().doc()); + } else { + updateRequestBuilder.setDoc(query.getUpdateRequest().doc()); + } + } else { + // or script + updateRequestBuilder.setScript(query.getUpdateRequest().script()); + } + + return updateRequestBuilder; + } + + @Override + public void bulkIndex(List queries) { + BulkRequestBuilder bulkRequest = client.prepareBulk(); + for (IndexQuery query : queries) { + bulkRequest.add(prepareIndex(query)); + } + BulkResponse bulkResponse = bulkRequest.execute().actionGet(); + 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 void bulkUpdate(List queries) { + BulkRequestBuilder bulkRequest = client.prepareBulk(); + for (UpdateQuery query : queries) { + bulkRequest.add(prepareUpdate(query)); + } + BulkResponse bulkResponse = bulkRequest.execute().actionGet(); + 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) { + return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists(); + } + + @Override + public boolean typeExists(String index, String type) { + return client.admin().cluster().prepareState().execute().actionGet() + .getState().metaData().index(index).getMappings().containsKey(type); + } + + @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)) { + return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged(); + } + return false; + } + + @Override + public String delete(String indexName, String type, String id) { + return client.prepareDelete(indexName, type, id).execute().actionGet().getId(); + } + + @Override + public String delete(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(new PageRequest(0, pageSize)) + .build(); + + String scrollId = scan(searchQuery, scrollTimeInMillis, true); + + BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); + List ids = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = scroll(scrollId, scrollTimeInMillis, new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List result = new ArrayList(); + for (SearchHit searchHit : response.getHits()) { + String id = searchHit.getId(); + result.add(id); + } + if (result.size() > 0) { + return new AggregatedPageImpl((List) result); + } + return null; + } + }); + if (page != null && page.getContent().size() > 0) { + ids.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + + for(String id : ids) { + bulkRequestBuilder.add(client.prepareDelete(indexName, typeName, id)); + } + + if(bulkRequestBuilder.numberOfActions() > 0) { + bulkRequestBuilder.execute().actionGet(); + } + + clearScroll(scrollId); + } + + @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); + } + + @Override + public String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields) { + return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields), criteriaQuery); + } + + @Override + public String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields, Class clazz) { + return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields, clazz), criteriaQuery); + } + + @Override + public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) { + return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields), searchQuery); + } + + @Override + public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields, Class clazz) { + return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields, clazz), searchQuery); + } + + private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields, Class clazz) { + setPersistentEntityIndexAndType(query, clazz); + return prepareScan(query, scrollTimeInMillis, noFields); + } + + private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields) { + SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices())).setSearchType(SCAN) + .setTypes(toArray(query.getTypes())) + .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0) + .setSize(query.getPageable().getPageSize()); + + if (!isEmpty(query.getFields())) { + requestBuilder.addFields(toArray(query.getFields())); + } + + if (noFields) { + requestBuilder.setNoFields(); + } + return requestBuilder; + } + + private String doScan(SearchRequestBuilder requestBuilder, 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) { + requestBuilder.setQuery(elasticsearchQuery); + } else { + requestBuilder.setQuery(QueryBuilders.matchAllQuery()); + } + + if (elasticsearchFilter != null) { + requestBuilder.setPostFilter(elasticsearchFilter); + } + + return getSearchResponse(requestBuilder.execute()).getScrollId(); + } + + private String doScan(SearchRequestBuilder requestBuilder, 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) { + requestBuilder.setPostFilter(searchQuery.getFilter()); + } + + return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()).execute()).getScrollId(); + } + + @Override + public Page scroll(String scrollId, long scrollTimeInMillis, Class clazz) { + SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId) + .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute()); + return resultsMapper.mapResults(response, clazz, null); + } + + @Override + public Page scroll(String scrollId, long scrollTimeInMillis, SearchResultMapper mapper) { + SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId) + .setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute()); + return mapper.mapResults(response, null, null); + } + + @Override + public void clearScroll(String scrollId) { + client.prepareClearScroll().addScrollId(scrollId).execute().actionGet(); + } + + @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() + .addLikeItem(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(SearchRequestBuilder searchRequest, SearchQuery searchQuery) { + if (searchQuery.getFilter() != null) { + searchRequest.setPostFilter(searchQuery.getFilter()); + } + + if (!isEmpty(searchQuery.getElasticsearchSorts())) { + for (SortBuilder sort : searchQuery.getElasticsearchSorts()) { + searchRequest.addSort(sort); + } + } + + if (!searchQuery.getScriptFields().isEmpty()) { + searchRequest.addField("_source"); + for (ScriptField scriptedField : searchQuery.getScriptFields()) { + searchRequest.addScriptField(scriptedField.fieldName(), scriptedField.script()); + } + } + + if (searchQuery.getHighlightFields() != null) { + for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) { + searchRequest.addHighlightedField(highlightField); + } + } + + if (!isEmpty(searchQuery.getIndicesBoost())) { + for (IndexBoost indexBoost : searchQuery.getIndicesBoost()) { + searchRequest.addIndexBoost(indexBoost.getIndexName(), indexBoost.getBoost()); + } + } + + if (!isEmpty(searchQuery.getAggregations())) { + for (AbstractAggregationBuilder aggregationBuilder : searchQuery.getAggregations()) { + searchRequest.addAggregation(aggregationBuilder); + } + } + + if (!isEmpty(searchQuery.getFacets())) { + for (FacetRequest aggregatedFacet : searchQuery.getFacets()) { + searchRequest.addAggregation(aggregatedFacet.getFacet()); + } + } + return getSearchResponse(searchRequest.setQuery(searchQuery.getQuery()).execute()); + } + + private SearchResponse getSearchResponse(ListenableActionFuture 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) { + CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName); + if (settings instanceof String) { + createIndexRequestBuilder.setSettings(String.valueOf(settings)); + } else if (settings instanceof Map) { + createIndexRequestBuilder.setSettings((Map) settings); + } else if (settings instanceof XContentBuilder) { + createIndexRequestBuilder.setSettings((XContentBuilder) settings); + } + return createIndexRequestBuilder.execute().actionGet().isAcknowledged(); + } + + @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 + public Map getSetting(String indexName) { + Assert.notNull(indexName, "No index defined for getSettings"); + return client.admin().indices().getSettings(new GetSettingsRequest()) + .actionGet().getIndexToSettings().get(indexName).getAsMap(); + } + + private SearchRequestBuilder prepareSearch(Query query, Class clazz) { + setPersistentEntityIndexAndType(query, clazz); + return prepareSearch(query); + } + + private SearchRequestBuilder prepareSearch(Query query) { + Assert.notNull(query.getIndices(), "No index defined for Query"); + Assert.notNull(query.getTypes(), "No type defined for Query"); + + int startRecord = 0; + SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices())) + .setSearchType(query.getSearchType()).setTypes(toArray(query.getTypes())); + + if (query.getSourceFilter() != null) { + SourceFilter sourceFilter = query.getSourceFilter(); + searchRequestBuilder.setFetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes()); + } + + if (query.getPageable() != null) { + startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize(); + searchRequestBuilder.setSize(query.getPageable().getPageSize()); + } + searchRequestBuilder.setFrom(startRecord); + + if (!query.getFields().isEmpty()) { + searchRequestBuilder.addFields(toArray(query.getFields())); + } + + if (query.getSort() != null) { + for (Sort.Order order : query.getSort()) { + searchRequestBuilder.addSort(order.getProperty(), order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC + : SortOrder.ASC); + } + } + + if (query.getMinScore() > 0) { + searchRequestBuilder.setMinScore(query.getMinScore()); + } + return searchRequestBuilder; + } + + private IndexRequestBuilder prepareIndex(IndexQuery query) { + try { + String indexName = isBlank(query.getIndexName()) ? retrieveIndexNameFromPersistentEntity(query.getObject() + .getClass())[0] : query.getIndexName(); + String type = isBlank(query.getType()) ? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0] + : query.getType(); + + IndexRequestBuilder indexRequestBuilder = 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) { + indexRequestBuilder = client.prepareIndex(indexName, type, id); + } else { + indexRequestBuilder = client.prepareIndex(indexName, type); + } + indexRequestBuilder.setSource(resultsMapper.getEntityMapper().mapToString(query.getObject())); + } else if (query.getSource() != null) { + indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource()); + } else { + throw new ElasticsearchException("object or source is null, failed to index the document [id: " + query.getId() + "]"); + } + if (query.getVersion() != null) { + indexRequestBuilder.setVersion(query.getVersion()); + indexRequestBuilder.setVersionType(EXTERNAL); + } + + if (query.getParentId() != null) { + indexRequestBuilder.setParent(query.getParentId()); + } + + return indexRequestBuilder; + } 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()"); + client.admin().indices().refresh(refreshRequest(indexName)).actionGet(); + } + + @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"); + AliasAction aliasAction = new AliasAction(ADD, query.getIndexName(), query.getAliasName()); + 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()); + } + return client.admin().indices().prepareAliases().addAliasAction(aliasAction).execute().actionGet().isAcknowledged(); + } + + @Override + public Boolean removeAlias(AliasQuery query) { + Assert.notNull(query.getIndexName(), "No index defined for Alias"); + Assert.notNull(query.getAliasName(), "No alias defined"); + return client.admin().indices().prepareAliases().removeAlias(query.getIndexName(), query.getAliasName()) + .execute().actionGet().isAcknowledged(); + } + + @Override + public List queryForAlias(String indexName) { + return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName)) + .actionGet().getAliases().get(indexName); + } + + @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().getPersistentEntity(clazz); + } + + private String getPersistentEntityId(Object entity) { + + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); + Object identifier = persistentEntity.getIdentifierAccessor(entity).getIdentifier(); + + return identifier == null ? null : String.valueOf(identifier); + } + + private void setPersistentEntityId(Object entity, String id) { + + ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); + PersistentProperty idProperty = persistentEntity.getIdProperty(); + + // Only deal with String 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); + } + + 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 SuggestResponse suggest(SuggestBuilder.SuggestionBuilder suggestion, String... indices) { + SuggestRequestBuilder suggestRequestBuilder = client.prepareSuggest(indices); + suggestRequestBuilder.addSuggestion(suggestion); + return suggestRequestBuilder.execute().actionGet(); + } + + public SuggestResponse suggest(SuggestBuilder.SuggestionBuilder suggestion, Class clazz) { + return suggest(suggestion, retrieveIndexNameFromPersistentEntity(clazz)); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java index 42584cb0..f1512460 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java @@ -1,361 +1,361 @@ -/* - * Copyright 2014-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 static org.apache.commons.lang.StringUtils.*; -import static org.elasticsearch.common.xcontent.XContentFactory.*; -import static org.springframework.util.StringUtils.*; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.NumberUtils; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.springframework.core.io.ClassPathResource; -import org.springframework.data.annotation.Transient; -import org.springframework.data.elasticsearch.annotations.*; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.core.completion.Completion; -import org.springframework.data.elasticsearch.core.geo.GeoPoint; -import org.springframework.data.mapping.model.SimpleTypeHolder; -import org.springframework.data.util.ClassTypeInformation; -import org.springframework.data.util.TypeInformation; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - * @author Kevin Leturc - * @author Alexander Volz - * @author Dennis Maaß - * @author Pavel Luhin - * @author Oliver Gierke - */ - -class MappingBuilder { - - public static final String FIELD_STORE = "store"; - public static final String FIELD_TYPE = "type"; - public static final String FIELD_INDEX = "index"; - public static final String FIELD_FORMAT = "format"; - public static final String FIELD_SEARCH_ANALYZER = "search_analyzer"; - public static final String FIELD_INDEX_ANALYZER = "analyzer"; - public static final String FIELD_PROPERTIES = "properties"; - public static final String FIELD_PARENT = "_parent"; - - public static final String COMPLETION_PAYLOADS = "payloads"; - public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators"; - public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments"; - public static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length"; - - public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed"; - public static final String TYPE_VALUE_STRING = "string"; - public static final String TYPE_VALUE_GEO_POINT = "geo_point"; - public static final String TYPE_VALUE_COMPLETION = "completion"; - public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix"; - public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision"; - - private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder(); - - static XContentBuilder buildMapping(Class clazz, String indexType, String idFieldName, String parentType) throws IOException { - - XContentBuilder mapping = jsonBuilder().startObject().startObject(indexType); - // Parent - if (hasText(parentType)) { - mapping.startObject(FIELD_PARENT).field(FIELD_TYPE, parentType).endObject(); - } - - // Properties - XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES); - - mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY, false, FieldType.Auto, null); - - return xContentBuilder.endObject().endObject().endObject(); - } - - private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName, - String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, Field fieldAnnotation) throws IOException { - - java.lang.reflect.Field[] fields = retrieveFields(clazz); - - if (!isRootObject && (isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField)) { - String type = FieldType.Object.toString().toLowerCase(); - if (nestedOrObjectField) { - type = fieldType.toString().toLowerCase(); - } - XContentBuilder t = xContentBuilder.startObject(nestedObjectFieldName).field(FIELD_TYPE, type); - - if (nestedOrObjectField && FieldType.Nested == fieldType && fieldAnnotation.includeInParent()) { - t.field("include_in_parent", fieldAnnotation.includeInParent()); - } - t.startObject(FIELD_PROPERTIES); - } - - for (java.lang.reflect.Field field : fields) { - - if (field.isAnnotationPresent(Transient.class) || isInIgnoreFields(field, fieldAnnotation)) { - continue; - } - - if (field.isAnnotationPresent(Mapping.class)) { - String mappingPath = field.getAnnotation(Mapping.class).mappingPath(); - if (isNotBlank(mappingPath)) { - ClassPathResource mappings = new ClassPathResource(mappingPath); - if (mappings.exists()) { - xContentBuilder.rawField(field.getName(), mappings.getInputStream()); - continue; - } - } - } - - boolean isGeoPointField = isGeoPointField(field); - boolean isCompletionField = isCompletionField(field); - - Field singleField = field.getAnnotation(Field.class); - if (!isGeoPointField && !isCompletionField && isEntity(field) && isAnnotated(field)) { - if (singleField == null) { - continue; - } - boolean nestedOrObject = isNestedOrObjectField(field); - mapEntity(xContentBuilder, getFieldType(field), false, EMPTY, field.getName(), nestedOrObject, singleField.type(), field.getAnnotation(Field.class)); - if (nestedOrObject) { - continue; - } - } - - MultiField multiField = field.getAnnotation(MultiField.class); - - if (isGeoPointField) { - applyGeoPointFieldMapping(xContentBuilder, field); - } - - if (isCompletionField) { - CompletionField completionField = field.getAnnotation(CompletionField.class); - applyCompletionFieldMapping(xContentBuilder, field, completionField); - } - - if (isRootObject && singleField != null && isIdField(field, idFieldName)) { - applyDefaultIdFieldMapping(xContentBuilder, field); - } else if (multiField != null) { - addMultiFieldMapping(xContentBuilder, field, multiField, isNestedOrObjectField(field)); - } else if (singleField != null) { - addSingleFieldMapping(xContentBuilder, field, singleField, isNestedOrObjectField(field)); - } - } - - if (!isRootObject && isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField) { - xContentBuilder.endObject().endObject(); - } - } - - private static java.lang.reflect.Field[] retrieveFields(Class clazz) { - // Create list of fields. - List fields = new ArrayList(); - - // Keep backing up the inheritance hierarchy. - Class targetClass = clazz; - do { - fields.addAll(Arrays.asList(targetClass.getDeclaredFields())); - targetClass = targetClass.getSuperclass(); - } - while (targetClass != null && targetClass != Object.class); - - return fields.toArray(new java.lang.reflect.Field[fields.size()]); - } - - private static boolean isAnnotated(java.lang.reflect.Field field) { - return field.getAnnotation(Field.class) != null || - field.getAnnotation(MultiField.class) != null || - field.getAnnotation(GeoPointField.class) != null || - field.getAnnotation(CompletionField.class) != null; - } - - private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException { - xContentBuilder.startObject(field.getName()); - xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT); - - GeoPointField annotation = field.getAnnotation(GeoPointField.class); - if (annotation != null) { - if (annotation.geoHashPrefix()) { - xContentBuilder.field(TYPE_VALUE_GEO_HASH_PREFIX, true); - if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) { - if (NumberUtils.isNumber(annotation.geoHashPrecision())) { - xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, Integer.parseInt(annotation.geoHashPrecision())); - } else { - xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision()); - } - } - } - } - - xContentBuilder.endObject(); - } - - private static void applyCompletionFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, CompletionField annotation) throws IOException { - xContentBuilder.startObject(field.getName()); - xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_COMPLETION); - if (annotation != null) { - xContentBuilder.field(COMPLETION_MAX_INPUT_LENGTH, annotation.maxInputLength()); - xContentBuilder.field(COMPLETION_PAYLOADS, annotation.payloads()); - xContentBuilder.field(COMPLETION_PRESERVE_POSITION_INCREMENTS, annotation.preservePositionIncrements()); - xContentBuilder.field(COMPLETION_PRESERVE_SEPARATORS, annotation.preserveSeparators()); - if (isNotBlank(annotation.searchAnalyzer())) { - xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer()); - } - if (isNotBlank(annotation.analyzer())) { - xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer()); - } - } - xContentBuilder.endObject(); - } - - private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) - throws IOException { - xContentBuilder.startObject(field.getName()) - .field(FIELD_TYPE, TYPE_VALUE_STRING) - .field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED); - xContentBuilder.endObject(); - } - - /** - * Apply mapping for a single @Field annotation - * - * @throws IOException - */ - private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, - Field fieldAnnotation, boolean nestedOrObjectField) throws IOException { - xContentBuilder.startObject(field.getName()); - if(!nestedOrObjectField) { - xContentBuilder.field(FIELD_STORE, fieldAnnotation.store()); - } - if (FieldType.Auto != fieldAnnotation.type()) { - xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase()); - if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) { - xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format() - ? fieldAnnotation.pattern() : fieldAnnotation.format()); - } - } - if (FieldIndex.not_analyzed == fieldAnnotation.index() || FieldIndex.no == fieldAnnotation.index()) { - xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index().name().toLowerCase()); - } - if (isNotBlank(fieldAnnotation.searchAnalyzer())) { - xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer()); - } - if (isNotBlank(fieldAnnotation.analyzer())) { - xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer()); - } - xContentBuilder.endObject(); - } - - /** - * Apply mapping for a single nested @Field annotation - * - * @throws IOException - */ - private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, - InnerField annotation) throws IOException { - builder.startObject(annotation.suffix()); - //builder.field(FIELD_STORE, annotation.store()); - if (FieldType.Auto != annotation.type()) { - builder.field(FIELD_TYPE, annotation.type().name().toLowerCase()); - } - if (FieldIndex.not_analyzed == annotation.index()) { - builder.field(FIELD_INDEX, annotation.index().name().toLowerCase()); - } - if (isNotBlank(annotation.searchAnalyzer())) { - builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer()); - } - if (isNotBlank(annotation.indexAnalyzer())) { - builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer()); - } - builder.endObject(); - } - - /** - * Multi field mappings for string type fields, support for sorts and facets - * - * @throws IOException - */ - private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, - MultiField annotation, boolean nestedOrObjectField) throws IOException { - builder.startObject(field.getName()); - builder.field(FIELD_TYPE, "multi_field"); - builder.startObject("fields"); - //add standard field - addSingleFieldMapping(builder, field, annotation.mainField(),nestedOrObjectField); - for (InnerField innerField : annotation.otherFields()) { - addNestedFieldMapping(builder, field, innerField); - } - builder.endObject(); - builder.endObject(); - } - - protected static boolean isEntity(java.lang.reflect.Field field) { - - TypeInformation typeInformation = ClassTypeInformation.from(field.getType()); - Class clazz = getFieldType(field); - boolean isComplexType = !SIMPLE_TYPE_HOLDER.isSimpleType(clazz); - return isComplexType && !typeInformation.isMap(); - } - - protected static Class getFieldType(java.lang.reflect.Field field) { - - return ClassTypeInformation.from(field.getDeclaringClass()) // - .getProperty(field.getName()) // - .getActualType() // - .getType(); - } - - private static boolean isAnyPropertyAnnotatedAsField(java.lang.reflect.Field[] fields) { - if (fields != null) { - for (java.lang.reflect.Field field : fields) { - if (field.isAnnotationPresent(Field.class)) { - return true; - } - } - } - return false; - } - - private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) { - return idFieldName.equals(field.getName()); - } - - private static boolean isInIgnoreFields(java.lang.reflect.Field field, Field parentFieldAnnotation) { - if (null != parentFieldAnnotation) { - String[] ignoreFields = parentFieldAnnotation.ignoreFields(); - return Arrays.asList(ignoreFields).contains(field.getName()); - } - return false; - } - - private static boolean isNestedOrObjectField(java.lang.reflect.Field field) { - Field fieldAnnotation = field.getAnnotation(Field.class); - return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type()); - } - - private static boolean isGeoPointField(java.lang.reflect.Field field) { - return field.getType() == GeoPoint.class || field.getAnnotation(GeoPointField.class) != null; - } - - private static boolean isCompletionField(java.lang.reflect.Field field) { - return field.getType() == Completion.class; - } -} +/* + * Copyright 2014-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 static org.apache.commons.lang.StringUtils.*; +import static org.elasticsearch.common.xcontent.XContentFactory.*; +import static org.springframework.util.StringUtils.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.springframework.core.io.ClassPathResource; +import org.springframework.data.annotation.Transient; +import org.springframework.data.elasticsearch.annotations.*; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.core.completion.Completion; +import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + * @author Kevin Leturc + * @author Alexander Volz + * @author Dennis Maaß + * @author Pavel Luhin + * @author Oliver Gierke + */ + +class MappingBuilder { + + public static final String FIELD_STORE = "store"; + public static final String FIELD_TYPE = "type"; + public static final String FIELD_INDEX = "index"; + public static final String FIELD_FORMAT = "format"; + public static final String FIELD_SEARCH_ANALYZER = "search_analyzer"; + public static final String FIELD_INDEX_ANALYZER = "analyzer"; + public static final String FIELD_PROPERTIES = "properties"; + public static final String FIELD_PARENT = "_parent"; + + public static final String COMPLETION_PAYLOADS = "payloads"; + public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators"; + public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments"; + public static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length"; + + public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed"; + public static final String TYPE_VALUE_STRING = "string"; + public static final String TYPE_VALUE_GEO_POINT = "geo_point"; + public static final String TYPE_VALUE_COMPLETION = "completion"; + public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix"; + public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision"; + + private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder(); + + static XContentBuilder buildMapping(Class clazz, String indexType, String idFieldName, String parentType) throws IOException { + + XContentBuilder mapping = jsonBuilder().startObject().startObject(indexType); + // Parent + if (hasText(parentType)) { + mapping.startObject(FIELD_PARENT).field(FIELD_TYPE, parentType).endObject(); + } + + // Properties + XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES); + + mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY, false, FieldType.Auto, null); + + return xContentBuilder.endObject().endObject().endObject(); + } + + private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName, + String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, Field fieldAnnotation) throws IOException { + + java.lang.reflect.Field[] fields = retrieveFields(clazz); + + if (!isRootObject && (isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField)) { + String type = FieldType.Object.toString().toLowerCase(); + if (nestedOrObjectField) { + type = fieldType.toString().toLowerCase(); + } + XContentBuilder t = xContentBuilder.startObject(nestedObjectFieldName).field(FIELD_TYPE, type); + + if (nestedOrObjectField && FieldType.Nested == fieldType && fieldAnnotation.includeInParent()) { + t.field("include_in_parent", fieldAnnotation.includeInParent()); + } + t.startObject(FIELD_PROPERTIES); + } + + for (java.lang.reflect.Field field : fields) { + + if (field.isAnnotationPresent(Transient.class) || isInIgnoreFields(field, fieldAnnotation)) { + continue; + } + + if (field.isAnnotationPresent(Mapping.class)) { + String mappingPath = field.getAnnotation(Mapping.class).mappingPath(); + if (isNotBlank(mappingPath)) { + ClassPathResource mappings = new ClassPathResource(mappingPath); + if (mappings.exists()) { + xContentBuilder.rawField(field.getName(), mappings.getInputStream()); + continue; + } + } + } + + boolean isGeoPointField = isGeoPointField(field); + boolean isCompletionField = isCompletionField(field); + + Field singleField = field.getAnnotation(Field.class); + if (!isGeoPointField && !isCompletionField && isEntity(field) && isAnnotated(field)) { + if (singleField == null) { + continue; + } + boolean nestedOrObject = isNestedOrObjectField(field); + mapEntity(xContentBuilder, getFieldType(field), false, EMPTY, field.getName(), nestedOrObject, singleField.type(), field.getAnnotation(Field.class)); + if (nestedOrObject) { + continue; + } + } + + MultiField multiField = field.getAnnotation(MultiField.class); + + if (isGeoPointField) { + applyGeoPointFieldMapping(xContentBuilder, field); + } + + if (isCompletionField) { + CompletionField completionField = field.getAnnotation(CompletionField.class); + applyCompletionFieldMapping(xContentBuilder, field, completionField); + } + + if (isRootObject && singleField != null && isIdField(field, idFieldName)) { + applyDefaultIdFieldMapping(xContentBuilder, field); + } else if (multiField != null) { + addMultiFieldMapping(xContentBuilder, field, multiField, isNestedOrObjectField(field)); + } else if (singleField != null) { + addSingleFieldMapping(xContentBuilder, field, singleField, isNestedOrObjectField(field)); + } + } + + if (!isRootObject && isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField) { + xContentBuilder.endObject().endObject(); + } + } + + private static java.lang.reflect.Field[] retrieveFields(Class clazz) { + // Create list of fields. + List fields = new ArrayList(); + + // Keep backing up the inheritance hierarchy. + Class targetClass = clazz; + do { + fields.addAll(Arrays.asList(targetClass.getDeclaredFields())); + targetClass = targetClass.getSuperclass(); + } + while (targetClass != null && targetClass != Object.class); + + return fields.toArray(new java.lang.reflect.Field[fields.size()]); + } + + private static boolean isAnnotated(java.lang.reflect.Field field) { + return field.getAnnotation(Field.class) != null || + field.getAnnotation(MultiField.class) != null || + field.getAnnotation(GeoPointField.class) != null || + field.getAnnotation(CompletionField.class) != null; + } + + private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException { + xContentBuilder.startObject(field.getName()); + xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT); + + GeoPointField annotation = field.getAnnotation(GeoPointField.class); + if (annotation != null) { + if (annotation.geoHashPrefix()) { + xContentBuilder.field(TYPE_VALUE_GEO_HASH_PREFIX, true); + if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) { + if (NumberUtils.isNumber(annotation.geoHashPrecision())) { + xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, Integer.parseInt(annotation.geoHashPrecision())); + } else { + xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision()); + } + } + } + } + + xContentBuilder.endObject(); + } + + private static void applyCompletionFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, CompletionField annotation) throws IOException { + xContentBuilder.startObject(field.getName()); + xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_COMPLETION); + if (annotation != null) { + xContentBuilder.field(COMPLETION_MAX_INPUT_LENGTH, annotation.maxInputLength()); + xContentBuilder.field(COMPLETION_PAYLOADS, annotation.payloads()); + xContentBuilder.field(COMPLETION_PRESERVE_POSITION_INCREMENTS, annotation.preservePositionIncrements()); + xContentBuilder.field(COMPLETION_PRESERVE_SEPARATORS, annotation.preserveSeparators()); + if (isNotBlank(annotation.searchAnalyzer())) { + xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer()); + } + if (isNotBlank(annotation.analyzer())) { + xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer()); + } + } + xContentBuilder.endObject(); + } + + private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) + throws IOException { + xContentBuilder.startObject(field.getName()) + .field(FIELD_TYPE, TYPE_VALUE_STRING) + .field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED); + xContentBuilder.endObject(); + } + + /** + * Apply mapping for a single @Field annotation + * + * @throws IOException + */ + private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, + Field fieldAnnotation, boolean nestedOrObjectField) throws IOException { + xContentBuilder.startObject(field.getName()); + if(!nestedOrObjectField) { + xContentBuilder.field(FIELD_STORE, fieldAnnotation.store()); + } + if (FieldType.Auto != fieldAnnotation.type()) { + xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase()); + if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) { + xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format() + ? fieldAnnotation.pattern() : fieldAnnotation.format()); + } + } + if (FieldIndex.not_analyzed == fieldAnnotation.index() || FieldIndex.no == fieldAnnotation.index()) { + xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index().name().toLowerCase()); + } + if (isNotBlank(fieldAnnotation.searchAnalyzer())) { + xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer()); + } + if (isNotBlank(fieldAnnotation.analyzer())) { + xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer()); + } + xContentBuilder.endObject(); + } + + /** + * Apply mapping for a single nested @Field annotation + * + * @throws IOException + */ + private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, + InnerField annotation) throws IOException { + builder.startObject(annotation.suffix()); + //builder.field(FIELD_STORE, annotation.store()); + if (FieldType.Auto != annotation.type()) { + builder.field(FIELD_TYPE, annotation.type().name().toLowerCase()); + } + if (FieldIndex.not_analyzed == annotation.index()) { + builder.field(FIELD_INDEX, annotation.index().name().toLowerCase()); + } + if (isNotBlank(annotation.searchAnalyzer())) { + builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer()); + } + if (isNotBlank(annotation.indexAnalyzer())) { + builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer()); + } + builder.endObject(); + } + + /** + * Multi field mappings for string type fields, support for sorts and facets + * + * @throws IOException + */ + private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, + MultiField annotation, boolean nestedOrObjectField) throws IOException { + builder.startObject(field.getName()); + builder.field(FIELD_TYPE, "multi_field"); + builder.startObject("fields"); + //add standard field + addSingleFieldMapping(builder, field, annotation.mainField(),nestedOrObjectField); + for (InnerField innerField : annotation.otherFields()) { + addNestedFieldMapping(builder, field, innerField); + } + builder.endObject(); + builder.endObject(); + } + + protected static boolean isEntity(java.lang.reflect.Field field) { + + TypeInformation typeInformation = ClassTypeInformation.from(field.getType()); + Class clazz = getFieldType(field); + boolean isComplexType = !SIMPLE_TYPE_HOLDER.isSimpleType(clazz); + return isComplexType && !typeInformation.isMap(); + } + + protected static Class getFieldType(java.lang.reflect.Field field) { + + return ClassTypeInformation.from(field.getDeclaringClass()) // + .getProperty(field.getName()) // + .getActualType() // + .getType(); + } + + private static boolean isAnyPropertyAnnotatedAsField(java.lang.reflect.Field[] fields) { + if (fields != null) { + for (java.lang.reflect.Field field : fields) { + if (field.isAnnotationPresent(Field.class)) { + return true; + } + } + } + return false; + } + + private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) { + return idFieldName.equals(field.getName()); + } + + private static boolean isInIgnoreFields(java.lang.reflect.Field field, Field parentFieldAnnotation) { + if (null != parentFieldAnnotation) { + String[] ignoreFields = parentFieldAnnotation.ignoreFields(); + return Arrays.asList(ignoreFields).contains(field.getName()); + } + return false; + } + + private static boolean isNestedOrObjectField(java.lang.reflect.Field field) { + Field fieldAnnotation = field.getAnnotation(Field.class); + return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type()); + } + + private static boolean isGeoPointField(java.lang.reflect.Field field) { + return field.getType() == GeoPoint.class || field.getAnnotation(GeoPointField.class) != null; + } + + private static boolean isCompletionField(java.lang.reflect.Field field) { + return field.getType() == Completion.class; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ResultsExtractor.java b/src/main/java/org/springframework/data/elasticsearch/core/ResultsExtractor.java index e1f816da..65856675 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ResultsExtractor.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ResultsExtractor.java @@ -1,24 +1,24 @@ -/* - * Copyright 2013-2014 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.search.SearchResponse; - -public interface ResultsExtractor { - - T extract(SearchResponse response); -} +/* + * Copyright 2013-2014 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.search.SearchResponse; + +public interface ResultsExtractor { + + T extract(SearchResponse response); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ResultsMapper.java b/src/main/java/org/springframework/data/elasticsearch/core/ResultsMapper.java index bd87082b..41db0f7e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ResultsMapper.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ResultsMapper.java @@ -1,29 +1,29 @@ -/* - * Copyright 2013-2014 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; - -/** - * ResultsMapper - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - */ - -public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper { - - EntityMapper getEntityMapper(); -} +/* + * Copyright 2013-2014 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; + +/** + * ResultsMapper + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + */ + +public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper { + + EntityMapper getEntityMapper(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/DateTimeConverters.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/DateTimeConverters.java index fe5c154b..ce81d6d3 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/DateTimeConverters.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/DateTimeConverters.java @@ -1,77 +1,77 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.convert; - -import java.util.Date; - -import org.joda.time.DateTimeZone; -import org.joda.time.LocalDateTime; -import org.joda.time.ReadableInstant; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; -import org.springframework.core.convert.converter.Converter; - -/** - * DateTimeConverters - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public final class DateTimeConverters { - - private static DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC); - - public enum JodaDateTimeConverter implements Converter { - INSTANCE; - - @Override - public String convert(ReadableInstant source) { - if (source == null) { - return null; - } - return formatter.print(source); - } - - } - - public enum JodaLocalDateTimeConverter implements Converter { - INSTANCE; - - @Override - public String convert(LocalDateTime source) { - if (source == null) { - return null; - } - return formatter.print(source.toDateTime(DateTimeZone.UTC)); - } - - } - - public enum JavaDateConverter implements Converter { - INSTANCE; - - @Override - public String convert(Date source) { - if (source == null) { - return null; - } - - return formatter.print(source.getTime()); - } - - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.convert; + +import java.util.Date; + +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDateTime; +import org.joda.time.ReadableInstant; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.springframework.core.convert.converter.Converter; + +/** + * DateTimeConverters + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public final class DateTimeConverters { + + private static DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC); + + public enum JodaDateTimeConverter implements Converter { + INSTANCE; + + @Override + public String convert(ReadableInstant source) { + if (source == null) { + return null; + } + return formatter.print(source); + } + + } + + public enum JodaLocalDateTimeConverter implements Converter { + INSTANCE; + + @Override + public String convert(LocalDateTime source) { + if (source == null) { + return null; + } + return formatter.print(source.toDateTime(DateTimeZone.UTC)); + } + + } + + public enum JavaDateConverter implements Converter { + INSTANCE; + + @Override + public String convert(Date source) { + if (source == null) { + return null; + } + + return formatter.print(source.getTime()); + } + + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java index 2a3c89e1..c649585b 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java @@ -1,45 +1,45 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.convert; - -import org.springframework.core.convert.ConversionService; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.mapping.context.MappingContext; - -/** - * ElasticsearchConverter - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public interface ElasticsearchConverter { - - /** - * Returns the underlying {@link org.springframework.data.mapping.context.MappingContext} used by the converter. - * - * @return never {@literal null} - */ - MappingContext, ElasticsearchPersistentProperty> getMappingContext(); - - /** - * Returns the underlying {@link org.springframework.core.convert.ConversionService} used by the converter. - * - * @return never {@literal null}. - */ - ConversionService getConversionService(); -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.convert; + +import org.springframework.core.convert.ConversionService; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.mapping.context.MappingContext; + +/** + * ElasticsearchConverter + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public interface ElasticsearchConverter { + + /** + * Returns the underlying {@link org.springframework.data.mapping.context.MappingContext} used by the converter. + * + * @return never {@literal null} + */ + MappingContext, ElasticsearchPersistentProperty> getMappingContext(); + + /** + * Returns the underlying {@link org.springframework.core.convert.ConversionService} used by the converter. + * + * @return never {@literal null}. + */ + ConversionService getConversionService(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java index bb0b1e78..496e5bcf 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java @@ -1,70 +1,70 @@ -/* - * 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.core.convert; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.core.convert.support.GenericConversionService; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.util.Assert; - -/** - * MappingElasticsearchConverter - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Mark Paluch - */ -public class MappingElasticsearchConverter implements ElasticsearchConverter, ApplicationContextAware { - - private final MappingContext, ElasticsearchPersistentProperty> mappingContext; - private final GenericConversionService conversionService; - - @SuppressWarnings("unused") - private ApplicationContext applicationContext; - - public MappingElasticsearchConverter( - MappingContext, ElasticsearchPersistentProperty> mappingContext) { - - Assert.notNull(mappingContext, "MappingContext must not be null!"); - - this.mappingContext = mappingContext; - this.conversionService = new DefaultConversionService(); - } - - @Override - public MappingContext, ElasticsearchPersistentProperty> getMappingContext() { - return mappingContext; - } - - @Override - public ConversionService getConversionService() { - return this.conversionService; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - if (mappingContext instanceof ApplicationContextAware) { - ((ApplicationContextAware) mappingContext).setApplicationContext(applicationContext); - } - } -} +/* + * 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.core.convert; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.util.Assert; + +/** + * MappingElasticsearchConverter + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Mark Paluch + */ +public class MappingElasticsearchConverter implements ElasticsearchConverter, ApplicationContextAware { + + private final MappingContext, ElasticsearchPersistentProperty> mappingContext; + private final GenericConversionService conversionService; + + @SuppressWarnings("unused") + private ApplicationContext applicationContext; + + public MappingElasticsearchConverter( + MappingContext, ElasticsearchPersistentProperty> mappingContext) { + + Assert.notNull(mappingContext, "MappingContext must not be null!"); + + this.mappingContext = mappingContext; + this.conversionService = new DefaultConversionService(); + } + + @Override + public MappingContext, ElasticsearchPersistentProperty> getMappingContext() { + return mappingContext; + } + + @Override + public ConversionService getConversionService() { + return this.conversionService; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + if (mappingContext instanceof ApplicationContextAware) { + ((ApplicationContextAware) mappingContext).setApplicationContext(applicationContext); + } + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java index b3127ad7..ee017d03 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java @@ -1,52 +1,52 @@ -/* - * Copyright 2013-2014 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.mapping; - -import org.springframework.data.mapping.PersistentEntity; - -/** - * ElasticsearchPersistentEntity - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public interface ElasticsearchPersistentEntity extends PersistentEntity { - - String getIndexName(); - - String getIndexType(); - - short getShards(); - - short getReplicas(); - - boolean isUseServerConfiguration(); - - String getRefreshInterval(); - - String getIndexStoreType(); - - ElasticsearchPersistentProperty getVersionProperty(); - - String getParentType(); - - ElasticsearchPersistentProperty getParentIdProperty(); - - String settingPath(); - - boolean isCreateIndexAndMapping(); -} +/* + * Copyright 2013-2014 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.mapping; + +import org.springframework.data.mapping.PersistentEntity; + +/** + * ElasticsearchPersistentEntity + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public interface ElasticsearchPersistentEntity extends PersistentEntity { + + String getIndexName(); + + String getIndexType(); + + short getShards(); + + short getReplicas(); + + boolean isUseServerConfiguration(); + + String getRefreshInterval(); + + String getIndexStoreType(); + + ElasticsearchPersistentProperty getVersionProperty(); + + String getParentType(); + + ElasticsearchPersistentProperty getParentIdProperty(); + + String settingPath(); + + boolean isCreateIndexAndMapping(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java index 328bb2d7..45ec379f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java @@ -1,40 +1,40 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.mapping; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.data.mapping.PersistentProperty; - -/** - * ElasticsearchPersistentProperty - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public interface ElasticsearchPersistentProperty extends PersistentProperty { - - String getFieldName(); - - public enum PropertyToFieldNameConverter implements Converter { - - INSTANCE; - - public String convert(ElasticsearchPersistentProperty source) { - return source.getFieldName(); - } - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.mapping; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.mapping.PersistentProperty; + +/** + * ElasticsearchPersistentProperty + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public interface ElasticsearchPersistentProperty extends PersistentProperty { + + String getFieldName(); + + public enum PropertyToFieldNameConverter implements Converter { + + INSTANCE; + + public String convert(ElasticsearchPersistentProperty source) { + return source.getFieldName(); + } + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchMappingContext.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchMappingContext.java index ee1efb09..91d120ab 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchMappingContext.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchMappingContext.java @@ -1,60 +1,60 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.mapping; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.data.mapping.context.AbstractMappingContext; -import org.springframework.data.mapping.model.SimpleTypeHolder; -import org.springframework.data.util.TypeInformation; - -/** - * SimpleElasticsearchMappingContext - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class SimpleElasticsearchMappingContext extends - AbstractMappingContext, ElasticsearchPersistentProperty> implements ApplicationContextAware { - - private ApplicationContext context; - - @Override - protected SimpleElasticsearchPersistentEntity createPersistentEntity(TypeInformation typeInformation) { - final SimpleElasticsearchPersistentEntity persistentEntity = - new SimpleElasticsearchPersistentEntity(typeInformation); - if (context != null) { - persistentEntity.setApplicationContext(context); - } - return persistentEntity; - } - - @Override - protected ElasticsearchPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, - SimpleElasticsearchPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { - return new SimpleElasticsearchPersistentProperty(field, descriptor, owner, simpleTypeHolder); - } - - @Override - public void setApplicationContext(ApplicationContext context) throws BeansException { - this.context = context; - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.mapping; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.data.mapping.context.AbstractMappingContext; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.TypeInformation; + +/** + * SimpleElasticsearchMappingContext + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class SimpleElasticsearchMappingContext extends + AbstractMappingContext, ElasticsearchPersistentProperty> implements ApplicationContextAware { + + private ApplicationContext context; + + @Override + protected SimpleElasticsearchPersistentEntity createPersistentEntity(TypeInformation typeInformation) { + final SimpleElasticsearchPersistentEntity persistentEntity = + new SimpleElasticsearchPersistentEntity(typeInformation); + if (context != null) { + persistentEntity.setApplicationContext(context); + } + return persistentEntity; + } + + @Override + protected ElasticsearchPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, + SimpleElasticsearchPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { + return new SimpleElasticsearchPersistentProperty(field, descriptor, owner, simpleTypeHolder); + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + this.context = context; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java index f4afb13d..ae9e8f33 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java @@ -1,170 +1,170 @@ -/* - * Copyright 2013-2014 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.mapping; - -import static org.springframework.util.StringUtils.*; - -import java.util.Locale; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.expression.BeanFactoryAccessor; -import org.springframework.context.expression.BeanFactoryResolver; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Parent; -import org.springframework.data.elasticsearch.annotations.Setting; -import org.springframework.data.mapping.model.BasicPersistentEntity; -import org.springframework.data.util.TypeInformation; -import org.springframework.expression.Expression; -import org.springframework.expression.ParserContext; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.util.Assert; - -/** - * Elasticsearch specific {@link org.springframework.data.mapping.PersistentEntity} implementation holding - * - * @param - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntity - implements ElasticsearchPersistentEntity, ApplicationContextAware { - - private final StandardEvaluationContext context; - private final SpelExpressionParser parser; - - private String indexName; - private String indexType; - private boolean useServerConfiguration; - private short shards; - private short replicas; - private String refreshInterval; - private String indexStoreType; - private String parentType; - private ElasticsearchPersistentProperty parentIdProperty; - private String settingPath; - private boolean createIndexAndMapping; - - public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation) { - super(typeInformation); - this.context = new StandardEvaluationContext(); - this.parser = new SpelExpressionParser(); - - Class clazz = typeInformation.getType(); - if (clazz.isAnnotationPresent(Document.class)) { - Document document = clazz.getAnnotation(Document.class); - Assert.hasText(document.indexName(), - " Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")"); - this.indexName = document.indexName(); - this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH); - this.useServerConfiguration = document.useServerConfiguration(); - this.shards = document.shards(); - this.replicas = document.replicas(); - this.refreshInterval = document.refreshInterval(); - this.indexStoreType = document.indexStoreType(); - this.createIndexAndMapping = document.createIndex(); - } - if (clazz.isAnnotationPresent(Setting.class)) { - this.settingPath = typeInformation.getType().getAnnotation(Setting.class).settingPath(); - } - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - context.addPropertyAccessor(new BeanFactoryAccessor()); - context.setBeanResolver(new BeanFactoryResolver(applicationContext)); - context.setRootObject(applicationContext); - } - - @Override - public String getIndexName() { - Expression expression = parser.parseExpression(indexName, ParserContext.TEMPLATE_EXPRESSION); - return expression.getValue(context, String.class); - } - - @Override - public String getIndexType() { - Expression expression = parser.parseExpression(indexType, ParserContext.TEMPLATE_EXPRESSION); - return expression.getValue(context, String.class); - } - - @Override - public String getIndexStoreType() { - return indexStoreType; - } - - @Override - public short getShards() { - return shards; - } - - @Override - public short getReplicas() { - return replicas; - } - - @Override - public boolean isUseServerConfiguration() { - return useServerConfiguration; - } - - @Override - public String getRefreshInterval() { - return refreshInterval; - } - - @Override - public String getParentType() { - return parentType; - } - - @Override - public ElasticsearchPersistentProperty getParentIdProperty() { - return parentIdProperty; - } - - @Override - public String settingPath() { - return settingPath; - } - - @Override - public boolean isCreateIndexAndMapping() { - return createIndexAndMapping; - } - - @Override - public void addPersistentProperty(ElasticsearchPersistentProperty property) { - super.addPersistentProperty(property); - - if (property.getField() != null) { - Parent parent = property.getField().getAnnotation(Parent.class); - if (parent != null) { - Assert.isNull(this.parentIdProperty, "Only one field can hold a @Parent annotation"); - Assert.isNull(this.parentType, "Only one field can hold a @Parent annotation"); - Assert.isTrue(property.getType() == String.class, "Parent ID property should be String"); - this.parentIdProperty = property; - this.parentType = parent.type(); - } - } - - if (property.isVersionProperty()) { - Assert.isTrue(property.getType() == Long.class, "Version property should be Long"); - } - } -} +/* + * Copyright 2013-2014 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.mapping; + +import static org.springframework.util.StringUtils.*; + +import java.util.Locale; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.expression.BeanFactoryAccessor; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Parent; +import org.springframework.data.elasticsearch.annotations.Setting; +import org.springframework.data.mapping.model.BasicPersistentEntity; +import org.springframework.data.util.TypeInformation; +import org.springframework.expression.Expression; +import org.springframework.expression.ParserContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.util.Assert; + +/** + * Elasticsearch specific {@link org.springframework.data.mapping.PersistentEntity} implementation holding + * + * @param + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntity + implements ElasticsearchPersistentEntity, ApplicationContextAware { + + private final StandardEvaluationContext context; + private final SpelExpressionParser parser; + + private String indexName; + private String indexType; + private boolean useServerConfiguration; + private short shards; + private short replicas; + private String refreshInterval; + private String indexStoreType; + private String parentType; + private ElasticsearchPersistentProperty parentIdProperty; + private String settingPath; + private boolean createIndexAndMapping; + + public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation) { + super(typeInformation); + this.context = new StandardEvaluationContext(); + this.parser = new SpelExpressionParser(); + + Class clazz = typeInformation.getType(); + if (clazz.isAnnotationPresent(Document.class)) { + Document document = clazz.getAnnotation(Document.class); + Assert.hasText(document.indexName(), + " Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")"); + this.indexName = document.indexName(); + this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH); + this.useServerConfiguration = document.useServerConfiguration(); + this.shards = document.shards(); + this.replicas = document.replicas(); + this.refreshInterval = document.refreshInterval(); + this.indexStoreType = document.indexStoreType(); + this.createIndexAndMapping = document.createIndex(); + } + if (clazz.isAnnotationPresent(Setting.class)) { + this.settingPath = typeInformation.getType().getAnnotation(Setting.class).settingPath(); + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context.addPropertyAccessor(new BeanFactoryAccessor()); + context.setBeanResolver(new BeanFactoryResolver(applicationContext)); + context.setRootObject(applicationContext); + } + + @Override + public String getIndexName() { + Expression expression = parser.parseExpression(indexName, ParserContext.TEMPLATE_EXPRESSION); + return expression.getValue(context, String.class); + } + + @Override + public String getIndexType() { + Expression expression = parser.parseExpression(indexType, ParserContext.TEMPLATE_EXPRESSION); + return expression.getValue(context, String.class); + } + + @Override + public String getIndexStoreType() { + return indexStoreType; + } + + @Override + public short getShards() { + return shards; + } + + @Override + public short getReplicas() { + return replicas; + } + + @Override + public boolean isUseServerConfiguration() { + return useServerConfiguration; + } + + @Override + public String getRefreshInterval() { + return refreshInterval; + } + + @Override + public String getParentType() { + return parentType; + } + + @Override + public ElasticsearchPersistentProperty getParentIdProperty() { + return parentIdProperty; + } + + @Override + public String settingPath() { + return settingPath; + } + + @Override + public boolean isCreateIndexAndMapping() { + return createIndexAndMapping; + } + + @Override + public void addPersistentProperty(ElasticsearchPersistentProperty property) { + super.addPersistentProperty(property); + + if (property.getField() != null) { + Parent parent = property.getField().getAnnotation(Parent.class); + if (parent != null) { + Assert.isNull(this.parentIdProperty, "Only one field can hold a @Parent annotation"); + Assert.isNull(this.parentType, "Only one field can hold a @Parent annotation"); + Assert.isTrue(property.getType() == String.class, "Parent ID property should be String"); + this.parentIdProperty = property; + this.parentType = parent.type(); + } + } + + if (property.isVersionProperty()) { + Assert.isTrue(property.getType() == Long.class, "Version property should be Long"); + } + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java index ea1765ec..57029efd 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java @@ -1,65 +1,65 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.mapping; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.data.mapping.Association; -import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; -import org.springframework.data.mapping.model.SimpleTypeHolder; - -/** - * Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class SimpleElasticsearchPersistentProperty extends - AnnotationBasedPersistentProperty implements ElasticsearchPersistentProperty { - - private static final Set> SUPPORTED_ID_TYPES = new HashSet>(); - private static final Set SUPPORTED_ID_PROPERTY_NAMES = new HashSet(); - - static { - SUPPORTED_ID_TYPES.add(String.class); - SUPPORTED_ID_PROPERTY_NAMES.add("id"); - SUPPORTED_ID_PROPERTY_NAMES.add("documentId"); - } - - public SimpleElasticsearchPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, - PersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { - super(field, propertyDescriptor, owner, simpleTypeHolder); - } - - @Override - public String getFieldName() { - return field.getName(); - } - - @Override - public boolean isIdProperty() { - return super.isIdProperty() || (field != null ? SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName()) : false); - } - - @Override - protected Association createAssociation() { - return null; - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.mapping; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.data.mapping.Association; +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; +import org.springframework.data.mapping.model.SimpleTypeHolder; + +/** + * Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class SimpleElasticsearchPersistentProperty extends + AnnotationBasedPersistentProperty implements ElasticsearchPersistentProperty { + + private static final Set> SUPPORTED_ID_TYPES = new HashSet>(); + private static final Set SUPPORTED_ID_PROPERTY_NAMES = new HashSet(); + + static { + SUPPORTED_ID_TYPES.add(String.class); + SUPPORTED_ID_PROPERTY_NAMES.add("id"); + SUPPORTED_ID_PROPERTY_NAMES.add("documentId"); + } + + public SimpleElasticsearchPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, + PersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { + super(field, propertyDescriptor, owner, simpleTypeHolder); + } + + @Override + public String getFieldName() { + return field.getName(); + } + + @Override + public boolean isIdProperty() { + return super.isIdProperty() || (field != null ? SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName()) : false); + } + + @Override + protected Association createAssociation() { + return null; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/AliasBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/query/AliasBuilder.java index b91ea350..d139cf5e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/AliasBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/AliasBuilder.java @@ -1,81 +1,81 @@ -/* - * Copyright 2013-2014 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.query; - -import java.util.Map; - -import org.elasticsearch.index.query.QueryBuilder; - -/** - * @author Mohsin Husen - */ -public class AliasBuilder { - - private String indexName; - private String aliasName; - private QueryBuilder filterBuilder; - private Map filter; - private String searchRouting; - private String indexRouting; - private String routing; - - public AliasBuilder withIndexName(String indexName) { - this.indexName = indexName; - return this; - } - - public AliasBuilder withAliasName(String aliasName) { - this.aliasName = aliasName; - return this; - } - - public AliasBuilder withFilterBuilder(QueryBuilder filterBuilder) { - this.filterBuilder = filterBuilder; - return this; - } - - public AliasBuilder withFilter(Map filter) { - this.filter = filter; - return this; - } - - public AliasBuilder withSearchRouting(String searchRouting) { - this.searchRouting = searchRouting; - return this; - } - - public AliasBuilder withIndexRouting(String indexRouting) { - this.indexRouting = indexRouting; - return this; - } - - public AliasBuilder withRouting(String routing) { - this.routing = routing; - return this; - } - - public AliasQuery build() { - AliasQuery aliasQuery = new AliasQuery(); - aliasQuery.setIndexName(indexName); - aliasQuery.setAliasName(aliasName); - aliasQuery.setFilterBuilder(filterBuilder); - aliasQuery.setFilter(filter); - aliasQuery.setSearchRouting(searchRouting); - aliasQuery.setIndexRouting(indexRouting); - aliasQuery.setRouting(routing); - return aliasQuery; - } -} +/* + * Copyright 2013-2014 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.query; + +import java.util.Map; + +import org.elasticsearch.index.query.QueryBuilder; + +/** + * @author Mohsin Husen + */ +public class AliasBuilder { + + private String indexName; + private String aliasName; + private QueryBuilder filterBuilder; + private Map filter; + private String searchRouting; + private String indexRouting; + private String routing; + + public AliasBuilder withIndexName(String indexName) { + this.indexName = indexName; + return this; + } + + public AliasBuilder withAliasName(String aliasName) { + this.aliasName = aliasName; + return this; + } + + public AliasBuilder withFilterBuilder(QueryBuilder filterBuilder) { + this.filterBuilder = filterBuilder; + return this; + } + + public AliasBuilder withFilter(Map filter) { + this.filter = filter; + return this; + } + + public AliasBuilder withSearchRouting(String searchRouting) { + this.searchRouting = searchRouting; + return this; + } + + public AliasBuilder withIndexRouting(String indexRouting) { + this.indexRouting = indexRouting; + return this; + } + + public AliasBuilder withRouting(String routing) { + this.routing = routing; + return this; + } + + public AliasQuery build() { + AliasQuery aliasQuery = new AliasQuery(); + aliasQuery.setIndexName(indexName); + aliasQuery.setAliasName(aliasName); + aliasQuery.setFilterBuilder(filterBuilder); + aliasQuery.setFilter(filter); + aliasQuery.setSearchRouting(searchRouting); + aliasQuery.setIndexRouting(indexRouting); + aliasQuery.setRouting(routing); + return aliasQuery; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/AliasQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/AliasQuery.java index 1a55f638..4b65c72e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/AliasQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/AliasQuery.java @@ -1,92 +1,92 @@ -/* - * Copyright 2013-2014 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.query; - -import java.util.Map; - -import org.elasticsearch.index.query.QueryBuilder; - -/** - * AliasQuery is useful for creating new alias or deleting existing ones - * - * @author Mohsin Husen - */ -public class AliasQuery { - - private String indexName; - private String aliasName; - private QueryBuilder filterBuilder; - private Map filter; - private String searchRouting; - private String indexRouting; - private String routing; - - public String getIndexName() { - return indexName; - } - - public void setIndexName(String indexName) { - this.indexName = indexName; - } - - public String getAliasName() { - return aliasName; - } - - public void setAliasName(String aliasName) { - this.aliasName = aliasName; - } - - public QueryBuilder getFilterBuilder() { - return filterBuilder; - } - - public void setFilterBuilder(QueryBuilder filterBuilder) { - this.filterBuilder = filterBuilder; - } - - public Map getFilter() { - return filter; - } - - public void setFilter(Map filter) { - this.filter = filter; - } - - public String getSearchRouting() { - return searchRouting; - } - - public void setSearchRouting(String searchRouting) { - this.searchRouting = searchRouting; - } - - public String getIndexRouting() { - return indexRouting; - } - - public void setIndexRouting(String indexRouting) { - this.indexRouting = indexRouting; - } - - public String getRouting() { - return routing; - } - - public void setRouting(String routing) { - this.routing = routing; - } -} +/* + * Copyright 2013-2014 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.query; + +import java.util.Map; + +import org.elasticsearch.index.query.QueryBuilder; + +/** + * AliasQuery is useful for creating new alias or deleting existing ones + * + * @author Mohsin Husen + */ +public class AliasQuery { + + private String indexName; + private String aliasName; + private QueryBuilder filterBuilder; + private Map filter; + private String searchRouting; + private String indexRouting; + private String routing; + + public String getIndexName() { + return indexName; + } + + public void setIndexName(String indexName) { + this.indexName = indexName; + } + + public String getAliasName() { + return aliasName; + } + + public void setAliasName(String aliasName) { + this.aliasName = aliasName; + } + + public QueryBuilder getFilterBuilder() { + return filterBuilder; + } + + public void setFilterBuilder(QueryBuilder filterBuilder) { + this.filterBuilder = filterBuilder; + } + + public Map getFilter() { + return filter; + } + + public void setFilter(Map filter) { + this.filter = filter; + } + + public String getSearchRouting() { + return searchRouting; + } + + public void setSearchRouting(String searchRouting) { + this.searchRouting = searchRouting; + } + + public String getIndexRouting() { + return indexRouting; + } + + public void setIndexRouting(String indexRouting) { + this.indexRouting = indexRouting; + } + + public String getRouting() { + return routing; + } + + public void setRouting(String routing) { + this.routing = routing; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java b/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java index f3e665a8..4e240fc4 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java @@ -1,619 +1,619 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -import java.util.*; - -import org.apache.commons.lang.StringUtils; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.elasticsearch.core.geo.GeoBox; -import org.springframework.data.elasticsearch.core.geo.GeoPoint; -import org.springframework.data.geo.Box; -import org.springframework.data.geo.Distance; -import org.springframework.data.geo.Point; -import org.springframework.util.Assert; - -/** - * Criteria is the central class when constructing queries. It follows more or less a fluent API style, which allows to - * easily chain together multiple criteria. - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Franck Marchand - */ -public class Criteria { - - @Override - public String toString() { - return "Criteria{" + - "field=" + field.getName() + - ", boost=" + boost + - ", negating=" + negating + - ", queryCriteria=" + StringUtils.join(queryCriteria, '|') + - ", filterCriteria=" + StringUtils.join(filterCriteria, '|') + - '}'; - } - - public static final String WILDCARD = "*"; - public static final String CRITERIA_VALUE_SEPERATOR = " "; - - private static final String OR_OPERATOR = " OR "; - private static final String AND_OPERATOR = " AND "; - - private Field field; - private float boost = Float.NaN; - private boolean negating = false; - - private List criteriaChain = new ArrayList(1); - - private Set queryCriteria = new LinkedHashSet(); - - private Set filterCriteria = new LinkedHashSet(); - - public Criteria() { - } - - /** - * Creates a new Criteria with provided field name - * - * @param fieldname - */ - public Criteria(String fieldname) { - this(new SimpleField(fieldname)); - } - - /** - * Creates a new Criteria for the given field - * - * @param field - */ - public Criteria(Field field) { - Assert.notNull(field, "Field for criteria must not be null"); - Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty"); - this.criteriaChain.add(this); - this.field = field; - } - - protected Criteria(List criteriaChain, String fieldname) { - this(criteriaChain, new SimpleField(fieldname)); - } - - protected Criteria(List criteriaChain, Field field) { - Assert.notNull(criteriaChain, "CriteriaChain must not be null"); - Assert.notNull(field, "Field for criteria must not be null"); - Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty"); - - this.criteriaChain.addAll(criteriaChain); - this.criteriaChain.add(this); - this.field = field; - } - - /** - * Static factory method to create a new Criteria for field with given name - * - * @param field - * @return - */ - public static Criteria where(String field) { - return where(new SimpleField(field)); - } - - /** - * Static factory method to create a new Criteria for provided field - * - * @param field - * @return - */ - public static Criteria where(Field field) { - return new Criteria(field); - } - - /** - * Chain using {@code AND} - * - * @param field - * @return - */ - public Criteria and(Field field) { - return new Criteria(this.criteriaChain, field); - } - - /** - * Chain using {@code AND} - * - * @param fieldName - * @return - */ - public Criteria and(String fieldName) { - return new Criteria(this.criteriaChain, fieldName); - } - - /** - * Chain using {@code AND} - * - * @param criteria - * @return - */ - public Criteria and(Criteria criteria) { - this.criteriaChain.add(criteria); - return this; - } - - /** - * Chain using {@code AND} - * - * @param criterias - * @return - */ - public Criteria and(Criteria... criterias) { - this.criteriaChain.addAll(Arrays.asList(criterias)); - return this; - } - - /** - * Chain using {@code OR} - * - * @param field - * @return - */ - public Criteria or(Field field) { - return new OrCriteria(this.criteriaChain, field); - } - - /** - * Chain using {@code OR} - * - * @param criteria - * @return - */ - public Criteria or(Criteria criteria) { - Assert.notNull(criteria, "Cannot chain 'null' criteria."); - - Criteria orConnectedCritiera = new OrCriteria(this.criteriaChain, criteria.getField()); - orConnectedCritiera.queryCriteria.addAll(criteria.queryCriteria); - return orConnectedCritiera; - } - - /** - * Chain using {@code OR} - * - * @param fieldName - * @return - */ - public Criteria or(String fieldName) { - return or(new SimpleField(fieldName)); - } - - /** - * Crates new CriteriaEntry without any wildcards - * - * @param o - * @return - */ - public Criteria is(Object o) { - queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o)); - return this; - } - - /** - * Crates new CriteriaEntry with leading and trailing wildcards
- * NOTE: mind your schema as leading wildcards may not be supported and/or execution might be slow. - * - * @param s - * @return - */ - public Criteria contains(String s) { - assertNoBlankInWildcardedQuery(s, true, true); - queryCriteria.add(new CriteriaEntry(OperationKey.CONTAINS, s)); - return this; - } - - /** - * Crates new CriteriaEntry with trailing wildcard - * - * @param s - * @return - */ - public Criteria startsWith(String s) { - assertNoBlankInWildcardedQuery(s, true, false); - queryCriteria.add(new CriteriaEntry(OperationKey.STARTS_WITH, s)); - return this; - } - - /** - * Crates new CriteriaEntry with leading wildcard
- * NOTE: mind your schema and execution times as leading wildcards may not be supported. - * - * @param s - * @return - */ - public Criteria endsWith(String s) { - assertNoBlankInWildcardedQuery(s, false, true); - queryCriteria.add(new CriteriaEntry(OperationKey.ENDS_WITH, s)); - return this; - } - - /** - * Crates new CriteriaEntry with trailing - - * - * @return - */ - public Criteria not() { - this.negating = true; - return this; - } - - /** - * Crates new CriteriaEntry with trailing ~ - * - * @param s - * @return - */ - public Criteria fuzzy(String s) { - queryCriteria.add(new CriteriaEntry(OperationKey.FUZZY, s)); - return this; - } - - /** - * Crates new CriteriaEntry allowing native elasticsearch expressions - * - * @param s - * @return - */ - public Criteria expression(String s) { - queryCriteria.add(new CriteriaEntry(OperationKey.EXPRESSION, s)); - return this; - } - - /** - * Boost positive hit with given factor. eg. ^2.3 - * - * @param boost - * @return - */ - public Criteria boost(float boost) { - if (boost < 0) { - throw new InvalidDataAccessApiUsageException("Boost must not be negative."); - } - this.boost = boost; - return this; - } - - /** - * Crates new CriteriaEntry for {@code RANGE [lowerBound TO upperBound]} - * - * @param lowerBound - * @param upperBound - * @return - */ - public Criteria between(Object lowerBound, Object upperBound) { - if (lowerBound == null && upperBound == null) { - throw new InvalidDataAccessApiUsageException("Range [* TO *] is not allowed"); - } - - queryCriteria.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[]{lowerBound, upperBound})); - return this; - } - - /** - * Crates new CriteriaEntry for {@code RANGE [* TO upperBound]} - * - * @param upperBound - * @return - */ - public Criteria lessThanEqual(Object upperBound) { - if (upperBound == null) { - throw new InvalidDataAccessApiUsageException("UpperBound can't be null"); - } - queryCriteria.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound)); - return this; - } - - public Criteria lessThan(Object upperBound) { - if (upperBound == null) { - throw new InvalidDataAccessApiUsageException("UpperBound can't be null"); - } - queryCriteria.add(new CriteriaEntry(OperationKey.LESS, upperBound)); - return this; - } - - /** - * Crates new CriteriaEntry for {@code RANGE [lowerBound TO *]} - * - * @param lowerBound - * @return - */ - public Criteria greaterThanEqual(Object lowerBound) { - if (lowerBound == null) { - throw new InvalidDataAccessApiUsageException("LowerBound can't be null"); - } - queryCriteria.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound)); - return this; - } - - public Criteria greaterThan(Object lowerBound) { - if (lowerBound == null) { - throw new InvalidDataAccessApiUsageException("LowerBound can't be null"); - } - queryCriteria.add(new CriteriaEntry(OperationKey.GREATER, lowerBound)); - return this; - } - - /** - * Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)} - * - * @param values - * @return - */ - public Criteria in(Object... values) { - return in(toCollection(values)); - } - - /** - * Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)} - * - * @param values the collection containing the values to match against - * @return - */ - public Criteria in(Iterable values) { - Assert.notNull(values, "Collection of 'in' values must not be null"); - queryCriteria.add(new CriteriaEntry(OperationKey.IN, values)); - return this; - } - - private List toCollection(Object... values) { - if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) { - throw new InvalidDataAccessApiUsageException("At least one element " - + (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "") - + " has to be present."); - } - return Arrays.asList(values); - } - - public Criteria notIn(Object... values) { - return notIn(toCollection(values)); - } - - public Criteria notIn(Iterable values) { - Assert.notNull(values, "Collection of 'NotIn' values must not be null"); - queryCriteria.add(new CriteriaEntry(OperationKey.NOT_IN, values)); - return this; - } - - /** - * Creates new CriteriaEntry for {@code location WITHIN distance} - * - * @param location {@link org.springframework.data.elasticsearch.core.geo.GeoPoint} center coordinates - * @param distance {@link String} radius as a string (e.g. : '100km'). - * Distance unit : - * either mi/miles or km can be set - * @return Criteria the chaind criteria with the new 'within' criteria included. - */ - public Criteria within(GeoPoint location, String distance) { - Assert.notNull(location, "Location value for near criteria must not be null"); - Assert.notNull(location, "Distance value for near criteria must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{location, distance})); - return this; - } - - /** - * Creates new CriteriaEntry for {@code location WITHIN distance} - * - * @param location {@link org.springframework.data.geo.Point} center coordinates - * @param distance {@link org.springframework.data.geo.Distance} radius - * . - * @return Criteria the chaind criteria with the new 'within' criteria included. - */ - public Criteria within(Point location, Distance distance) { - Assert.notNull(location, "Location value for near criteria must not be null"); - Assert.notNull(location, "Distance value for near criteria must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{location, distance})); - return this; - } - - /** - * Creates new CriteriaEntry for {@code geoLocation WITHIN distance} - * - * @param geoLocation {@link String} center point - * supported formats: - * lat on = > "41.2,45.1", - * geohash = > "asd9as0d" - * @param distance {@link String} radius as a string (e.g. : '100km'). - * Distance unit : - * either mi/miles or km can be set - * @return - */ - public Criteria within(String geoLocation, String distance) { - Assert.isTrue(StringUtils.isNotBlank(geoLocation), "geoLocation value must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{geoLocation, distance})); - return this; - } - - /** - * Creates new CriteriaEntry for {@code location GeoBox bounding box} - * - * @param boundingBox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner) - * @return Criteria the chaind criteria with the new 'boundingBox' criteria included. - */ - public Criteria boundedBy(GeoBox boundingBox) { - Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{boundingBox})); - return this; - } - - /** - * Creates new CriteriaEntry for {@code location Box bounding box} - * - * @param boundingBox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner) - * @return Criteria the chaind criteria with the new 'boundingBox' criteria included. - */ - public Criteria boundedBy(Box boundingBox) { - Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{boundingBox.getFirst(), boundingBox.getSecond()})); - return this; - } - - /** - * Creates new CriteriaEntry for bounding box created from points - * - * @param topLeftGeohash left top corner of bounding box as geohash - * @param bottomRightGeohash right bottom corner of bounding box as geohash - * @return Criteria the chaind criteria with the new 'boundedBy' criteria included. - */ - public Criteria boundedBy(String topLeftGeohash, String bottomRightGeohash) { - Assert.isTrue(StringUtils.isNotBlank(topLeftGeohash), "topLeftGeohash must not be empty"); - Assert.isTrue(StringUtils.isNotBlank(bottomRightGeohash), "bottomRightGeohash must not be empty"); - filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeftGeohash, bottomRightGeohash})); - return this; - } - - /** - * Creates new CriteriaEntry for bounding box created from points - * - * @param topLeftPoint left top corner of bounding box - * @param bottomRightPoint right bottom corner of bounding box - * @return Criteria the chaind criteria with the new 'boundedBy' criteria included. - */ - public Criteria boundedBy(GeoPoint topLeftPoint, GeoPoint bottomRightPoint) { - Assert.notNull(topLeftPoint, "topLeftPoint must not be null"); - Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeftPoint, bottomRightPoint})); - return this; - } - - public Criteria boundedBy(Point topLeftPoint, Point bottomRightPoint) { - Assert.notNull(topLeftPoint, "topLeftPoint must not be null"); - Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null"); - filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{GeoPoint.fromPoint(topLeftPoint), GeoPoint.fromPoint(bottomRightPoint)})); - return this; - } - - private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) { - if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) { - throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\"" - + searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use expression or multiple clauses instead."); - } - } - - /** - * Field targeted by this Criteria - * - * @return - */ - public Field getField() { - return this.field; - } - - public Set getQueryCriteriaEntries() { - return Collections.unmodifiableSet(this.queryCriteria); - } - - public Set getFilterCriteriaEntries() { - return Collections.unmodifiableSet(this.filterCriteria); - } - - public Set getFilterCriteria() { - return filterCriteria; - } - - /** - * Conjunction to be used with this criteria (AND | OR) - * - * @return - */ - public String getConjunctionOperator() { - return AND_OPERATOR; - } - - public List getCriteriaChain() { - return Collections.unmodifiableList(this.criteriaChain); - } - - public boolean isNegating() { - return this.negating; - } - - public boolean isAnd() { - return AND_OPERATOR == getConjunctionOperator(); - } - - public boolean isOr() { - return OR_OPERATOR == getConjunctionOperator(); - } - - public float getBoost() { - return this.boost; - } - - static class OrCriteria extends Criteria { - - public OrCriteria() { - super(); - } - - public OrCriteria(Field field) { - super(field); - } - - public OrCriteria(List criteriaChain, Field field) { - super(criteriaChain, field); - } - - public OrCriteria(List criteriaChain, String fieldname) { - super(criteriaChain, fieldname); - } - - public OrCriteria(String fieldname) { - super(fieldname); - } - - @Override - public String getConjunctionOperator() { - return OR_OPERATOR; - } - } - - public enum OperationKey { - EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, NOT_IN, WITHIN, BBOX, NEAR, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL; - } - - public static class CriteriaEntry { - - private OperationKey key; - private Object value; - - CriteriaEntry(OperationKey key, Object value) { - this.key = key; - this.value = value; - } - - public OperationKey getKey() { - return key; - } - - public Object getValue() { - return value; - } - - @Override - public String toString() { - return "CriteriaEntry{" + - "key=" + key + - ", value=" + value + - '}'; - } - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +import java.util.*; + +import org.apache.commons.lang.StringUtils; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.elasticsearch.core.geo.GeoBox; +import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.geo.Box; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; +import org.springframework.util.Assert; + +/** + * Criteria is the central class when constructing queries. It follows more or less a fluent API style, which allows to + * easily chain together multiple criteria. + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Franck Marchand + */ +public class Criteria { + + @Override + public String toString() { + return "Criteria{" + + "field=" + field.getName() + + ", boost=" + boost + + ", negating=" + negating + + ", queryCriteria=" + StringUtils.join(queryCriteria, '|') + + ", filterCriteria=" + StringUtils.join(filterCriteria, '|') + + '}'; + } + + public static final String WILDCARD = "*"; + public static final String CRITERIA_VALUE_SEPERATOR = " "; + + private static final String OR_OPERATOR = " OR "; + private static final String AND_OPERATOR = " AND "; + + private Field field; + private float boost = Float.NaN; + private boolean negating = false; + + private List criteriaChain = new ArrayList(1); + + private Set queryCriteria = new LinkedHashSet(); + + private Set filterCriteria = new LinkedHashSet(); + + public Criteria() { + } + + /** + * Creates a new Criteria with provided field name + * + * @param fieldname + */ + public Criteria(String fieldname) { + this(new SimpleField(fieldname)); + } + + /** + * Creates a new Criteria for the given field + * + * @param field + */ + public Criteria(Field field) { + Assert.notNull(field, "Field for criteria must not be null"); + Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty"); + this.criteriaChain.add(this); + this.field = field; + } + + protected Criteria(List criteriaChain, String fieldname) { + this(criteriaChain, new SimpleField(fieldname)); + } + + protected Criteria(List criteriaChain, Field field) { + Assert.notNull(criteriaChain, "CriteriaChain must not be null"); + Assert.notNull(field, "Field for criteria must not be null"); + Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty"); + + this.criteriaChain.addAll(criteriaChain); + this.criteriaChain.add(this); + this.field = field; + } + + /** + * Static factory method to create a new Criteria for field with given name + * + * @param field + * @return + */ + public static Criteria where(String field) { + return where(new SimpleField(field)); + } + + /** + * Static factory method to create a new Criteria for provided field + * + * @param field + * @return + */ + public static Criteria where(Field field) { + return new Criteria(field); + } + + /** + * Chain using {@code AND} + * + * @param field + * @return + */ + public Criteria and(Field field) { + return new Criteria(this.criteriaChain, field); + } + + /** + * Chain using {@code AND} + * + * @param fieldName + * @return + */ + public Criteria and(String fieldName) { + return new Criteria(this.criteriaChain, fieldName); + } + + /** + * Chain using {@code AND} + * + * @param criteria + * @return + */ + public Criteria and(Criteria criteria) { + this.criteriaChain.add(criteria); + return this; + } + + /** + * Chain using {@code AND} + * + * @param criterias + * @return + */ + public Criteria and(Criteria... criterias) { + this.criteriaChain.addAll(Arrays.asList(criterias)); + return this; + } + + /** + * Chain using {@code OR} + * + * @param field + * @return + */ + public Criteria or(Field field) { + return new OrCriteria(this.criteriaChain, field); + } + + /** + * Chain using {@code OR} + * + * @param criteria + * @return + */ + public Criteria or(Criteria criteria) { + Assert.notNull(criteria, "Cannot chain 'null' criteria."); + + Criteria orConnectedCritiera = new OrCriteria(this.criteriaChain, criteria.getField()); + orConnectedCritiera.queryCriteria.addAll(criteria.queryCriteria); + return orConnectedCritiera; + } + + /** + * Chain using {@code OR} + * + * @param fieldName + * @return + */ + public Criteria or(String fieldName) { + return or(new SimpleField(fieldName)); + } + + /** + * Crates new CriteriaEntry without any wildcards + * + * @param o + * @return + */ + public Criteria is(Object o) { + queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o)); + return this; + } + + /** + * Crates new CriteriaEntry with leading and trailing wildcards
+ * NOTE: mind your schema as leading wildcards may not be supported and/or execution might be slow. + * + * @param s + * @return + */ + public Criteria contains(String s) { + assertNoBlankInWildcardedQuery(s, true, true); + queryCriteria.add(new CriteriaEntry(OperationKey.CONTAINS, s)); + return this; + } + + /** + * Crates new CriteriaEntry with trailing wildcard + * + * @param s + * @return + */ + public Criteria startsWith(String s) { + assertNoBlankInWildcardedQuery(s, true, false); + queryCriteria.add(new CriteriaEntry(OperationKey.STARTS_WITH, s)); + return this; + } + + /** + * Crates new CriteriaEntry with leading wildcard
+ * NOTE: mind your schema and execution times as leading wildcards may not be supported. + * + * @param s + * @return + */ + public Criteria endsWith(String s) { + assertNoBlankInWildcardedQuery(s, false, true); + queryCriteria.add(new CriteriaEntry(OperationKey.ENDS_WITH, s)); + return this; + } + + /** + * Crates new CriteriaEntry with trailing - + * + * @return + */ + public Criteria not() { + this.negating = true; + return this; + } + + /** + * Crates new CriteriaEntry with trailing ~ + * + * @param s + * @return + */ + public Criteria fuzzy(String s) { + queryCriteria.add(new CriteriaEntry(OperationKey.FUZZY, s)); + return this; + } + + /** + * Crates new CriteriaEntry allowing native elasticsearch expressions + * + * @param s + * @return + */ + public Criteria expression(String s) { + queryCriteria.add(new CriteriaEntry(OperationKey.EXPRESSION, s)); + return this; + } + + /** + * Boost positive hit with given factor. eg. ^2.3 + * + * @param boost + * @return + */ + public Criteria boost(float boost) { + if (boost < 0) { + throw new InvalidDataAccessApiUsageException("Boost must not be negative."); + } + this.boost = boost; + return this; + } + + /** + * Crates new CriteriaEntry for {@code RANGE [lowerBound TO upperBound]} + * + * @param lowerBound + * @param upperBound + * @return + */ + public Criteria between(Object lowerBound, Object upperBound) { + if (lowerBound == null && upperBound == null) { + throw new InvalidDataAccessApiUsageException("Range [* TO *] is not allowed"); + } + + queryCriteria.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[]{lowerBound, upperBound})); + return this; + } + + /** + * Crates new CriteriaEntry for {@code RANGE [* TO upperBound]} + * + * @param upperBound + * @return + */ + public Criteria lessThanEqual(Object upperBound) { + if (upperBound == null) { + throw new InvalidDataAccessApiUsageException("UpperBound can't be null"); + } + queryCriteria.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound)); + return this; + } + + public Criteria lessThan(Object upperBound) { + if (upperBound == null) { + throw new InvalidDataAccessApiUsageException("UpperBound can't be null"); + } + queryCriteria.add(new CriteriaEntry(OperationKey.LESS, upperBound)); + return this; + } + + /** + * Crates new CriteriaEntry for {@code RANGE [lowerBound TO *]} + * + * @param lowerBound + * @return + */ + public Criteria greaterThanEqual(Object lowerBound) { + if (lowerBound == null) { + throw new InvalidDataAccessApiUsageException("LowerBound can't be null"); + } + queryCriteria.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound)); + return this; + } + + public Criteria greaterThan(Object lowerBound) { + if (lowerBound == null) { + throw new InvalidDataAccessApiUsageException("LowerBound can't be null"); + } + queryCriteria.add(new CriteriaEntry(OperationKey.GREATER, lowerBound)); + return this; + } + + /** + * Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)} + * + * @param values + * @return + */ + public Criteria in(Object... values) { + return in(toCollection(values)); + } + + /** + * Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)} + * + * @param values the collection containing the values to match against + * @return + */ + public Criteria in(Iterable values) { + Assert.notNull(values, "Collection of 'in' values must not be null"); + queryCriteria.add(new CriteriaEntry(OperationKey.IN, values)); + return this; + } + + private List toCollection(Object... values) { + if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) { + throw new InvalidDataAccessApiUsageException("At least one element " + + (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "") + + " has to be present."); + } + return Arrays.asList(values); + } + + public Criteria notIn(Object... values) { + return notIn(toCollection(values)); + } + + public Criteria notIn(Iterable values) { + Assert.notNull(values, "Collection of 'NotIn' values must not be null"); + queryCriteria.add(new CriteriaEntry(OperationKey.NOT_IN, values)); + return this; + } + + /** + * Creates new CriteriaEntry for {@code location WITHIN distance} + * + * @param location {@link org.springframework.data.elasticsearch.core.geo.GeoPoint} center coordinates + * @param distance {@link String} radius as a string (e.g. : '100km'). + * Distance unit : + * either mi/miles or km can be set + * @return Criteria the chaind criteria with the new 'within' criteria included. + */ + public Criteria within(GeoPoint location, String distance) { + Assert.notNull(location, "Location value for near criteria must not be null"); + Assert.notNull(location, "Distance value for near criteria must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{location, distance})); + return this; + } + + /** + * Creates new CriteriaEntry for {@code location WITHIN distance} + * + * @param location {@link org.springframework.data.geo.Point} center coordinates + * @param distance {@link org.springframework.data.geo.Distance} radius + * . + * @return Criteria the chaind criteria with the new 'within' criteria included. + */ + public Criteria within(Point location, Distance distance) { + Assert.notNull(location, "Location value for near criteria must not be null"); + Assert.notNull(location, "Distance value for near criteria must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{location, distance})); + return this; + } + + /** + * Creates new CriteriaEntry for {@code geoLocation WITHIN distance} + * + * @param geoLocation {@link String} center point + * supported formats: + * lat on = > "41.2,45.1", + * geohash = > "asd9as0d" + * @param distance {@link String} radius as a string (e.g. : '100km'). + * Distance unit : + * either mi/miles or km can be set + * @return + */ + public Criteria within(String geoLocation, String distance) { + Assert.isTrue(StringUtils.isNotBlank(geoLocation), "geoLocation value must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{geoLocation, distance})); + return this; + } + + /** + * Creates new CriteriaEntry for {@code location GeoBox bounding box} + * + * @param boundingBox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner) + * @return Criteria the chaind criteria with the new 'boundingBox' criteria included. + */ + public Criteria boundedBy(GeoBox boundingBox) { + Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{boundingBox})); + return this; + } + + /** + * Creates new CriteriaEntry for {@code location Box bounding box} + * + * @param boundingBox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner) + * @return Criteria the chaind criteria with the new 'boundingBox' criteria included. + */ + public Criteria boundedBy(Box boundingBox) { + Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{boundingBox.getFirst(), boundingBox.getSecond()})); + return this; + } + + /** + * Creates new CriteriaEntry for bounding box created from points + * + * @param topLeftGeohash left top corner of bounding box as geohash + * @param bottomRightGeohash right bottom corner of bounding box as geohash + * @return Criteria the chaind criteria with the new 'boundedBy' criteria included. + */ + public Criteria boundedBy(String topLeftGeohash, String bottomRightGeohash) { + Assert.isTrue(StringUtils.isNotBlank(topLeftGeohash), "topLeftGeohash must not be empty"); + Assert.isTrue(StringUtils.isNotBlank(bottomRightGeohash), "bottomRightGeohash must not be empty"); + filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeftGeohash, bottomRightGeohash})); + return this; + } + + /** + * Creates new CriteriaEntry for bounding box created from points + * + * @param topLeftPoint left top corner of bounding box + * @param bottomRightPoint right bottom corner of bounding box + * @return Criteria the chaind criteria with the new 'boundedBy' criteria included. + */ + public Criteria boundedBy(GeoPoint topLeftPoint, GeoPoint bottomRightPoint) { + Assert.notNull(topLeftPoint, "topLeftPoint must not be null"); + Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeftPoint, bottomRightPoint})); + return this; + } + + public Criteria boundedBy(Point topLeftPoint, Point bottomRightPoint) { + Assert.notNull(topLeftPoint, "topLeftPoint must not be null"); + Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null"); + filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{GeoPoint.fromPoint(topLeftPoint), GeoPoint.fromPoint(bottomRightPoint)})); + return this; + } + + private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) { + if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) { + throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\"" + + searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use expression or multiple clauses instead."); + } + } + + /** + * Field targeted by this Criteria + * + * @return + */ + public Field getField() { + return this.field; + } + + public Set getQueryCriteriaEntries() { + return Collections.unmodifiableSet(this.queryCriteria); + } + + public Set getFilterCriteriaEntries() { + return Collections.unmodifiableSet(this.filterCriteria); + } + + public Set getFilterCriteria() { + return filterCriteria; + } + + /** + * Conjunction to be used with this criteria (AND | OR) + * + * @return + */ + public String getConjunctionOperator() { + return AND_OPERATOR; + } + + public List getCriteriaChain() { + return Collections.unmodifiableList(this.criteriaChain); + } + + public boolean isNegating() { + return this.negating; + } + + public boolean isAnd() { + return AND_OPERATOR == getConjunctionOperator(); + } + + public boolean isOr() { + return OR_OPERATOR == getConjunctionOperator(); + } + + public float getBoost() { + return this.boost; + } + + static class OrCriteria extends Criteria { + + public OrCriteria() { + super(); + } + + public OrCriteria(Field field) { + super(field); + } + + public OrCriteria(List criteriaChain, Field field) { + super(criteriaChain, field); + } + + public OrCriteria(List criteriaChain, String fieldname) { + super(criteriaChain, fieldname); + } + + public OrCriteria(String fieldname) { + super(fieldname); + } + + @Override + public String getConjunctionOperator() { + return OR_OPERATOR; + } + } + + public enum OperationKey { + EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, NOT_IN, WITHIN, BBOX, NEAR, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL; + } + + public static class CriteriaEntry { + + private OperationKey key; + private Object value; + + CriteriaEntry(OperationKey key, Object value) { + this.key = key; + this.value = value; + } + + public OperationKey getKey() { + return key; + } + + public Object getValue() { + return value; + } + + @Override + public String toString() { + return "CriteriaEntry{" + + "key=" + key + + ", value=" + value + + '}'; + } + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/CriteriaQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/CriteriaQuery.java index d760e665..2adccc67 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/CriteriaQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/CriteriaQuery.java @@ -1,80 +1,80 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -import org.springframework.data.domain.Pageable; -import org.springframework.util.Assert; - -/** - * CriteriaQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class CriteriaQuery extends AbstractQuery { - - private Criteria criteria; - - private CriteriaQuery() { - } - - public CriteriaQuery(Criteria criteria) { - this(criteria, null); - } - - public CriteriaQuery(Criteria criteria, Pageable pageable) { - this.criteria = criteria; - this.pageable = pageable; - if (pageable != null) { - this.addSort(pageable.getSort()); - } - } - - public static final Query fromQuery(CriteriaQuery source) { - return fromQuery(source, new CriteriaQuery()); - } - - public static T fromQuery(CriteriaQuery source, T destination) { - if (source == null || destination == null) { - return null; - } - - if (source.getCriteria() != null) { - destination.addCriteria(source.getCriteria()); - } - - if (source.getSort() != null) { - destination.addSort(source.getSort()); - } - - return destination; - } - - @SuppressWarnings("unchecked") - public final T addCriteria(Criteria criteria) { - Assert.notNull(criteria, "Cannot add null criteria."); - if (this.criteria == null) { - this.criteria = criteria; - } else { - this.criteria.and(criteria); - } - return (T) this; - } - - public Criteria getCriteria() { - return this.criteria; - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +import org.springframework.data.domain.Pageable; +import org.springframework.util.Assert; + +/** + * CriteriaQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class CriteriaQuery extends AbstractQuery { + + private Criteria criteria; + + private CriteriaQuery() { + } + + public CriteriaQuery(Criteria criteria) { + this(criteria, null); + } + + public CriteriaQuery(Criteria criteria, Pageable pageable) { + this.criteria = criteria; + this.pageable = pageable; + if (pageable != null) { + this.addSort(pageable.getSort()); + } + } + + public static final Query fromQuery(CriteriaQuery source) { + return fromQuery(source, new CriteriaQuery()); + } + + public static T fromQuery(CriteriaQuery source, T destination) { + if (source == null || destination == null) { + return null; + } + + if (source.getCriteria() != null) { + destination.addCriteria(source.getCriteria()); + } + + if (source.getSort() != null) { + destination.addSort(source.getSort()); + } + + return destination; + } + + @SuppressWarnings("unchecked") + public final T addCriteria(Criteria criteria) { + Assert.notNull(criteria, "Cannot add null criteria."); + if (this.criteria == null) { + this.criteria = criteria; + } else { + this.criteria.and(criteria); + } + return (T) this; + } + + public Criteria getCriteria() { + return this.criteria; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/DeleteQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/DeleteQuery.java index d36a8bda..be2cae43 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/DeleteQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/DeleteQuery.java @@ -1,73 +1,73 @@ -/* - * 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.query; - -import org.elasticsearch.index.query.QueryBuilder; - -/** - * DeleteQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class DeleteQuery { - - private QueryBuilder query; - private String index; - private String type; - private Integer pageSize; - private Long scrollTimeInMillis; - - public QueryBuilder getQuery() { - return query; - } - - public void setQuery(QueryBuilder query) { - this.query = query; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Integer getPageSize() { - return pageSize; - } - - public void setPageSize(Integer pageSize) { - this.pageSize = pageSize; - } - - public Long getScrollTimeInMillis() { - return scrollTimeInMillis; - } - - public void setScrollTimeInMillis(Long scrollTimeInMillis) { - this.scrollTimeInMillis = scrollTimeInMillis; - } -} +/* + * 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.query; + +import org.elasticsearch.index.query.QueryBuilder; + +/** + * DeleteQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class DeleteQuery { + + private QueryBuilder query; + private String index; + private String type; + private Integer pageSize; + private Long scrollTimeInMillis; + + public QueryBuilder getQuery() { + return query; + } + + public void setQuery(QueryBuilder query) { + this.query = query; + } + + public String getIndex() { + return index; + } + + public void setIndex(String index) { + this.index = index; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Integer getPageSize() { + return pageSize; + } + + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + public Long getScrollTimeInMillis() { + return scrollTimeInMillis; + } + + public void setScrollTimeInMillis(Long scrollTimeInMillis) { + this.scrollTimeInMillis = scrollTimeInMillis; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/Field.java b/src/main/java/org/springframework/data/elasticsearch/core/query/Field.java index 0be8a336..33c097da 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/Field.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/Field.java @@ -1,32 +1,32 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -/** - * Defines a Field that can be used within a Criteria. - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public interface Field { - - /** - * Get the name of the field used in schema.xml of elasticsearch server - * - * @return - */ - String getName(); -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * Defines a Field that can be used within a Criteria. + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public interface Field { + + /** + * Get the name of the field used in schema.xml of elasticsearch server + * + * @return + */ + String getName(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/GetQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/GetQuery.java index 53dcd55d..c5409d5b 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/GetQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/GetQuery.java @@ -1,35 +1,35 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -/** - * GetQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class GetQuery { - - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * GetQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class GetQuery { + + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java index b3ffb167..69a0b911 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java @@ -1,90 +1,90 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -/** - * IndexQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class IndexQuery { - - private String id; - private Object object; - private Long version; - private String indexName; - private String type; - private String source; - private String parentId; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Object getObject() { - return object; - } - - public void setObject(Object object) { - this.object = object; - } - - public Long getVersion() { - return version; - } - - public void setVersion(Long version) { - this.version = version; - } - - public String getIndexName() { - return indexName; - } - - public void setIndexName(String indexName) { - this.indexName = indexName; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public String getParentId() { - return parentId; - } - - public void setParentId(String parentId) { - this.parentId = parentId; - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * IndexQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class IndexQuery { + + private String id; + private Object object; + private Long version; + private String indexName; + private String type; + private String source; + private String parentId; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Object getObject() { + return object; + } + + public void setObject(Object object) { + this.object = object; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getIndexName() { + return indexName; + } + + public void setIndexName(String indexName) { + this.indexName = indexName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/MoreLikeThisQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/MoreLikeThisQuery.java index 0a7f0da0..2143ca5d 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/MoreLikeThisQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/MoreLikeThisQuery.java @@ -1,188 +1,188 @@ -/* - * 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.query; - -import static java.util.Collections.addAll; -import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.data.domain.Pageable; - -/** - * MoreLikeThisQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public class MoreLikeThisQuery { - - private String id; - private String indexName; - private String type; - private List searchIndices = new ArrayList(); - private List searchTypes = new ArrayList(); - private List fields = new ArrayList(); - private String routing; - private Float percentTermsToMatch; - private Integer minTermFreq; - private Integer maxQueryTerms; - private List stopWords = new ArrayList(); - private Integer minDocFreq; - private Integer maxDocFreq; - private Integer minWordLen; - private Integer maxWordLen; - private Float boostTerms; - private Pageable pageable = DEFAULT_PAGE; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getIndexName() { - return indexName; - } - - public void setIndexName(String indexName) { - this.indexName = indexName; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getSearchIndices() { - return searchIndices; - } - - public void addSearchIndices(String... searchIndices) { - addAll(this.searchIndices, searchIndices); - } - - public List getSearchTypes() { - return searchTypes; - } - - public void addSearchTypes(String... searchTypes) { - addAll(this.searchTypes, searchTypes); - } - - public List getFields() { - return fields; - } - - public void addFields(String... fields) { - addAll(this.fields, fields); - } - - public String getRouting() { - return routing; - } - - public void setRouting(String routing) { - this.routing = routing; - } - - public Float getPercentTermsToMatch() { - return percentTermsToMatch; - } - - public void setPercentTermsToMatch(Float percentTermsToMatch) { - this.percentTermsToMatch = percentTermsToMatch; - } - - public Integer getMinTermFreq() { - return minTermFreq; - } - - public void setMinTermFreq(Integer minTermFreq) { - this.minTermFreq = minTermFreq; - } - - public Integer getMaxQueryTerms() { - return maxQueryTerms; - } - - public void setMaxQueryTerms(Integer maxQueryTerms) { - this.maxQueryTerms = maxQueryTerms; - } - - public List getStopWords() { - return stopWords; - } - - public void addStopWords(String... stopWords) { - addAll(this.stopWords, stopWords); - } - - public Integer getMinDocFreq() { - return minDocFreq; - } - - public void setMinDocFreq(Integer minDocFreq) { - this.minDocFreq = minDocFreq; - } - - public Integer getMaxDocFreq() { - return maxDocFreq; - } - - public void setMaxDocFreq(Integer maxDocFreq) { - this.maxDocFreq = maxDocFreq; - } - - public Integer getMinWordLen() { - return minWordLen; - } - - public void setMinWordLen(Integer minWordLen) { - this.minWordLen = minWordLen; - } - - public Integer getMaxWordLen() { - return maxWordLen; - } - - public void setMaxWordLen(Integer maxWordLen) { - this.maxWordLen = maxWordLen; - } - - public Float getBoostTerms() { - return boostTerms; - } - - public void setBoostTerms(Float boostTerms) { - this.boostTerms = boostTerms; - } - - public Pageable getPageable() { - return pageable; - } - - public void setPageable(Pageable pageable) { - this.pageable = pageable; - } -} +/* + * 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.query; + +import static java.util.Collections.addAll; +import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.domain.Pageable; + +/** + * MoreLikeThisQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public class MoreLikeThisQuery { + + private String id; + private String indexName; + private String type; + private List searchIndices = new ArrayList(); + private List searchTypes = new ArrayList(); + private List fields = new ArrayList(); + private String routing; + private Float percentTermsToMatch; + private Integer minTermFreq; + private Integer maxQueryTerms; + private List stopWords = new ArrayList(); + private Integer minDocFreq; + private Integer maxDocFreq; + private Integer minWordLen; + private Integer maxWordLen; + private Float boostTerms; + private Pageable pageable = DEFAULT_PAGE; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIndexName() { + return indexName; + } + + public void setIndexName(String indexName) { + this.indexName = indexName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getSearchIndices() { + return searchIndices; + } + + public void addSearchIndices(String... searchIndices) { + addAll(this.searchIndices, searchIndices); + } + + public List getSearchTypes() { + return searchTypes; + } + + public void addSearchTypes(String... searchTypes) { + addAll(this.searchTypes, searchTypes); + } + + public List getFields() { + return fields; + } + + public void addFields(String... fields) { + addAll(this.fields, fields); + } + + public String getRouting() { + return routing; + } + + public void setRouting(String routing) { + this.routing = routing; + } + + public Float getPercentTermsToMatch() { + return percentTermsToMatch; + } + + public void setPercentTermsToMatch(Float percentTermsToMatch) { + this.percentTermsToMatch = percentTermsToMatch; + } + + public Integer getMinTermFreq() { + return minTermFreq; + } + + public void setMinTermFreq(Integer minTermFreq) { + this.minTermFreq = minTermFreq; + } + + public Integer getMaxQueryTerms() { + return maxQueryTerms; + } + + public void setMaxQueryTerms(Integer maxQueryTerms) { + this.maxQueryTerms = maxQueryTerms; + } + + public List getStopWords() { + return stopWords; + } + + public void addStopWords(String... stopWords) { + addAll(this.stopWords, stopWords); + } + + public Integer getMinDocFreq() { + return minDocFreq; + } + + public void setMinDocFreq(Integer minDocFreq) { + this.minDocFreq = minDocFreq; + } + + public Integer getMaxDocFreq() { + return maxDocFreq; + } + + public void setMaxDocFreq(Integer maxDocFreq) { + this.maxDocFreq = maxDocFreq; + } + + public Integer getMinWordLen() { + return minWordLen; + } + + public void setMinWordLen(Integer minWordLen) { + this.minWordLen = minWordLen; + } + + public Integer getMaxWordLen() { + return maxWordLen; + } + + public void setMaxWordLen(Integer maxWordLen) { + this.maxWordLen = maxWordLen; + } + + public Float getBoostTerms() { + return boostTerms; + } + + public void setBoostTerms(Float boostTerms) { + this.boostTerms = boostTerms; + } + + public Pageable getPageable() { + return pageable; + } + + public void setPageable(Pageable pageable) { + this.pageable = pageable; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQuery.java index 265468bc..de7e0340 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQuery.java @@ -1,140 +1,140 @@ -/* - * 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.query; - -import java.util.ArrayList; -import java.util.List; - -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; -import org.elasticsearch.search.highlight.HighlightBuilder; -import org.elasticsearch.search.sort.SortBuilder; -import org.springframework.data.elasticsearch.core.facet.FacetRequest; - -import java.util.Arrays; - -/** - * NativeSearchQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - */ -public class NativeSearchQuery extends AbstractQuery implements SearchQuery { - - private QueryBuilder query; - private QueryBuilder filter; - private List sorts; - private final List scriptFields = new ArrayList(); - private List facets; - private List aggregations; - private HighlightBuilder.Field[] highlightFields; - private List indicesBoost; - - - public NativeSearchQuery(QueryBuilder query) { - this.query = query; - } - - public NativeSearchQuery(QueryBuilder query, QueryBuilder filter) { - this.query = query; - this.filter = filter; - } - - public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List sorts) { - this.query = query; - this.filter = filter; - this.sorts = sorts; - } - - public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List sorts, HighlightBuilder.Field[] highlightFields) { - this.query = query; - this.filter = filter; - this.sorts = sorts; - this.highlightFields = highlightFields; - } - - public QueryBuilder getQuery() { - return query; - } - - public QueryBuilder getFilter() { - return filter; - } - - public List getElasticsearchSorts() { - return sorts; - } - - @Override - public HighlightBuilder.Field[] getHighlightFields() { - return highlightFields; - } - - @Override - public List getScriptFields() { return scriptFields; } - - public void setScriptFields(List scriptFields) { - this.scriptFields.addAll(scriptFields); - } - - public void addScriptField(ScriptField... scriptField) { - scriptFields.addAll(Arrays.asList(scriptField)); - } - - public void addFacet(FacetRequest facetRequest) { - if (facets == null) { - facets = new ArrayList(); - } - facets.add(facetRequest); - } - - public void setFacets(List facets) { - this.facets = facets; - } - - @Override - public List getFacets() { - return facets; - } - - @Override - public List getAggregations() { - return aggregations; - } - - - public void addAggregation(AbstractAggregationBuilder aggregationBuilder) { - if (aggregations == null) { - aggregations = new ArrayList(); - } - aggregations.add(aggregationBuilder); - } - - public void setAggregations(List aggregations) { - this.aggregations = aggregations; - } - - @Override - public List getIndicesBoost() { - return indicesBoost; - } - - public void setIndicesBoost(List indicesBoost) { - this.indicesBoost = indicesBoost; - } - -} +/* + * 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.query; + +import java.util.ArrayList; +import java.util.List; + +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; +import org.elasticsearch.search.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.SortBuilder; +import org.springframework.data.elasticsearch.core.facet.FacetRequest; + +import java.util.Arrays; + +/** + * NativeSearchQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + */ +public class NativeSearchQuery extends AbstractQuery implements SearchQuery { + + private QueryBuilder query; + private QueryBuilder filter; + private List sorts; + private final List scriptFields = new ArrayList(); + private List facets; + private List aggregations; + private HighlightBuilder.Field[] highlightFields; + private List indicesBoost; + + + public NativeSearchQuery(QueryBuilder query) { + this.query = query; + } + + public NativeSearchQuery(QueryBuilder query, QueryBuilder filter) { + this.query = query; + this.filter = filter; + } + + public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List sorts) { + this.query = query; + this.filter = filter; + this.sorts = sorts; + } + + public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List sorts, HighlightBuilder.Field[] highlightFields) { + this.query = query; + this.filter = filter; + this.sorts = sorts; + this.highlightFields = highlightFields; + } + + public QueryBuilder getQuery() { + return query; + } + + public QueryBuilder getFilter() { + return filter; + } + + public List getElasticsearchSorts() { + return sorts; + } + + @Override + public HighlightBuilder.Field[] getHighlightFields() { + return highlightFields; + } + + @Override + public List getScriptFields() { return scriptFields; } + + public void setScriptFields(List scriptFields) { + this.scriptFields.addAll(scriptFields); + } + + public void addScriptField(ScriptField... scriptField) { + scriptFields.addAll(Arrays.asList(scriptField)); + } + + public void addFacet(FacetRequest facetRequest) { + if (facets == null) { + facets = new ArrayList(); + } + facets.add(facetRequest); + } + + public void setFacets(List facets) { + this.facets = facets; + } + + @Override + public List getFacets() { + return facets; + } + + @Override + public List getAggregations() { + return aggregations; + } + + + public void addAggregation(AbstractAggregationBuilder aggregationBuilder) { + if (aggregations == null) { + aggregations = new ArrayList(); + } + aggregations.add(aggregationBuilder); + } + + public void setAggregations(List aggregations) { + this.aggregations = aggregations; + } + + @Override + public List getIndicesBoost() { + return indicesBoost; + } + + public void setIndicesBoost(List indicesBoost) { + this.indicesBoost = indicesBoost; + } + +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java index 1e159c34..8b0d5548 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java @@ -1,199 +1,199 @@ -/* - * 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.query; - -import static org.springframework.util.CollectionUtils.isEmpty; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import org.elasticsearch.action.search.SearchType; -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; -import org.elasticsearch.search.highlight.HighlightBuilder; -import org.elasticsearch.search.sort.SortBuilder; -import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.facet.FacetRequest; - -/** - * NativeSearchQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - */ - -public class NativeSearchQueryBuilder { - - private QueryBuilder queryBuilder; - private QueryBuilder filterBuilder; - private List scriptFields = new ArrayList(); - private List sortBuilders = new ArrayList(); - private List facetRequests = new ArrayList(); - private List aggregationBuilders = new ArrayList(); - private HighlightBuilder.Field[] highlightFields; - private Pageable pageable; - private String[] indices; - private String[] types; - private String[] fields; - private SourceFilter sourceFilter; - private List indicesBoost; - private float minScore; - private Collection ids; - private String route; - private SearchType searchType; - - public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) { - this.queryBuilder = queryBuilder; - return this; - } - - public NativeSearchQueryBuilder withFilter(QueryBuilder filterBuilder) { - this.filterBuilder = filterBuilder; - return this; - } - - public NativeSearchQueryBuilder withSort(SortBuilder sortBuilder) { - this.sortBuilders.add(sortBuilder); - return this; - } - - public NativeSearchQueryBuilder withScriptField(ScriptField scriptField) { - this.scriptFields.add(scriptField); - return this; - } - - public NativeSearchQueryBuilder addAggregation(AbstractAggregationBuilder aggregationBuilder) { - this.aggregationBuilders.add(aggregationBuilder); - return this; - } - - public NativeSearchQueryBuilder withFacet(FacetRequest facetRequest) { - facetRequests.add(facetRequest); - return this; - } - - public NativeSearchQueryBuilder withHighlightFields(HighlightBuilder.Field... highlightFields) { - this.highlightFields = highlightFields; - return this; - } - - public NativeSearchQueryBuilder withIndicesBoost(List indicesBoost) { - this.indicesBoost = indicesBoost; - return this; - } - - public NativeSearchQueryBuilder withPageable(Pageable pageable) { - this.pageable = pageable; - return this; - } - - public NativeSearchQueryBuilder withIndices(String... indices) { - this.indices = indices; - return this; - } - - public NativeSearchQueryBuilder withTypes(String... types) { - this.types = types; - return this; - } - - public NativeSearchQueryBuilder withFields(String... fields) { - this.fields = fields; - return this; - } - - public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) { - this.sourceFilter = sourceFilter; - return this; - } - - public NativeSearchQueryBuilder withMinScore(float minScore) { - this.minScore = minScore; - return this; - } - - public NativeSearchQueryBuilder withIds(Collection ids) { - this.ids = ids; - return this; - } - - public NativeSearchQueryBuilder withRoute(String route) { - this.route = route; - return this; - } - - public NativeSearchQueryBuilder withSearchType(SearchType searchType) { - this.searchType = searchType; - return this; - } - - public NativeSearchQuery build() { - NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilders, highlightFields); - if (pageable != null) { - nativeSearchQuery.setPageable(pageable); - } - - if (indices != null) { - nativeSearchQuery.addIndices(indices); - } - - if (types != null) { - nativeSearchQuery.addTypes(types); - } - - if (fields != null) { - nativeSearchQuery.addFields(fields); - } - - if (sourceFilter != null) { - nativeSearchQuery.addSourceFilter(sourceFilter); - } - - if(indicesBoost != null) { - nativeSearchQuery.setIndicesBoost(indicesBoost); - } - - if (!isEmpty(scriptFields)) { - nativeSearchQuery.setScriptFields(scriptFields); - } - - if (!isEmpty(facetRequests)) { - nativeSearchQuery.setFacets(facetRequests); - } - - if (!isEmpty(aggregationBuilders)) { - nativeSearchQuery.setAggregations(aggregationBuilders); - } - - if (minScore > 0) { - nativeSearchQuery.setMinScore(minScore); - } - - if (ids != null) { - nativeSearchQuery.setIds(ids); - } - - if (route != null) { - nativeSearchQuery.setRoute(route); - } - - if (searchType != null) { - nativeSearchQuery.setSearchType(searchType); - } - - return nativeSearchQuery; - } -} +/* + * 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.query; + +import static org.springframework.util.CollectionUtils.isEmpty; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.elasticsearch.action.search.SearchType; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; +import org.elasticsearch.search.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.SortBuilder; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.core.facet.FacetRequest; + +/** + * NativeSearchQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + */ + +public class NativeSearchQueryBuilder { + + private QueryBuilder queryBuilder; + private QueryBuilder filterBuilder; + private List scriptFields = new ArrayList(); + private List sortBuilders = new ArrayList(); + private List facetRequests = new ArrayList(); + private List aggregationBuilders = new ArrayList(); + private HighlightBuilder.Field[] highlightFields; + private Pageable pageable; + private String[] indices; + private String[] types; + private String[] fields; + private SourceFilter sourceFilter; + private List indicesBoost; + private float minScore; + private Collection ids; + private String route; + private SearchType searchType; + + public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) { + this.queryBuilder = queryBuilder; + return this; + } + + public NativeSearchQueryBuilder withFilter(QueryBuilder filterBuilder) { + this.filterBuilder = filterBuilder; + return this; + } + + public NativeSearchQueryBuilder withSort(SortBuilder sortBuilder) { + this.sortBuilders.add(sortBuilder); + return this; + } + + public NativeSearchQueryBuilder withScriptField(ScriptField scriptField) { + this.scriptFields.add(scriptField); + return this; + } + + public NativeSearchQueryBuilder addAggregation(AbstractAggregationBuilder aggregationBuilder) { + this.aggregationBuilders.add(aggregationBuilder); + return this; + } + + public NativeSearchQueryBuilder withFacet(FacetRequest facetRequest) { + facetRequests.add(facetRequest); + return this; + } + + public NativeSearchQueryBuilder withHighlightFields(HighlightBuilder.Field... highlightFields) { + this.highlightFields = highlightFields; + return this; + } + + public NativeSearchQueryBuilder withIndicesBoost(List indicesBoost) { + this.indicesBoost = indicesBoost; + return this; + } + + public NativeSearchQueryBuilder withPageable(Pageable pageable) { + this.pageable = pageable; + return this; + } + + public NativeSearchQueryBuilder withIndices(String... indices) { + this.indices = indices; + return this; + } + + public NativeSearchQueryBuilder withTypes(String... types) { + this.types = types; + return this; + } + + public NativeSearchQueryBuilder withFields(String... fields) { + this.fields = fields; + return this; + } + + public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) { + this.sourceFilter = sourceFilter; + return this; + } + + public NativeSearchQueryBuilder withMinScore(float minScore) { + this.minScore = minScore; + return this; + } + + public NativeSearchQueryBuilder withIds(Collection ids) { + this.ids = ids; + return this; + } + + public NativeSearchQueryBuilder withRoute(String route) { + this.route = route; + return this; + } + + public NativeSearchQueryBuilder withSearchType(SearchType searchType) { + this.searchType = searchType; + return this; + } + + public NativeSearchQuery build() { + NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilders, highlightFields); + if (pageable != null) { + nativeSearchQuery.setPageable(pageable); + } + + if (indices != null) { + nativeSearchQuery.addIndices(indices); + } + + if (types != null) { + nativeSearchQuery.addTypes(types); + } + + if (fields != null) { + nativeSearchQuery.addFields(fields); + } + + if (sourceFilter != null) { + nativeSearchQuery.addSourceFilter(sourceFilter); + } + + if(indicesBoost != null) { + nativeSearchQuery.setIndicesBoost(indicesBoost); + } + + if (!isEmpty(scriptFields)) { + nativeSearchQuery.setScriptFields(scriptFields); + } + + if (!isEmpty(facetRequests)) { + nativeSearchQuery.setFacets(facetRequests); + } + + if (!isEmpty(aggregationBuilders)) { + nativeSearchQuery.setAggregations(aggregationBuilders); + } + + if (minScore > 0) { + nativeSearchQuery.setMinScore(minScore); + } + + if (ids != null) { + nativeSearchQuery.setIds(ids); + } + + if (route != null) { + nativeSearchQuery.setRoute(route); + } + + if (searchType != null) { + nativeSearchQuery.setSearchType(searchType); + } + + return nativeSearchQuery; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java b/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java index 8bde92f3..2018cf90 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java @@ -1,157 +1,157 @@ -/* - * 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.query; - -import java.util.Collection; -import java.util.List; - -import org.elasticsearch.action.search.SearchType; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; - -/** - * Query - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public interface Query { - - public static final int DEFAULT_PAGE_SIZE = 10; - public static final Pageable DEFAULT_PAGE = new PageRequest(0, DEFAULT_PAGE_SIZE); - - /** - * restrict result to entries on given page. Corresponds to the 'start' and 'rows' parameter in elasticsearch - * - * @param pageable - * @return - */ - T setPageable(Pageable pageable); - - /** - * Get filter queries if defined - * - * @return - */ - // List getFilterQueries(); - - /** - * Get page settings if defined - * - * @return - */ - Pageable getPageable(); - - /** - * Add {@link org.springframework.data.domain.Sort} to query - * - * @param sort - * @return - */ - T addSort(Sort sort); - - /** - * @return null if not set - */ - Sort getSort(); - - /** - * Get Indices to be searched - * - * @return - */ - List getIndices(); - - /** - * Add Indices to be added as part of search request - * - * @param indices - */ - void addIndices(String... indices); - - /** - * Add types to be searched - * - * @param types - */ - void addTypes(String... types); - - /** - * Get types to be searched - * - * @return - */ - List getTypes(); - - /** - * Add fields to be added as part of search request - * - * @param fields - */ - void addFields(String... fields); - - /** - * Get fields to be returned as part of search request - * - * @return - */ - List getFields(); - - /** - * Add source filter to be added as part of search request - * - * @param sourceFilter - */ - void addSourceFilter(SourceFilter sourceFilter); - - /** - * Get SourceFilter to be returned to get include and exclude source - * fields as part of search request. - * - * @return SourceFilter - */ - SourceFilter getSourceFilter(); - - /** - * Get minimum score - * - * @return - */ - float getMinScore(); - - /** - * Get Ids - * - * @return - */ - Collection getIds(); - - /** - * Get route - * - * @return - */ - String getRoute(); - - - /** - * Type of search - * - * @return - */ - SearchType getSearchType(); -} +/* + * 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.query; + +import java.util.Collection; +import java.util.List; + +import org.elasticsearch.action.search.SearchType; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +/** + * Query + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public interface Query { + + public static final int DEFAULT_PAGE_SIZE = 10; + public static final Pageable DEFAULT_PAGE = new PageRequest(0, DEFAULT_PAGE_SIZE); + + /** + * restrict result to entries on given page. Corresponds to the 'start' and 'rows' parameter in elasticsearch + * + * @param pageable + * @return + */ + T setPageable(Pageable pageable); + + /** + * Get filter queries if defined + * + * @return + */ + // List getFilterQueries(); + + /** + * Get page settings if defined + * + * @return + */ + Pageable getPageable(); + + /** + * Add {@link org.springframework.data.domain.Sort} to query + * + * @param sort + * @return + */ + T addSort(Sort sort); + + /** + * @return null if not set + */ + Sort getSort(); + + /** + * Get Indices to be searched + * + * @return + */ + List getIndices(); + + /** + * Add Indices to be added as part of search request + * + * @param indices + */ + void addIndices(String... indices); + + /** + * Add types to be searched + * + * @param types + */ + void addTypes(String... types); + + /** + * Get types to be searched + * + * @return + */ + List getTypes(); + + /** + * Add fields to be added as part of search request + * + * @param fields + */ + void addFields(String... fields); + + /** + * Get fields to be returned as part of search request + * + * @return + */ + List getFields(); + + /** + * Add source filter to be added as part of search request + * + * @param sourceFilter + */ + void addSourceFilter(SourceFilter sourceFilter); + + /** + * Get SourceFilter to be returned to get include and exclude source + * fields as part of search request. + * + * @return SourceFilter + */ + SourceFilter getSourceFilter(); + + /** + * Get minimum score + * + * @return + */ + float getMinScore(); + + /** + * Get Ids + * + * @return + */ + Collection getIds(); + + /** + * Get route + * + * @return + */ + String getRoute(); + + + /** + * Type of search + * + * @return + */ + SearchType getSearchType(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/SearchQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/SearchQuery.java index f3bfa9fa..9db08255 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/SearchQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/SearchQuery.java @@ -1,52 +1,52 @@ -/* - * 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.query; - -import java.util.List; - -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; -import org.elasticsearch.search.highlight.HighlightBuilder; -import org.elasticsearch.search.sort.SortBuilder; -import org.springframework.data.elasticsearch.core.facet.FacetRequest; - -/** - * NativeSearchQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - */ -public interface SearchQuery extends Query { - - QueryBuilder getQuery(); - - QueryBuilder getFilter(); - - List getElasticsearchSorts(); - - @Deprecated - List getFacets(); - - List getAggregations(); - - HighlightBuilder.Field[] getHighlightFields(); - - List getIndicesBoost(); - - List getScriptFields(); - -} +/* + * 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.query; + +import java.util.List; + +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; +import org.elasticsearch.search.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.SortBuilder; +import org.springframework.data.elasticsearch.core.facet.FacetRequest; + +/** + * NativeSearchQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + */ +public interface SearchQuery extends Query { + + QueryBuilder getQuery(); + + QueryBuilder getFilter(); + + List getElasticsearchSorts(); + + @Deprecated + List getFacets(); + + List getAggregations(); + + HighlightBuilder.Field[] getHighlightFields(); + + List getIndicesBoost(); + + List getScriptFields(); + +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/SimpleField.java b/src/main/java/org/springframework/data/elasticsearch/core/query/SimpleField.java index 494be9a6..c4bf7596 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/SimpleField.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/SimpleField.java @@ -1,41 +1,41 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -/** - * The most trivial implementation of a Field - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class SimpleField implements Field { - - private final String name; - - public SimpleField(String name) { - this.name = name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String toString() { - return this.name; - } +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * The most trivial implementation of a Field + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class SimpleField implements Field { + + private final String name; + + public SimpleField(String name) { + this.name = name; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String toString() { + return this.name; + } } \ No newline at end of file diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/StringQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/StringQuery.java index f0c49b68..5ad65075 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/StringQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/StringQuery.java @@ -1,49 +1,49 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.query; - -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; - -/** - * StringQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class StringQuery extends AbstractQuery { - - private String source; - - public StringQuery(String source) { - this.source = source; - } - - public StringQuery(String source, Pageable pageable) { - this.source = source; - this.pageable = pageable; - } - - public StringQuery(String source, Pageable pageable, Sort sort) { - this.pageable = pageable; - this.sort = sort; - this.source = source; - } - - public String getSource() { - return source; - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +/** + * StringQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class StringQuery extends AbstractQuery { + + private String source; + + public StringQuery(String source) { + this.source = source; + } + + public StringQuery(String source, Pageable pageable) { + this.source = source; + this.pageable = pageable; + } + + public StringQuery(String source, Pageable pageable, Sort sort) { + this.pageable = pageable; + this.sort = sort; + this.source = source; + } + + public String getSource() { + return source; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchCrudRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchCrudRepository.java index 2df696fb..cd74a985 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchCrudRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchCrudRepository.java @@ -1,33 +1,33 @@ -/* - * Copyright 2013-2014 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.repository; - -import java.io.Serializable; - -import org.springframework.data.repository.NoRepositoryBean; -import org.springframework.data.repository.PagingAndSortingRepository; - -/** - * @param - * @param - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Oliver Gierke - */ -@NoRepositoryBean -public interface ElasticsearchCrudRepository extends PagingAndSortingRepository { - -} +/* + * Copyright 2013-2014 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.repository; + +import java.io.Serializable; + +import org.springframework.data.repository.NoRepositoryBean; +import org.springframework.data.repository.PagingAndSortingRepository; + +/** + * @param + * @param + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Oliver Gierke + */ +@NoRepositoryBean +public interface ElasticsearchCrudRepository extends PagingAndSortingRepository { + +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java index 455c2821..a349058a 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java @@ -1,48 +1,48 @@ -/* - * 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.repository; - -import java.io.Serializable; - -import org.elasticsearch.index.query.QueryBuilder; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.query.SearchQuery; -import org.springframework.data.repository.NoRepositoryBean; - -/** - * @param - * @param - * @author Rizwan Idrees - * @author Mohsin Husen - */ -@NoRepositoryBean -public interface ElasticsearchRepository extends ElasticsearchCrudRepository { - - S index(S entity); - - Iterable search(QueryBuilder query); - - Page search(QueryBuilder query, Pageable pageable); - - Page search(SearchQuery searchQuery); - - Page searchSimilar(T entity, String[] fields, Pageable pageable); - - void refresh(); - - Class getEntityClass(); -} +/* + * 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.repository; + +import java.io.Serializable; + +import org.elasticsearch.index.query.QueryBuilder; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.data.repository.NoRepositoryBean; + +/** + * @param + * @param + * @author Rizwan Idrees + * @author Mohsin Husen + */ +@NoRepositoryBean +public interface ElasticsearchRepository extends ElasticsearchCrudRepository { + + S index(S entity); + + Iterable search(QueryBuilder query); + + Page search(QueryBuilder query, Pageable pageable); + + Page search(SearchQuery searchQuery); + + Page searchSimilar(T entity, String[] fields, Pageable pageable); + + void refresh(); + + Class getEntityClass(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryBean.java b/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryBean.java index 88daf135..30e981a2 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryBean.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryBean.java @@ -1,71 +1,71 @@ -/* - * Copyright 2013-2014 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.repository.cdi; - -import javax.enterprise.context.spi.CreationalContext; -import javax.enterprise.inject.spi.Bean; -import javax.enterprise.inject.spi.BeanManager; -import java.lang.annotation.Annotation; -import java.util.Set; - -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory; -import org.springframework.data.repository.cdi.CdiRepositoryBean; -import org.springframework.data.repository.config.CustomRepositoryImplementationDetector; -import org.springframework.util.Assert; - -/** - * Uses CdiRepositoryBean to create ElasticsearchRepository instances. - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Mark Paluch - */ -public class ElasticsearchRepositoryBean extends CdiRepositoryBean { - - private final Bean elasticsearchOperationsBean; - - /** - * Creates a new {@link ElasticsearchRepositoryBean}. - * - * @param operations must not be {@literal null}. - * @param qualifiers must not be {@literal null}. - * @param repositoryType must not be {@literal null}. - * @param beanManager must not be {@literal null}. - * @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations - * {@link CustomRepositoryImplementationDetector}, can be {@literal null}. - */ - public ElasticsearchRepositoryBean(Bean operations, Set qualifiers, - Class repositoryType, BeanManager beanManager, CustomRepositoryImplementationDetector detector) { - super(qualifiers, repositoryType, beanManager, detector); - - Assert.notNull(operations, "Cannot create repository with 'null' for ElasticsearchOperations."); - this.elasticsearchOperationsBean = operations; - } - - @Override - protected T create(CreationalContext creationalContext, Class repositoryType, Object customImplementation) { - ElasticsearchOperations elasticsearchOperations = getDependencyInstance(elasticsearchOperationsBean, - ElasticsearchOperations.class); - return new ElasticsearchRepositoryFactory(elasticsearchOperations).getRepository(repositoryType, - customImplementation); - } - - @Override - public Class getScope() { - return elasticsearchOperationsBean.getScope(); - } -} +/* + * Copyright 2013-2014 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.repository.cdi; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import java.lang.annotation.Annotation; +import java.util.Set; + +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory; +import org.springframework.data.repository.cdi.CdiRepositoryBean; +import org.springframework.data.repository.config.CustomRepositoryImplementationDetector; +import org.springframework.util.Assert; + +/** + * Uses CdiRepositoryBean to create ElasticsearchRepository instances. + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Mark Paluch + */ +public class ElasticsearchRepositoryBean extends CdiRepositoryBean { + + private final Bean elasticsearchOperationsBean; + + /** + * Creates a new {@link ElasticsearchRepositoryBean}. + * + * @param operations must not be {@literal null}. + * @param qualifiers must not be {@literal null}. + * @param repositoryType must not be {@literal null}. + * @param beanManager must not be {@literal null}. + * @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations + * {@link CustomRepositoryImplementationDetector}, can be {@literal null}. + */ + public ElasticsearchRepositoryBean(Bean operations, Set qualifiers, + Class repositoryType, BeanManager beanManager, CustomRepositoryImplementationDetector detector) { + super(qualifiers, repositoryType, beanManager, detector); + + Assert.notNull(operations, "Cannot create repository with 'null' for ElasticsearchOperations."); + this.elasticsearchOperationsBean = operations; + } + + @Override + protected T create(CreationalContext creationalContext, Class repositoryType, Object customImplementation) { + ElasticsearchOperations elasticsearchOperations = getDependencyInstance(elasticsearchOperationsBean, + ElasticsearchOperations.class); + return new ElasticsearchRepositoryFactory(elasticsearchOperations).getRepository(repositoryType, + customImplementation); + } + + @Override + public Class getScope() { + return elasticsearchOperationsBean.getScope(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryExtension.java b/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryExtension.java index 602d19ba..4e4adc15 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryExtension.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/cdi/ElasticsearchRepositoryExtension.java @@ -1,82 +1,82 @@ -/* - * 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.repository.cdi; - -import javax.enterprise.event.Observes; -import javax.enterprise.inject.UnsatisfiedResolutionException; -import javax.enterprise.inject.spi.AfterBeanDiscovery; -import javax.enterprise.inject.spi.Bean; -import javax.enterprise.inject.spi.BeanManager; -import javax.enterprise.inject.spi.ProcessBean; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.repository.cdi.CdiRepositoryBean; -import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport; - -/** - * CDI extension to export Elasticsearch repositories. - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Oliver Gierke - * @author Mark Paluch - */ -public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupport { - - private final Map, Bean> elasticsearchOperationsMap = new HashMap, Bean>(); - - @SuppressWarnings("unchecked") - void processBean(@Observes ProcessBean processBean) { - Bean bean = processBean.getBean(); - for (Type type : bean.getTypes()) { - if (type instanceof Class && ElasticsearchOperations.class.isAssignableFrom((Class) type)) { - elasticsearchOperationsMap.put(bean.getQualifiers(), ((Bean) bean)); - } - } - } - - void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) { - for (Entry, Set> entry : getRepositoryTypes()) { - - Class repositoryType = entry.getKey(); - Set qualifiers = entry.getValue(); - - CdiRepositoryBean repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager); - afterBeanDiscovery.addBean(repositoryBean); - registerBean(repositoryBean); - } - } - - private CdiRepositoryBean createRepositoryBean(Class repositoryType, Set qualifiers, - BeanManager beanManager) { - - Bean elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers); - - if (elasticsearchOperationsBean == null) { - throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.", - ElasticsearchOperations.class.getName(), qualifiers)); - } - - return new ElasticsearchRepositoryBean(elasticsearchOperationsBean, qualifiers, repositoryType, beanManager, - getCustomImplementationDetector()); - } -} +/* + * 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.repository.cdi; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.UnsatisfiedResolutionException; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.ProcessBean; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.repository.cdi.CdiRepositoryBean; +import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport; + +/** + * CDI extension to export Elasticsearch repositories. + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Oliver Gierke + * @author Mark Paluch + */ +public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupport { + + private final Map, Bean> elasticsearchOperationsMap = new HashMap, Bean>(); + + @SuppressWarnings("unchecked") + void processBean(@Observes ProcessBean processBean) { + Bean bean = processBean.getBean(); + for (Type type : bean.getTypes()) { + if (type instanceof Class && ElasticsearchOperations.class.isAssignableFrom((Class) type)) { + elasticsearchOperationsMap.put(bean.getQualifiers(), ((Bean) bean)); + } + } + } + + void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) { + for (Entry, Set> entry : getRepositoryTypes()) { + + Class repositoryType = entry.getKey(); + Set qualifiers = entry.getValue(); + + CdiRepositoryBean repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager); + afterBeanDiscovery.addBean(repositoryBean); + registerBean(repositoryBean); + } + } + + private CdiRepositoryBean createRepositoryBean(Class repositoryType, Set qualifiers, + BeanManager beanManager) { + + Bean elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers); + + if (elasticsearchOperationsBean == null) { + throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.", + ElasticsearchOperations.class.getName(), qualifiers)); + } + + return new ElasticsearchRepositoryBean(elasticsearchOperationsBean, qualifiers, repositoryType, beanManager, + getCustomImplementationDetector()); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractElasticsearchRepositoryQuery.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractElasticsearchRepositoryQuery.java index f2aafc6d..5f9a9b54 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractElasticsearchRepositoryQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractElasticsearchRepositoryQuery.java @@ -1,44 +1,44 @@ -/* - * 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.repository.query; - -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.repository.query.QueryMethod; -import org.springframework.data.repository.query.RepositoryQuery; - -/** - * AbstractElasticsearchRepositoryQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -public abstract class AbstractElasticsearchRepositoryQuery implements RepositoryQuery { - - protected ElasticsearchQueryMethod queryMethod; - protected ElasticsearchOperations elasticsearchOperations; - - public AbstractElasticsearchRepositoryQuery(ElasticsearchQueryMethod queryMethod, - ElasticsearchOperations elasticsearchOperations) { - this.queryMethod = queryMethod; - this.elasticsearchOperations = elasticsearchOperations; - } - - @Override - public QueryMethod getQueryMethod() { - return queryMethod; - } -} +/* + * 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.repository.query; + +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.repository.query.QueryMethod; +import org.springframework.data.repository.query.RepositoryQuery; + +/** + * AbstractElasticsearchRepositoryQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +public abstract class AbstractElasticsearchRepositoryQuery implements RepositoryQuery { + + protected ElasticsearchQueryMethod queryMethod; + protected ElasticsearchOperations elasticsearchOperations; + + public AbstractElasticsearchRepositoryQuery(ElasticsearchQueryMethod queryMethod, + ElasticsearchOperations elasticsearchOperations) { + this.queryMethod = queryMethod; + this.elasticsearchOperations = elasticsearchOperations; + } + + @Override + public QueryMethod getQueryMethod() { + return queryMethod; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java index cbc98ecc..1183471c 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java @@ -1,104 +1,104 @@ -/* - * 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.repository.query; - -import org.springframework.data.domain.PageRequest; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.elasticsearch.core.query.CriteriaQuery; -import org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.repository.query.ParametersParameterAccessor; -import org.springframework.data.repository.query.parser.PartTree; -import org.springframework.util.ClassUtils; -import org.springframework.data.util.CloseableIterator; -import org.springframework.data.util.StreamUtils; - -/** - * ElasticsearchPartQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Kevin Leturc - */ -public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery { - - private final PartTree tree; - private final MappingContext mappingContext; - - public ElasticsearchPartQuery(ElasticsearchQueryMethod method, ElasticsearchOperations elasticsearchOperations) { - super(method, elasticsearchOperations); - this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType()); - this.mappingContext = elasticsearchOperations.getElasticsearchConverter().getMappingContext(); - } - - @Override - public Object execute(Object[] parameters) { - ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters); - CriteriaQuery query = createQuery(accessor); - if(tree.isDelete()) { - Object result = countOrGetDocumentsForDelete(query, accessor); - elasticsearchOperations.delete(query, queryMethod.getEntityInformation().getJavaType()); - return result; - } else if (queryMethod.isPageQuery()) { - query.setPageable(accessor.getPageable()); - return elasticsearchOperations.queryForPage(query, queryMethod.getEntityInformation().getJavaType()); - } else if (queryMethod.isStreamQuery()) { - Class entityType = queryMethod.getEntityInformation().getJavaType(); - if (query.getPageable() == null) { - query.setPageable(new PageRequest(0, 20)); - } - - return StreamUtils.createStreamFromIterator((CloseableIterator) elasticsearchOperations.stream(query, entityType)); - - } else if (queryMethod.isCollectionQuery()) { - if (accessor.getPageable() == null) { - int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); - query.setPageable(new PageRequest(0, Math.max(1, itemCount))); - } else { - query.setPageable(accessor.getPageable()); - } - return elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType()); - } else if (tree.isCountProjection()) { - return elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); - } - return elasticsearchOperations.queryForObject(query, queryMethod.getEntityInformation().getJavaType()); - } - - private Object countOrGetDocumentsForDelete(CriteriaQuery query, ParametersParameterAccessor accessor) { - - Object result = null; - - if (queryMethod.isCollectionQuery()) { - if (accessor.getPageable() == null) { - int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); - query.setPageable(new PageRequest(0, Math.max(1, itemCount))); - } else { - query.setPageable(accessor.getPageable()); - } - result = elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType()); - } - - if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) { - result = elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); - } - return result; - } - - public CriteriaQuery createQuery(ParametersParameterAccessor accessor) { - return new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery(); - } -} +/* + * 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.repository.query; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.query.CriteriaQuery; +import org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.query.ParametersParameterAccessor; +import org.springframework.data.repository.query.parser.PartTree; +import org.springframework.util.ClassUtils; +import org.springframework.data.util.CloseableIterator; +import org.springframework.data.util.StreamUtils; + +/** + * ElasticsearchPartQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Kevin Leturc + */ +public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery { + + private final PartTree tree; + private final MappingContext mappingContext; + + public ElasticsearchPartQuery(ElasticsearchQueryMethod method, ElasticsearchOperations elasticsearchOperations) { + super(method, elasticsearchOperations); + this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType()); + this.mappingContext = elasticsearchOperations.getElasticsearchConverter().getMappingContext(); + } + + @Override + public Object execute(Object[] parameters) { + ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters); + CriteriaQuery query = createQuery(accessor); + if(tree.isDelete()) { + Object result = countOrGetDocumentsForDelete(query, accessor); + elasticsearchOperations.delete(query, queryMethod.getEntityInformation().getJavaType()); + return result; + } else if (queryMethod.isPageQuery()) { + query.setPageable(accessor.getPageable()); + return elasticsearchOperations.queryForPage(query, queryMethod.getEntityInformation().getJavaType()); + } else if (queryMethod.isStreamQuery()) { + Class entityType = queryMethod.getEntityInformation().getJavaType(); + if (query.getPageable() == null) { + query.setPageable(new PageRequest(0, 20)); + } + + return StreamUtils.createStreamFromIterator((CloseableIterator) elasticsearchOperations.stream(query, entityType)); + + } else if (queryMethod.isCollectionQuery()) { + if (accessor.getPageable() == null) { + int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); + query.setPageable(new PageRequest(0, Math.max(1, itemCount))); + } else { + query.setPageable(accessor.getPageable()); + } + return elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType()); + } else if (tree.isCountProjection()) { + return elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); + } + return elasticsearchOperations.queryForObject(query, queryMethod.getEntityInformation().getJavaType()); + } + + private Object countOrGetDocumentsForDelete(CriteriaQuery query, ParametersParameterAccessor accessor) { + + Object result = null; + + if (queryMethod.isCollectionQuery()) { + if (accessor.getPageable() == null) { + int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); + query.setPageable(new PageRequest(0, Math.max(1, itemCount))); + } else { + query.setPageable(accessor.getPageable()); + } + result = elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType()); + } + + if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) { + result = elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); + } + return result; + } + + public CriteriaQuery createQuery(ParametersParameterAccessor accessor) { + return new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchQueryMethod.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchQueryMethod.java index 8cb1c3fa..f08a2df9 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchQueryMethod.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchQueryMethod.java @@ -1,51 +1,51 @@ -/* - * Copyright 2013-2015 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.repository.query; - -import java.lang.reflect.Method; - -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.data.elasticsearch.annotations.Query; -import org.springframework.data.projection.ProjectionFactory; -import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.query.QueryMethod; -import org.springframework.util.StringUtils; - -/** - * ElasticsearchQueryMethod - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Oliver Gierke - */ -public class ElasticsearchQueryMethod extends QueryMethod { - - private final Query queryAnnotation; - - public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) { - super(method, metadata, factory); - this.queryAnnotation = method.getAnnotation(Query.class); - } - - public boolean hasAnnotatedQuery() { - return this.queryAnnotation != null; - } - - public String getAnnotatedQuery() { - String query = (String) AnnotationUtils.getValue(queryAnnotation, "value"); - return StringUtils.hasText(query) ? query : null; - } -} +/* + * Copyright 2013-2015 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.repository.query; + +import java.lang.reflect.Method; + +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.data.elasticsearch.annotations.Query; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.query.QueryMethod; +import org.springframework.util.StringUtils; + +/** + * ElasticsearchQueryMethod + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Oliver Gierke + */ +public class ElasticsearchQueryMethod extends QueryMethod { + + private final Query queryAnnotation; + + public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) { + super(method, metadata, factory); + this.queryAnnotation = method.getAnnotation(Query.class); + } + + public boolean hasAnnotatedQuery() { + return this.queryAnnotation != null; + } + + public String getAnnotatedQuery() { + String query = (String) AnnotationUtils.getValue(queryAnnotation, "value"); + return StringUtils.hasText(query) ? query : null; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java index 8bf2bcf9..63e68987 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java @@ -1,103 +1,103 @@ -/* - * 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.repository.query; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.springframework.core.convert.support.GenericConversionService; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.convert.DateTimeConverters; -import org.springframework.data.elasticsearch.core.query.StringQuery; -import org.springframework.data.repository.query.ParametersParameterAccessor; -import org.springframework.util.Assert; - -/** - * ElasticsearchStringQuery - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery { - - private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)"); - private String query; - - private final GenericConversionService conversionService = new GenericConversionService(); - - { - if (!conversionService.canConvert(java.util.Date.class, String.class)) { - conversionService.addConverter(DateTimeConverters.JavaDateConverter.INSTANCE); - } - if (!conversionService.canConvert(org.joda.time.ReadableInstant.class, String.class)) { - conversionService.addConverter(DateTimeConverters.JodaDateTimeConverter.INSTANCE); - } - if (!conversionService.canConvert(org.joda.time.LocalDateTime.class, String.class)) { - conversionService.addConverter(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE); - } - } - - public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod, - ElasticsearchOperations elasticsearchOperations, String query) { - super(queryMethod, elasticsearchOperations); - Assert.notNull(query, "Query cannot be empty"); - this.query = query; - } - - @Override - public Object execute(Object[] parameters) { - ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters); - StringQuery stringQuery = createQuery(accessor); - if (queryMethod.isPageQuery()) { - stringQuery.setPageable(accessor.getPageable()); - return elasticsearchOperations.queryForPage(stringQuery, queryMethod.getEntityInformation().getJavaType()); - } else if (queryMethod.isCollectionQuery()) { - if (accessor.getPageable() != null) { - stringQuery.setPageable(accessor.getPageable()); - } - return elasticsearchOperations.queryForList(stringQuery, queryMethod.getEntityInformation().getJavaType()); - } - - return elasticsearchOperations.queryForObject(stringQuery, queryMethod.getEntityInformation().getJavaType()); - } - - protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) { - String queryString = replacePlaceholders(this.query, parameterAccessor); - return new StringQuery(queryString); - } - - private String replacePlaceholders(String input, ParametersParameterAccessor accessor) { - Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input); - String result = input; - while (matcher.find()) { - String group = matcher.group(); - int index = Integer.parseInt(matcher.group(1)); - result = result.replace(group, getParameterWithIndex(accessor, index)); - } - return result; - } - - private String getParameterWithIndex(ParametersParameterAccessor accessor, int index) { - Object parameter = accessor.getBindableValue(index); - if (parameter == null) { - return "null"; - } - if (conversionService.canConvert(parameter.getClass(), String.class)) { - return conversionService.convert(parameter, String.class); - } - return parameter.toString(); - } -} +/* + * 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.repository.query; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.convert.DateTimeConverters; +import org.springframework.data.elasticsearch.core.query.StringQuery; +import org.springframework.data.repository.query.ParametersParameterAccessor; +import org.springframework.util.Assert; + +/** + * ElasticsearchStringQuery + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery { + + private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)"); + private String query; + + private final GenericConversionService conversionService = new GenericConversionService(); + + { + if (!conversionService.canConvert(java.util.Date.class, String.class)) { + conversionService.addConverter(DateTimeConverters.JavaDateConverter.INSTANCE); + } + if (!conversionService.canConvert(org.joda.time.ReadableInstant.class, String.class)) { + conversionService.addConverter(DateTimeConverters.JodaDateTimeConverter.INSTANCE); + } + if (!conversionService.canConvert(org.joda.time.LocalDateTime.class, String.class)) { + conversionService.addConverter(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE); + } + } + + public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod, + ElasticsearchOperations elasticsearchOperations, String query) { + super(queryMethod, elasticsearchOperations); + Assert.notNull(query, "Query cannot be empty"); + this.query = query; + } + + @Override + public Object execute(Object[] parameters) { + ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters); + StringQuery stringQuery = createQuery(accessor); + if (queryMethod.isPageQuery()) { + stringQuery.setPageable(accessor.getPageable()); + return elasticsearchOperations.queryForPage(stringQuery, queryMethod.getEntityInformation().getJavaType()); + } else if (queryMethod.isCollectionQuery()) { + if (accessor.getPageable() != null) { + stringQuery.setPageable(accessor.getPageable()); + } + return elasticsearchOperations.queryForList(stringQuery, queryMethod.getEntityInformation().getJavaType()); + } + + return elasticsearchOperations.queryForObject(stringQuery, queryMethod.getEntityInformation().getJavaType()); + } + + protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) { + String queryString = replacePlaceholders(this.query, parameterAccessor); + return new StringQuery(queryString); + } + + private String replacePlaceholders(String input, ParametersParameterAccessor accessor) { + Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input); + String result = input; + while (matcher.find()) { + String group = matcher.group(); + int index = Integer.parseInt(matcher.group(1)); + result = result.replace(group, getParameterWithIndex(accessor, index)); + } + return result; + } + + private String getParameterWithIndex(ParametersParameterAccessor accessor, int index) { + Object parameter = accessor.getBindableValue(index); + if (parameter == null) { + return "null"; + } + if (conversionService.canConvert(parameter.getClass(), String.class)) { + return conversionService.convert(parameter, String.class); + } + return parameter.toString(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java index 9b54f5f5..a5555c0d 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java @@ -1,195 +1,195 @@ -/* - * 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.repository.query.parser; - -import java.util.Collection; -import java.util.Iterator; - -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.domain.Sort; -import org.springframework.data.elasticsearch.core.geo.GeoBox; -import org.springframework.data.elasticsearch.core.geo.GeoPoint; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.elasticsearch.core.query.Criteria; -import org.springframework.data.elasticsearch.core.query.CriteriaQuery; -import org.springframework.data.geo.Box; -import org.springframework.data.geo.Distance; -import org.springframework.data.geo.Point; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.mapping.context.PersistentPropertyPath; -import org.springframework.data.repository.query.ParameterAccessor; -import org.springframework.data.repository.query.parser.AbstractQueryCreator; -import org.springframework.data.repository.query.parser.Part; -import org.springframework.data.repository.query.parser.PartTree; - -/** - * ElasticsearchQueryCreator - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Franck Marchand - * @author Artur Konczak - */ -public class ElasticsearchQueryCreator extends AbstractQueryCreator { - - private final MappingContext context; - - public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters, - MappingContext context) { - super(tree, parameters); - this.context = context; - } - - public ElasticsearchQueryCreator(PartTree tree, MappingContext context) { - super(tree); - this.context = context; - } - - @Override - protected CriteriaQuery create(Part part, Iterator iterator) { - PersistentPropertyPath path = context - .getPersistentPropertyPath(part.getProperty()); - return new CriteriaQuery(from(part, - new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); - } - - @Override - protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator iterator) { - if (base == null) { - return create(part, iterator); - } - PersistentPropertyPath path = context - .getPersistentPropertyPath(part.getProperty()); - return base.addCriteria(from(part, - new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); - } - - @Override - protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) { - return new CriteriaQuery(base.getCriteria().or(query.getCriteria())); - } - - @Override - protected CriteriaQuery complete(CriteriaQuery query, Sort sort) { - if (query == null) { - return null; - } - return query.addSort(sort); - } - - private Criteria from(Part part, Criteria instance, Iterator parameters) { - Part.Type type = part.getType(); - - Criteria criteria = instance; - if (criteria == null) { - criteria = new Criteria(); - } - switch (type) { - case TRUE: - return criteria.is(true); - case FALSE: - return criteria.is(false); - case NEGATING_SIMPLE_PROPERTY: - return criteria.is(parameters.next()).not(); - case REGEX: - return criteria.expression(parameters.next().toString()); - case LIKE: - case STARTING_WITH: - return criteria.startsWith(parameters.next().toString()); - case ENDING_WITH: - return criteria.endsWith(parameters.next().toString()); - case CONTAINING: - return criteria.contains(parameters.next().toString()); - case GREATER_THAN: - return criteria.greaterThan(parameters.next()); - case AFTER: - case GREATER_THAN_EQUAL: - return criteria.greaterThanEqual(parameters.next()); - case LESS_THAN: - return criteria.lessThan(parameters.next()); - case BEFORE: - case LESS_THAN_EQUAL: - return criteria.lessThanEqual(parameters.next()); - case BETWEEN: - return criteria.between(parameters.next(), parameters.next()); - case IN: - return criteria.in(asArray(parameters.next())); - case NOT_IN: - return criteria.notIn(asArray(parameters.next())); - case SIMPLE_PROPERTY: - case WITHIN: { - Object firstParameter = parameters.next(); - Object secondParameter = null; - if (type == Part.Type.SIMPLE_PROPERTY) { - if (part.getProperty().getType() != GeoPoint.class) - return criteria.is(firstParameter); - else { - // it means it's a simple find with exact geopoint matching (e.g. findByLocation) - // and because Elasticsearch does not have any kind of query with just a geopoint - // as argument we use a "geo distance" query with a distance of one meter. - secondParameter = ".001km"; - } - } else { - secondParameter = parameters.next(); - } - - if (firstParameter instanceof GeoPoint && secondParameter instanceof String) - return criteria.within((GeoPoint) firstParameter, (String) secondParameter); - - if (firstParameter instanceof Point && secondParameter instanceof Distance) - return criteria.within((Point) firstParameter, (Distance) secondParameter); - - if (firstParameter instanceof String && secondParameter instanceof String) - return criteria.within((String) firstParameter, (String) secondParameter); - } - case NEAR: { - Object firstParameter = parameters.next(); - - if (firstParameter instanceof GeoBox) { - return criteria.boundedBy((GeoBox) firstParameter); - } - - if (firstParameter instanceof Box) { - return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter)); - } - - Object secondParameter = parameters.next(); - - // "near" query can be the same query as the "within" query - if (firstParameter instanceof GeoPoint && secondParameter instanceof String) - return criteria.within((GeoPoint) firstParameter, (String) secondParameter); - - if (firstParameter instanceof Point && secondParameter instanceof Distance) - return criteria.within((Point) firstParameter, (Distance) secondParameter); - - if (firstParameter instanceof String && secondParameter instanceof String) - return criteria.within((String) firstParameter, (String) secondParameter); - } - - default: - throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'."); - } - } - - private Object[] asArray(Object o) { - if (o instanceof Collection) { - return ((Collection) o).toArray(); - } else if (o.getClass().isArray()) { - return (Object[]) o; - } - return new Object[]{o}; - } -} +/* + * 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.repository.query.parser; + +import java.util.Collection; +import java.util.Iterator; + +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.geo.GeoBox; +import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.query.Criteria; +import org.springframework.data.elasticsearch.core.query.CriteriaQuery; +import org.springframework.data.geo.Box; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.context.PersistentPropertyPath; +import org.springframework.data.repository.query.ParameterAccessor; +import org.springframework.data.repository.query.parser.AbstractQueryCreator; +import org.springframework.data.repository.query.parser.Part; +import org.springframework.data.repository.query.parser.PartTree; + +/** + * ElasticsearchQueryCreator + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Franck Marchand + * @author Artur Konczak + */ +public class ElasticsearchQueryCreator extends AbstractQueryCreator { + + private final MappingContext context; + + public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters, + MappingContext context) { + super(tree, parameters); + this.context = context; + } + + public ElasticsearchQueryCreator(PartTree tree, MappingContext context) { + super(tree); + this.context = context; + } + + @Override + protected CriteriaQuery create(Part part, Iterator iterator) { + PersistentPropertyPath path = context + .getPersistentPropertyPath(part.getProperty()); + return new CriteriaQuery(from(part, + new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); + } + + @Override + protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator iterator) { + if (base == null) { + return create(part, iterator); + } + PersistentPropertyPath path = context + .getPersistentPropertyPath(part.getProperty()); + return base.addCriteria(from(part, + new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); + } + + @Override + protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) { + return new CriteriaQuery(base.getCriteria().or(query.getCriteria())); + } + + @Override + protected CriteriaQuery complete(CriteriaQuery query, Sort sort) { + if (query == null) { + return null; + } + return query.addSort(sort); + } + + private Criteria from(Part part, Criteria instance, Iterator parameters) { + Part.Type type = part.getType(); + + Criteria criteria = instance; + if (criteria == null) { + criteria = new Criteria(); + } + switch (type) { + case TRUE: + return criteria.is(true); + case FALSE: + return criteria.is(false); + case NEGATING_SIMPLE_PROPERTY: + return criteria.is(parameters.next()).not(); + case REGEX: + return criteria.expression(parameters.next().toString()); + case LIKE: + case STARTING_WITH: + return criteria.startsWith(parameters.next().toString()); + case ENDING_WITH: + return criteria.endsWith(parameters.next().toString()); + case CONTAINING: + return criteria.contains(parameters.next().toString()); + case GREATER_THAN: + return criteria.greaterThan(parameters.next()); + case AFTER: + case GREATER_THAN_EQUAL: + return criteria.greaterThanEqual(parameters.next()); + case LESS_THAN: + return criteria.lessThan(parameters.next()); + case BEFORE: + case LESS_THAN_EQUAL: + return criteria.lessThanEqual(parameters.next()); + case BETWEEN: + return criteria.between(parameters.next(), parameters.next()); + case IN: + return criteria.in(asArray(parameters.next())); + case NOT_IN: + return criteria.notIn(asArray(parameters.next())); + case SIMPLE_PROPERTY: + case WITHIN: { + Object firstParameter = parameters.next(); + Object secondParameter = null; + if (type == Part.Type.SIMPLE_PROPERTY) { + if (part.getProperty().getType() != GeoPoint.class) + return criteria.is(firstParameter); + else { + // it means it's a simple find with exact geopoint matching (e.g. findByLocation) + // and because Elasticsearch does not have any kind of query with just a geopoint + // as argument we use a "geo distance" query with a distance of one meter. + secondParameter = ".001km"; + } + } else { + secondParameter = parameters.next(); + } + + if (firstParameter instanceof GeoPoint && secondParameter instanceof String) + return criteria.within((GeoPoint) firstParameter, (String) secondParameter); + + if (firstParameter instanceof Point && secondParameter instanceof Distance) + return criteria.within((Point) firstParameter, (Distance) secondParameter); + + if (firstParameter instanceof String && secondParameter instanceof String) + return criteria.within((String) firstParameter, (String) secondParameter); + } + case NEAR: { + Object firstParameter = parameters.next(); + + if (firstParameter instanceof GeoBox) { + return criteria.boundedBy((GeoBox) firstParameter); + } + + if (firstParameter instanceof Box) { + return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter)); + } + + Object secondParameter = parameters.next(); + + // "near" query can be the same query as the "within" query + if (firstParameter instanceof GeoPoint && secondParameter instanceof String) + return criteria.within((GeoPoint) firstParameter, (String) secondParameter); + + if (firstParameter instanceof Point && secondParameter instanceof Distance) + return criteria.within((Point) firstParameter, (Distance) secondParameter); + + if (firstParameter instanceof String && secondParameter instanceof String) + return criteria.within((String) firstParameter, (String) secondParameter); + } + + default: + throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'."); + } + } + + private Object[] asArray(Object o) { + if (o instanceof Collection) { + return ((Collection) o).toArray(); + } else if (o.getClass().isArray()) { + return (Object[]) o; + } + return new Object[]{o}; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java index 490706cf..176809a4 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java @@ -1,39 +1,39 @@ -/* - * 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.repository.support; - -import java.io.Serializable; - -import org.springframework.data.repository.core.EntityInformation; - -/** - * @param - * @param - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public interface ElasticsearchEntityInformation extends EntityInformation { - - String getIdAttribute(); - - String getIndexName(); - - String getType(); - - Long getVersion(T entity); - - String getParentId(T entity); -} +/* + * 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.repository.core.EntityInformation; + +/** + * @param + * @param + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public interface ElasticsearchEntityInformation extends EntityInformation { + + String getIdAttribute(); + + String getIndexName(); + + String getType(); + + Long getVersion(T entity); + + String getParentId(T entity); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreator.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreator.java index bec17ffb..f7acf538 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreator.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreator.java @@ -1,29 +1,29 @@ -/* - * 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.repository.support; - -import java.io.Serializable; - -/** - * ElasticsearchEntityInformationCreator - * - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public interface ElasticsearchEntityInformationCreator { - - ElasticsearchEntityInformation getEntityInformation(Class domainClass); -} +/* + * 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.repository.support; + +import java.io.Serializable; + +/** + * ElasticsearchEntityInformationCreator + * + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public interface ElasticsearchEntityInformationCreator { + + ElasticsearchEntityInformation getEntityInformation(Class domainClass); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreatorImpl.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreatorImpl.java index 6be8669f..05892a0e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreatorImpl.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformationCreatorImpl.java @@ -1,57 +1,57 @@ -/* - * 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.repository.support; - -import java.io.Serializable; - -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.util.Assert; - -/** - * ElasticsearchEntityInformationCreatorImpl - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Oliver Gierke - * @author Mark Paluch - */ -public class ElasticsearchEntityInformationCreatorImpl implements ElasticsearchEntityInformationCreator { - - private final MappingContext, ElasticsearchPersistentProperty> mappingContext; - - public ElasticsearchEntityInformationCreatorImpl( - MappingContext, ElasticsearchPersistentProperty> mappingContext) { - - Assert.notNull(mappingContext, "MappingContext must not be null!"); - - this.mappingContext = mappingContext; - } - - @Override - @SuppressWarnings("unchecked") - public ElasticsearchEntityInformation getEntityInformation(Class domainClass) { - - ElasticsearchPersistentEntity persistentEntity = (ElasticsearchPersistentEntity) mappingContext - .getPersistentEntity(domainClass); - - Assert.notNull(persistentEntity, String.format("Unable to obtain mapping metadata for %s!", domainClass)); - Assert.notNull(persistentEntity.getIdProperty(), String.format("No id property found for %s!", domainClass)); - - return new MappingElasticsearchEntityInformation(persistentEntity); - } -} +/* + * 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.util.Assert; + +/** + * ElasticsearchEntityInformationCreatorImpl + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Oliver Gierke + * @author Mark Paluch + */ +public class ElasticsearchEntityInformationCreatorImpl implements ElasticsearchEntityInformationCreator { + + private final MappingContext, ElasticsearchPersistentProperty> mappingContext; + + public ElasticsearchEntityInformationCreatorImpl( + MappingContext, ElasticsearchPersistentProperty> mappingContext) { + + Assert.notNull(mappingContext, "MappingContext must not be null!"); + + this.mappingContext = mappingContext; + } + + @Override + @SuppressWarnings("unchecked") + public ElasticsearchEntityInformation getEntityInformation(Class domainClass) { + + ElasticsearchPersistentEntity persistentEntity = (ElasticsearchPersistentEntity) mappingContext + .getPersistentEntity(domainClass); + + Assert.notNull(persistentEntity, String.format("Unable to obtain mapping metadata for %s!", domainClass)); + Assert.notNull(persistentEntity.getIdProperty(), String.format("No id property found for %s!", domainClass)); + + return new MappingElasticsearchEntityInformation(persistentEntity); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java index d43553de..0ff3fe48 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java @@ -1,101 +1,101 @@ -/* - * Copyright 2013-2015 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.repository.support; - -import java.io.Serializable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.repository.core.support.PersistentEntityInformation; -import org.springframework.util.Assert; - -/** - * Elasticsearch specific implementation of - * {@link org.springframework.data.repository.core.support.AbstractEntityInformation} - * - * @param - * @param - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Ryan Henszey - * @author Oliver Gierke - */ -public class MappingElasticsearchEntityInformation extends PersistentEntityInformation - implements ElasticsearchEntityInformation { - - private static final Logger logger = LoggerFactory.getLogger(MappingElasticsearchEntityInformation.class); - private final ElasticsearchPersistentEntity entityMetadata; - private final String indexName; - private final String type; - - public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity) { - this(entity, null, null); - } - - public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity, String indexName, String type) { - super(entity); - this.entityMetadata = entity; - this.indexName = indexName; - this.type = type; - } - - - @Override - public String getIdAttribute() { - Assert.notNull(entityMetadata.getIdProperty(), "Unable to identify 'id' property in class " - + entityMetadata.getType().getSimpleName() - + ". Make sure the 'id' property is annotated with @Id or named as 'id' or 'documentId' "); - return entityMetadata.getIdProperty().getFieldName(); - } - - @Override - public String getIndexName() { - return indexName != null ? indexName : entityMetadata.getIndexName(); - } - - @Override - public String getType() { - return type != null ? type : entityMetadata.getIndexType(); - } - - @Override - public Long getVersion(T entity) { - ElasticsearchPersistentProperty versionProperty = entityMetadata.getVersionProperty(); - try { - if (versionProperty != null) { - return (Long) entityMetadata.getPropertyAccessor(entity).getProperty(versionProperty); - } - } catch (Exception e) { - throw new IllegalStateException("failed to load version field", e); - } - return null; - } - - @Override - public String getParentId(T entity) { - ElasticsearchPersistentProperty parentProperty = entityMetadata.getParentIdProperty(); - try { - if (parentProperty != null) { - return (String) entityMetadata.getPropertyAccessor(entity).getProperty(parentProperty); - } - } catch (Exception e) { - throw new IllegalStateException("failed to load parent ID: " + e, e); - } - return null; - } -} +/* + * Copyright 2013-2015 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.repository.support; + +import java.io.Serializable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.repository.core.support.PersistentEntityInformation; +import org.springframework.util.Assert; + +/** + * Elasticsearch specific implementation of + * {@link org.springframework.data.repository.core.support.AbstractEntityInformation} + * + * @param + * @param + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Ryan Henszey + * @author Oliver Gierke + */ +public class MappingElasticsearchEntityInformation extends PersistentEntityInformation + implements ElasticsearchEntityInformation { + + private static final Logger logger = LoggerFactory.getLogger(MappingElasticsearchEntityInformation.class); + private final ElasticsearchPersistentEntity entityMetadata; + private final String indexName; + private final String type; + + public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity) { + this(entity, null, null); + } + + public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity, String indexName, String type) { + super(entity); + this.entityMetadata = entity; + this.indexName = indexName; + this.type = type; + } + + + @Override + public String getIdAttribute() { + Assert.notNull(entityMetadata.getIdProperty(), "Unable to identify 'id' property in class " + + entityMetadata.getType().getSimpleName() + + ". Make sure the 'id' property is annotated with @Id or named as 'id' or 'documentId' "); + return entityMetadata.getIdProperty().getFieldName(); + } + + @Override + public String getIndexName() { + return indexName != null ? indexName : entityMetadata.getIndexName(); + } + + @Override + public String getType() { + return type != null ? type : entityMetadata.getIndexType(); + } + + @Override + public Long getVersion(T entity) { + ElasticsearchPersistentProperty versionProperty = entityMetadata.getVersionProperty(); + try { + if (versionProperty != null) { + return (Long) entityMetadata.getPropertyAccessor(entity).getProperty(versionProperty); + } + } catch (Exception e) { + throw new IllegalStateException("failed to load version field", e); + } + return null; + } + + @Override + public String getParentId(T entity) { + ElasticsearchPersistentProperty parentProperty = entityMetadata.getParentIdProperty(); + try { + if (parentProperty != null) { + return (String) entityMetadata.getPropertyAccessor(entity).getProperty(parentProperty); + } + } catch (Exception e) { + throw new IllegalStateException("failed to load parent ID: " + e, e); + } + return null; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java index e6bef78b..25472b60 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java @@ -1,47 +1,47 @@ -/* - * 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.repository.support; - -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; - -/** - * Elasticsearch specific repository implementation. Likely to be used as target within - * {@link ElasticsearchRepositoryFactory} - * - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Ryan Henszey - */ -public class SimpleElasticsearchRepository extends AbstractElasticsearchRepository { - - public SimpleElasticsearchRepository() { - super(); - } - - public SimpleElasticsearchRepository(ElasticsearchEntityInformation metadata, - ElasticsearchOperations elasticsearchOperations) { - super(metadata, elasticsearchOperations); - } - - public SimpleElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) { - super(elasticsearchOperations); - } - - @Override - protected String stringIdRepresentation(String id) { - return id; - } -} +/* + * 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.repository.support; + +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; + +/** + * Elasticsearch specific repository implementation. Likely to be used as target within + * {@link ElasticsearchRepositoryFactory} + * + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Ryan Henszey + */ +public class SimpleElasticsearchRepository extends AbstractElasticsearchRepository { + + public SimpleElasticsearchRepository() { + super(); + } + + public SimpleElasticsearchRepository(ElasticsearchEntityInformation metadata, + ElasticsearchOperations elasticsearchOperations) { + super(metadata, elasticsearchOperations); + } + + public SimpleElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) { + super(elasticsearchOperations); + } + + @Override + protected String stringIdRepresentation(String id) { + return id; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java index cb9be54a..599cd987 100644 --- a/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java @@ -1,72 +1,72 @@ -/* - * Copyright 2014-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; - -import static org.apache.commons.lang.RandomStringUtils.*; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.entities.Author; -import org.springframework.data.elasticsearch.entities.Book; -import org.springframework.data.elasticsearch.repositories.book.SampleElasticSearchBookRepository; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Mohsin Husen - */ - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:/repository-test-nested-object.xml") -public class InnerObjectTests { - - @Autowired - private SampleElasticSearchBookRepository bookRepository; - - @Autowired - private ElasticsearchTemplate elasticsearchTemplate; - - @Before - public void before() { - elasticsearchTemplate.deleteIndex(Book.class); - elasticsearchTemplate.createIndex(Book.class); - elasticsearchTemplate.putMapping(Book.class); - elasticsearchTemplate.refresh(Book.class); - } - - @Test - public void shouldIndexInnerObject() { - // given - String id = randomAlphanumeric(5); - Book book = new Book(); - book.setId(id); - book.setName("xyz"); - Author author = new Author(); - author.setId("1"); - author.setName("ABC"); - book.setAuthor(author); - // when - bookRepository.save(book); - // then - assertThat(bookRepository.findOne(id), is(notNullValue())); - } -} +/* + * Copyright 2014-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; + +import static org.apache.commons.lang.RandomStringUtils.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.entities.Author; +import org.springframework.data.elasticsearch.entities.Book; +import org.springframework.data.elasticsearch.repositories.book.SampleElasticSearchBookRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Mohsin Husen + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:/repository-test-nested-object.xml") +public class InnerObjectTests { + + @Autowired + private SampleElasticSearchBookRepository bookRepository; + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(Book.class); + elasticsearchTemplate.createIndex(Book.class); + elasticsearchTemplate.putMapping(Book.class); + elasticsearchTemplate.refresh(Book.class); + } + + @Test + public void shouldIndexInnerObject() { + // given + String id = randomAlphanumeric(5); + Book book = new Book(); + book.setId(id); + book.setName("xyz"); + Author author = new Author(); + author.setId("1"); + author.setName("ABC"); + book.setAuthor(author); + // when + bookRepository.save(book); + // then + assertThat(bookRepository.findOne(id), is(notNullValue())); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java index b20b7d09..bc12d3ff 100644 --- a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java @@ -1,387 +1,387 @@ -/* - * 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; - -import static org.apache.commons.lang.RandomStringUtils.randomNumeric; -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.nestedQuery; -import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -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.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.core.query.GetQuery; -import org.springframework.data.elasticsearch.core.query.IndexQuery; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.data.elasticsearch.core.query.SearchQuery; -import org.springframework.data.elasticsearch.entities.Author; -import org.springframework.data.elasticsearch.entities.Book; -import org.springframework.data.elasticsearch.entities.Car; -import org.springframework.data.elasticsearch.entities.GirlFriend; -import org.springframework.data.elasticsearch.entities.Person; -import org.springframework.data.elasticsearch.entities.PersonMultipleLevelNested; -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 Artur Konczak - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:/repository-test-nested-object.xml") -public class NestedObjectTests { - - @Autowired - private ElasticsearchTemplate elasticsearchTemplate; - - - @Before - public void before() { - elasticsearchTemplate.deleteIndex(Book.class); - elasticsearchTemplate.createIndex(Book.class); - elasticsearchTemplate.putMapping(Book.class); - elasticsearchTemplate.refresh(Book.class); - elasticsearchTemplate.deleteIndex(Person.class); - elasticsearchTemplate.createIndex(Person.class); - elasticsearchTemplate.putMapping(Person.class); - elasticsearchTemplate.refresh(Person.class); - elasticsearchTemplate.deleteIndex(PersonMultipleLevelNested.class); - elasticsearchTemplate.createIndex(PersonMultipleLevelNested.class); - elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); - elasticsearchTemplate.refresh(PersonMultipleLevelNested.class); - } - - @Test - public void shouldIndexInitialLevelNestedObject() { - - final List cars = new ArrayList(); - - final Car saturn = new Car(); - saturn.setName("Saturn"); - saturn.setModel("SL"); - - final Car subaru = new Car(); - subaru.setName("Subaru"); - subaru.setModel("Imprezza"); - - final Car ford = new Car(); - ford.setName("Ford"); - ford.setModel("Focus"); - - cars.add(saturn); - cars.add(subaru); - cars.add(ford); - - final Person foo = new Person(); - foo.setName("Foo"); - foo.setId("1"); - foo.setCar(cars); - - final Car car = new Car(); - car.setName("Saturn"); - car.setModel("Imprezza"); - - final Person bar = new Person(); - bar.setId("2"); - bar.setName("Bar"); - bar.setCar(Arrays.asList(car)); - - final List indexQueries = new ArrayList(); - final IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(foo.getId()); - indexQuery1.setObject(foo); - - final IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(bar.getId()); - indexQuery2.setObject(bar); - - indexQueries.add(indexQuery1); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.putMapping(Person.class); - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(Person.class); - - final QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name", "saturn")).must(termQuery("car.model", "imprezza"))); - - final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build(); - final List persons = elasticsearchTemplate.queryForList(searchQuery, Person.class); - - assertThat(persons.size(), is(1)); - } - - @Test - public void shouldIndexMultipleLevelNestedObject() { - //given - final List indexQueries = createPerson(); - - //when - elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(PersonMultipleLevelNested.class); - - //then - final GetQuery getQuery = new GetQuery(); - getQuery.setId("1"); - final PersonMultipleLevelNested personIndexed = elasticsearchTemplate.queryForObject(getQuery, PersonMultipleLevelNested.class); - assertThat(personIndexed, is(notNullValue())); - } - - @Test - public void shouldIndexMultipleLevelNestedObjectWithIncludeInParent() { - //given - final List indexQueries = createPerson(); - - //when - elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); - elasticsearchTemplate.bulkIndex(indexQueries); - // then - - final Map mapping = elasticsearchTemplate.getMapping(PersonMultipleLevelNested.class); - - assertThat(mapping, is(notNullValue())); - final Map propertyMap = (Map) mapping.get("properties"); - assertThat(propertyMap, is(notNullValue())); - final Map bestCarsAttributes = (Map) propertyMap.get("bestCars"); - assertThat(bestCarsAttributes.get("include_in_parent"), is(notNullValue())); - } - - - @Test - public void shouldSearchUsingNestedQueryOnMultipleLevelNestedObject() { - //given - final List indexQueries = createPerson(); - - //when - elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(PersonMultipleLevelNested.class); - - //then - final BoolQueryBuilder builder = boolQuery(); - builder.must(nestedQuery("girlFriends", termQuery("girlFriends.type", "temp"))) - .must(nestedQuery("girlFriends.cars", termQuery("girlFriends.cars.name", "Ford".toLowerCase()))); - - final SearchQuery searchQuery = new NativeSearchQueryBuilder() - .withQuery(builder) - .build(); - - final Page personIndexed = elasticsearchTemplate.queryForPage(searchQuery, PersonMultipleLevelNested.class); - assertThat(personIndexed, is(notNullValue())); - assertThat(personIndexed.getTotalElements(), is(1L)); - assertThat(personIndexed.getContent().get(0).getId(), is("1")); - } - - - private List createPerson() { - - final PersonMultipleLevelNested person1 = new PersonMultipleLevelNested(); - - person1.setId("1"); - person1.setName("name"); - - final Car saturn = new Car(); - saturn.setName("Saturn"); - saturn.setModel("SL"); - - final Car subaru = new Car(); - subaru.setName("Subaru"); - subaru.setModel("Imprezza"); - - final Car car = new Car(); - car.setName("Saturn"); - car.setModel("Imprezza"); - - final Car ford = new Car(); - ford.setName("Ford"); - ford.setModel("Focus"); - - final GirlFriend permanent = new GirlFriend(); - permanent.setName("permanent"); - permanent.setType("permanent"); - permanent.setCars(Arrays.asList(saturn, subaru)); - - final GirlFriend temp = new GirlFriend(); - temp.setName("temp"); - temp.setType("temp"); - temp.setCars(Arrays.asList(car, ford)); - - person1.setGirlFriends(Arrays.asList(permanent, temp)); - - final IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(person1.getId()); - indexQuery1.setObject(person1); - - final PersonMultipleLevelNested person2 = new PersonMultipleLevelNested(); - - person2.setId("2"); - person2.setName("name"); - - person2.setGirlFriends(Arrays.asList(permanent)); - - final IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(person2.getId()); - indexQuery2.setObject(person2); - - final List indexQueries = new ArrayList(); - indexQueries.add(indexQuery1); - indexQueries.add(indexQuery2); - - return indexQueries; - } - - @Test - public void shouldSearchBooksForPersonInitialLevelNestedType() { - - final List cars = new ArrayList(); - - final Car saturn = new Car(); - saturn.setName("Saturn"); - saturn.setModel("SL"); - - final Car subaru = new Car(); - subaru.setName("Subaru"); - subaru.setModel("Imprezza"); - - final Car ford = new Car(); - ford.setName("Ford"); - ford.setModel("Focus"); - - cars.add(saturn); - cars.add(subaru); - cars.add(ford); - - final Book java = new Book(); - java.setId("1"); - java.setName("java"); - final Author javaAuthor = new Author(); - javaAuthor.setId("1"); - javaAuthor.setName("javaAuthor"); - java.setAuthor(javaAuthor); - - final Book spring = new Book(); - spring.setId("2"); - spring.setName("spring"); - final Author springAuthor = new Author(); - springAuthor.setId("2"); - springAuthor.setName("springAuthor"); - spring.setAuthor(springAuthor); - - final Person foo = new Person(); - foo.setName("Foo"); - foo.setId("1"); - foo.setCar(cars); - foo.setBooks(Arrays.asList(java, spring)); - - final Car car = new Car(); - car.setName("Saturn"); - car.setModel("Imprezza"); - - final Person bar = new Person(); - bar.setId("2"); - bar.setName("Bar"); - bar.setCar(Arrays.asList(car)); - - final List indexQueries = new ArrayList(); - final IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(foo.getId()); - indexQuery1.setObject(foo); - - final IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(bar.getId()); - indexQuery2.setObject(bar); - - indexQueries.add(indexQuery1); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.putMapping(Person.class); - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(Person.class); - - final QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java"))); - - final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build(); - final List persons = elasticsearchTemplate.queryForList(searchQuery, Person.class); - - assertThat(persons.size(), is(1)); - } - - /* - DATAES-73 - */ - @Test - public void shouldIndexAndSearchMapAsNestedType() { - //given - final Book book1 = new Book(); - final Book book2 = new Book(); - - book1.setId(randomNumeric(5)); - book1.setName("testBook1"); - - book2.setId(randomNumeric(5)); - book2.setName("testBook2"); - - final Map> map1 = new HashMap>(); - map1.put(1, Arrays.asList("test1", "test2")); - - final Map> map2 = new HashMap>(); - map2.put(1, Arrays.asList("test3", "test4")); - - book1.setBuckets(map1); - book2.setBuckets(map2); - - final List indexQueries = new ArrayList(); - final IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(book1.getId()); - indexQuery1.setObject(book1); - - final IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(book2.getId()); - indexQuery2.setObject(book2); - - indexQueries.add(indexQuery1); - indexQueries.add(indexQuery2); - //when - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(Book.class); - //then - final SearchQuery searchQuery = new NativeSearchQueryBuilder() - .withQuery(nestedQuery("buckets", termQuery("buckets.1", "test3"))) - .build(); - final Page books = elasticsearchTemplate.queryForPage(searchQuery, Book.class); - - assertThat(books.getContent().size(), is(1)); - assertThat(books.getContent().get(0).getId(), is(book2.getId())); - } -} - +/* + * 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; + +import static org.apache.commons.lang.RandomStringUtils.randomNumeric; +import static org.elasticsearch.index.query.QueryBuilders.boolQuery; +import static org.elasticsearch.index.query.QueryBuilders.nestedQuery; +import static org.elasticsearch.index.query.QueryBuilders.termQuery; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +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.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.query.GetQuery; +import org.springframework.data.elasticsearch.core.query.IndexQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.data.elasticsearch.entities.Author; +import org.springframework.data.elasticsearch.entities.Book; +import org.springframework.data.elasticsearch.entities.Car; +import org.springframework.data.elasticsearch.entities.GirlFriend; +import org.springframework.data.elasticsearch.entities.Person; +import org.springframework.data.elasticsearch.entities.PersonMultipleLevelNested; +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 Artur Konczak + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:/repository-test-nested-object.xml") +public class NestedObjectTests { + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(Book.class); + elasticsearchTemplate.createIndex(Book.class); + elasticsearchTemplate.putMapping(Book.class); + elasticsearchTemplate.refresh(Book.class); + elasticsearchTemplate.deleteIndex(Person.class); + elasticsearchTemplate.createIndex(Person.class); + elasticsearchTemplate.putMapping(Person.class); + elasticsearchTemplate.refresh(Person.class); + elasticsearchTemplate.deleteIndex(PersonMultipleLevelNested.class); + elasticsearchTemplate.createIndex(PersonMultipleLevelNested.class); + elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); + elasticsearchTemplate.refresh(PersonMultipleLevelNested.class); + } + + @Test + public void shouldIndexInitialLevelNestedObject() { + + final List cars = new ArrayList(); + + final Car saturn = new Car(); + saturn.setName("Saturn"); + saturn.setModel("SL"); + + final Car subaru = new Car(); + subaru.setName("Subaru"); + subaru.setModel("Imprezza"); + + final Car ford = new Car(); + ford.setName("Ford"); + ford.setModel("Focus"); + + cars.add(saturn); + cars.add(subaru); + cars.add(ford); + + final Person foo = new Person(); + foo.setName("Foo"); + foo.setId("1"); + foo.setCar(cars); + + final Car car = new Car(); + car.setName("Saturn"); + car.setModel("Imprezza"); + + final Person bar = new Person(); + bar.setId("2"); + bar.setName("Bar"); + bar.setCar(Arrays.asList(car)); + + final List indexQueries = new ArrayList(); + final IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(foo.getId()); + indexQuery1.setObject(foo); + + final IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(bar.getId()); + indexQuery2.setObject(bar); + + indexQueries.add(indexQuery1); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.putMapping(Person.class); + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(Person.class); + + final QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name", "saturn")).must(termQuery("car.model", "imprezza"))); + + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build(); + final List persons = elasticsearchTemplate.queryForList(searchQuery, Person.class); + + assertThat(persons.size(), is(1)); + } + + @Test + public void shouldIndexMultipleLevelNestedObject() { + //given + final List indexQueries = createPerson(); + + //when + elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(PersonMultipleLevelNested.class); + + //then + final GetQuery getQuery = new GetQuery(); + getQuery.setId("1"); + final PersonMultipleLevelNested personIndexed = elasticsearchTemplate.queryForObject(getQuery, PersonMultipleLevelNested.class); + assertThat(personIndexed, is(notNullValue())); + } + + @Test + public void shouldIndexMultipleLevelNestedObjectWithIncludeInParent() { + //given + final List indexQueries = createPerson(); + + //when + elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); + elasticsearchTemplate.bulkIndex(indexQueries); + // then + + final Map mapping = elasticsearchTemplate.getMapping(PersonMultipleLevelNested.class); + + assertThat(mapping, is(notNullValue())); + final Map propertyMap = (Map) mapping.get("properties"); + assertThat(propertyMap, is(notNullValue())); + final Map bestCarsAttributes = (Map) propertyMap.get("bestCars"); + assertThat(bestCarsAttributes.get("include_in_parent"), is(notNullValue())); + } + + + @Test + public void shouldSearchUsingNestedQueryOnMultipleLevelNestedObject() { + //given + final List indexQueries = createPerson(); + + //when + elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class); + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(PersonMultipleLevelNested.class); + + //then + final BoolQueryBuilder builder = boolQuery(); + builder.must(nestedQuery("girlFriends", termQuery("girlFriends.type", "temp"))) + .must(nestedQuery("girlFriends.cars", termQuery("girlFriends.cars.name", "Ford".toLowerCase()))); + + final SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(builder) + .build(); + + final Page personIndexed = elasticsearchTemplate.queryForPage(searchQuery, PersonMultipleLevelNested.class); + assertThat(personIndexed, is(notNullValue())); + assertThat(personIndexed.getTotalElements(), is(1L)); + assertThat(personIndexed.getContent().get(0).getId(), is("1")); + } + + + private List createPerson() { + + final PersonMultipleLevelNested person1 = new PersonMultipleLevelNested(); + + person1.setId("1"); + person1.setName("name"); + + final Car saturn = new Car(); + saturn.setName("Saturn"); + saturn.setModel("SL"); + + final Car subaru = new Car(); + subaru.setName("Subaru"); + subaru.setModel("Imprezza"); + + final Car car = new Car(); + car.setName("Saturn"); + car.setModel("Imprezza"); + + final Car ford = new Car(); + ford.setName("Ford"); + ford.setModel("Focus"); + + final GirlFriend permanent = new GirlFriend(); + permanent.setName("permanent"); + permanent.setType("permanent"); + permanent.setCars(Arrays.asList(saturn, subaru)); + + final GirlFriend temp = new GirlFriend(); + temp.setName("temp"); + temp.setType("temp"); + temp.setCars(Arrays.asList(car, ford)); + + person1.setGirlFriends(Arrays.asList(permanent, temp)); + + final IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(person1.getId()); + indexQuery1.setObject(person1); + + final PersonMultipleLevelNested person2 = new PersonMultipleLevelNested(); + + person2.setId("2"); + person2.setName("name"); + + person2.setGirlFriends(Arrays.asList(permanent)); + + final IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(person2.getId()); + indexQuery2.setObject(person2); + + final List indexQueries = new ArrayList(); + indexQueries.add(indexQuery1); + indexQueries.add(indexQuery2); + + return indexQueries; + } + + @Test + public void shouldSearchBooksForPersonInitialLevelNestedType() { + + final List cars = new ArrayList(); + + final Car saturn = new Car(); + saturn.setName("Saturn"); + saturn.setModel("SL"); + + final Car subaru = new Car(); + subaru.setName("Subaru"); + subaru.setModel("Imprezza"); + + final Car ford = new Car(); + ford.setName("Ford"); + ford.setModel("Focus"); + + cars.add(saturn); + cars.add(subaru); + cars.add(ford); + + final Book java = new Book(); + java.setId("1"); + java.setName("java"); + final Author javaAuthor = new Author(); + javaAuthor.setId("1"); + javaAuthor.setName("javaAuthor"); + java.setAuthor(javaAuthor); + + final Book spring = new Book(); + spring.setId("2"); + spring.setName("spring"); + final Author springAuthor = new Author(); + springAuthor.setId("2"); + springAuthor.setName("springAuthor"); + spring.setAuthor(springAuthor); + + final Person foo = new Person(); + foo.setName("Foo"); + foo.setId("1"); + foo.setCar(cars); + foo.setBooks(Arrays.asList(java, spring)); + + final Car car = new Car(); + car.setName("Saturn"); + car.setModel("Imprezza"); + + final Person bar = new Person(); + bar.setId("2"); + bar.setName("Bar"); + bar.setCar(Arrays.asList(car)); + + final List indexQueries = new ArrayList(); + final IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(foo.getId()); + indexQuery1.setObject(foo); + + final IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(bar.getId()); + indexQuery2.setObject(bar); + + indexQueries.add(indexQuery1); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.putMapping(Person.class); + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(Person.class); + + final QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java"))); + + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build(); + final List persons = elasticsearchTemplate.queryForList(searchQuery, Person.class); + + assertThat(persons.size(), is(1)); + } + + /* + DATAES-73 + */ + @Test + public void shouldIndexAndSearchMapAsNestedType() { + //given + final Book book1 = new Book(); + final Book book2 = new Book(); + + book1.setId(randomNumeric(5)); + book1.setName("testBook1"); + + book2.setId(randomNumeric(5)); + book2.setName("testBook2"); + + final Map> map1 = new HashMap>(); + map1.put(1, Arrays.asList("test1", "test2")); + + final Map> map2 = new HashMap>(); + map2.put(1, Arrays.asList("test3", "test4")); + + book1.setBuckets(map1); + book2.setBuckets(map2); + + final List indexQueries = new ArrayList(); + final IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(book1.getId()); + indexQuery1.setObject(book1); + + final IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(book2.getId()); + indexQuery2.setObject(book2); + + indexQueries.add(indexQuery1); + indexQueries.add(indexQuery2); + //when + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(Book.class); + //then + final SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(nestedQuery("buckets", termQuery("buckets.1", "test3"))) + .build(); + final Page books = elasticsearchTemplate.queryForPage(searchQuery, Book.class); + + assertThat(books.getContent().size(), is(1)); + assertThat(books.getContent().get(0).getId(), is(book2.getId())); + } +} + diff --git a/src/test/java/org/springframework/data/elasticsearch/NonDocumentEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/NonDocumentEntityTests.java index 8242e88b..e1ce1bdf 100644 --- a/src/test/java/org/springframework/data/elasticsearch/NonDocumentEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/NonDocumentEntityTests.java @@ -1,35 +1,35 @@ -/* - * 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; - -import org.junit.Test; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.data.elasticsearch.repositories.nondocument.NonDocumentEntityRepository; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class NonDocumentEntityTests { - - @Test(expected = BeanCreationException.class) - public void shouldNotInitialiseRepositoryWithNonDocument() { - // when - ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/repository-non-document-entity.xml"); - ctx.getBean(NonDocumentEntityRepository.class); - } -} +/* + * 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; + +import org.junit.Test; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.data.elasticsearch.repositories.nondocument.NonDocumentEntityRepository; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class NonDocumentEntityTests { + + @Test(expected = BeanCreationException.class) + public void shouldNotInitialiseRepositoryWithNonDocument() { + // when + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/repository-non-document-entity.xml"); + ctx.getBean(NonDocumentEntityRepository.class); + } +} 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 15db89a9..7d9e1a91 100644 --- a/src/test/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandlerTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/config/ElasticsearchNamespaceHandlerTests.java @@ -1,62 +1,62 @@ -/* - * 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.NodeClientFactoryBean; -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 shouldCreatesNodeClient() { - assertThat(context.getBean(NodeClientFactoryBean.class), is(notNullValue())); - assertThat(context.getBean(NodeClientFactoryBean.class), is(instanceOf(NodeClientFactoryBean.class))); - } - - @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 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.NodeClientFactoryBean; +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 shouldCreatesNodeClient() { + assertThat(context.getBean(NodeClientFactoryBean.class), is(notNullValue())); + assertThat(context.getBean(NodeClientFactoryBean.class), is(instanceOf(NodeClientFactoryBean.class))); + } + + @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))); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index 6fe00e00..151b7102 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -1,2074 +1,2074 @@ -/* - * Copyright 2014-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 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.*; - -import java.util.*; - -import org.apache.commons.lang.StringUtils; -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.index.engine.DocumentMissingException; -import org.elasticsearch.script.Script; -import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.highlight.HighlightBuilder; -import org.elasticsearch.search.sort.FieldSortBuilder; -import org.elasticsearch.search.sort.SortOrder; -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Ignore; -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.*; -import org.springframework.data.util.CloseableIterator; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Franck Marchand - * @author Abdul Mohammed - * @author Kevin Leturc - * @author Mason Chan - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:elasticsearch-template-test.xml") -public class ElasticsearchTemplateTests { - - private static final String INDEX_NAME = "test-index"; - 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 ElasticsearchTemplate elasticsearchTemplate; - - @Before - public void before() { - elasticsearchTemplate.deleteIndex(SampleEntity.class); - elasticsearchTemplate.createIndex(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().getField("message").getValue()); - entity.setType((String) response.getResponse().getField("type").getValue()); - 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)); - } - - @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").ignoreUnmapped(true).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").ignoreUnmapped(true).order(SortOrder.ASC)) - .withSort(new FieldSortBuilder("message").ignoreUnmapped(true).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 - 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("doc['rate'].value * factor", ScriptService.ScriptType.INLINE, null, params))) - .build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); - // then - assertThat(sampleEntities.getTotalElements(), equalTo(1L)); - assertThat(sampleEntities.getContent().get(0).getScriptedRate(), equalTo(4L)); - } - - @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 - @Ignore("By default, the search request will fail if there is no mapping associated with a field. The ignore_unmapped option allows to ignore fields that have no mapping and not sort by them") - 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, "messsage"))); - // 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); - 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.field("message").value()); - } - 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)); - - String scrollId = elasticsearchTemplate.scan(criteriaQuery, 1000, false); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); - if (page.hasContent()) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - elasticsearchTemplate.clearScroll(scrollId); - 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(); - - String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); - if (page.hasContent()) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - elasticsearchTemplate.clearScroll(scrollId); - assertThat(sampleEntities.size(), is(equalTo(30))); - } - - /* - DATAES-167 - */ - @Test - public void shouldReturnResultsWithScanAndScrollForSpecifiedFieldsForCriteriaCriteria() { - //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)); - - String scrollId = elasticsearchTemplate.scan(criteriaQuery, 5000, false); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, new SearchResultMapper() { - @Override - public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { - List result = new ArrayList(); - for (SearchHit searchHit : response.getHits()) { - String message = searchHit.getFields().get("message").getValue(); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(searchHit.getId()); - sampleEntity.setMessage(message); - result.add(sampleEntity); - } - - if (result.size() > 0) { - return new AggregatedPageImpl((List) result); - } - return null; - } - }); - if (page != null) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - 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(); - - String scrollId = elasticsearchTemplate.scan(searchQuery, 10000, false); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 10000L, new SearchResultMapper() { - @Override - public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { - List result = new ArrayList(); - for (SearchHit searchHit : response.getHits()) { - String message = searchHit.getFields().get("message").getValue(); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(searchHit.getId()); - sampleEntity.setMessage(message); - result.add(sampleEntity); - } - - if (result.size() > 0) { - return new AggregatedPageImpl((List) result); - } - return null; - } - }); - if (page != null) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - 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)); - - String scrollId = elasticsearchTemplate.scan(criteriaQuery, 5000, false); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, 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; - } - SampleEntity user = new SampleEntity(); - user.setId(searchHit.getId()); - user.setMessage((String) searchHit.getSource().get("message")); - chunk.add(user); - } - if (chunk.size() > 0) { - return new AggregatedPageImpl((List) chunk); - } - return null; - } - }); - if (page != null) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - 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(); - - String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, 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; - } - SampleEntity user = new SampleEntity(); - user.setId(searchHit.getId()); - user.setMessage((String) searchHit.getSource().get("message")); - chunk.add(user); - } - if (chunk.size() > 0) { - return new AggregatedPageImpl((List) chunk); - } - return null; - } - }); - if (page != null) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - 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)); - - String scrollId = elasticsearchTemplate.scan(criteriaQuery, 1000, false, SampleEntity.class); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); - if (page.hasContent()) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - 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(); - - String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false, SampleEntity.class); - List sampleEntities = new ArrayList(); - boolean hasRecords = true; - while (hasRecords) { - Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); - if (page.hasContent()) { - sampleEntities.addAll(page.getContent()); - } else { - hasRecords = false; - } - } - 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.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(expected = DocumentMissingException.class) - public void shouldThrowExceptionIfDocumentDoesNotExistWhileDoingPartialUpdate() { - // when - IndexRequest indexRequest = new IndexRequest(); - UpdateQuery updateQuery = new UpdateQueryBuilder().withId(randomNumeric(5)) - .withClass(SampleEntity.class).withIndexRequest(indexRequest).build(); - elasticsearchTemplate.update(updateQuery); - } - - @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); - - SearchQuery searchQuery = new NativeSearchQueryBuilder() - .withQuery(termQuery("message", "test")) - .withHighlightFields(new HighlightBuilder.Field("message")) - .build(); - - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.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; - } - SampleEntity user = new SampleEntity(); - user.setId(searchHit.getId()); - user.setMessage((String) searchHit.getSource().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 - 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.getSource().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(0.5F) - .build(); - - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); - // then - assertThat(page.getTotalElements(), is(1L)); - assertThat(page.getContent().get(0).getMessage(), is("ab")); - } - - - @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.getSource().get("userId")); - person.put("email", searchHit.getSource().get("email")); - person.put("title", searchHit.getSource().get("title")); - person.put("firstName", searchHit.getSource().get("firstName")); - person.put("lastName", searchHit.getSource().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("test-index"); - // 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("test-index") - .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("test-index"); - 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("test-index") - .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.refresh(SampleEntity.class); - - // then - Map map = elasticsearchTemplate.getSetting(SampleEntity.class); - assertThat(elasticsearchTemplate.indexExists("test-index"), 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.getSource().get("id")); - String firstName = StringUtils.isNotEmpty((String) searchHit.getSource().get("firstName")) ? (String) searchHit.getSource().get("firstName") : ""; - String lastName = StringUtils.isNotEmpty((String) searchHit.getSource().get("lastName")) ? (String) searchHit.getSource().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).build(); - } - - private List getIndexQueries(List sampleEntities) { - List indexQueries = new ArrayList(); - for (SampleEntity sampleEntity : sampleEntities) { - indexQueries.add(new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build()); - } - 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; - } - } -} +/* + * Copyright 2014-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 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.*; + +import java.util.*; + +import org.apache.commons.lang.StringUtils; +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.index.engine.DocumentMissingException; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptService; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.FieldSortBuilder; +import org.elasticsearch.search.sort.SortOrder; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Ignore; +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.*; +import org.springframework.data.util.CloseableIterator; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Franck Marchand + * @author Abdul Mohammed + * @author Kevin Leturc + * @author Mason Chan + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:elasticsearch-template-test.xml") +public class ElasticsearchTemplateTests { + + private static final String INDEX_NAME = "test-index"; + 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 ElasticsearchTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(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().getField("message").getValue()); + entity.setType((String) response.getResponse().getField("type").getValue()); + 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)); + } + + @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").ignoreUnmapped(true).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").ignoreUnmapped(true).order(SortOrder.ASC)) + .withSort(new FieldSortBuilder("message").ignoreUnmapped(true).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 + 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("doc['rate'].value * factor", ScriptService.ScriptType.INLINE, null, params))) + .build(); + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + assertThat(sampleEntities.getContent().get(0).getScriptedRate(), equalTo(4L)); + } + + @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 + @Ignore("By default, the search request will fail if there is no mapping associated with a field. The ignore_unmapped option allows to ignore fields that have no mapping and not sort by them") + 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, "messsage"))); + // 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); + 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.field("message").value()); + } + 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)); + + String scrollId = elasticsearchTemplate.scan(criteriaQuery, 1000, false); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); + if (page.hasContent()) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + elasticsearchTemplate.clearScroll(scrollId); + 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(); + + String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); + if (page.hasContent()) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + elasticsearchTemplate.clearScroll(scrollId); + assertThat(sampleEntities.size(), is(equalTo(30))); + } + + /* + DATAES-167 + */ + @Test + public void shouldReturnResultsWithScanAndScrollForSpecifiedFieldsForCriteriaCriteria() { + //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)); + + String scrollId = elasticsearchTemplate.scan(criteriaQuery, 5000, false); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List result = new ArrayList(); + for (SearchHit searchHit : response.getHits()) { + String message = searchHit.getFields().get("message").getValue(); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(searchHit.getId()); + sampleEntity.setMessage(message); + result.add(sampleEntity); + } + + if (result.size() > 0) { + return new AggregatedPageImpl((List) result); + } + return null; + } + }); + if (page != null) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + 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(); + + String scrollId = elasticsearchTemplate.scan(searchQuery, 10000, false); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 10000L, new SearchResultMapper() { + @Override + public AggregatedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List result = new ArrayList(); + for (SearchHit searchHit : response.getHits()) { + String message = searchHit.getFields().get("message").getValue(); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(searchHit.getId()); + sampleEntity.setMessage(message); + result.add(sampleEntity); + } + + if (result.size() > 0) { + return new AggregatedPageImpl((List) result); + } + return null; + } + }); + if (page != null) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + 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)); + + String scrollId = elasticsearchTemplate.scan(criteriaQuery, 5000, false); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, 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; + } + SampleEntity user = new SampleEntity(); + user.setId(searchHit.getId()); + user.setMessage((String) searchHit.getSource().get("message")); + chunk.add(user); + } + if (chunk.size() > 0) { + return new AggregatedPageImpl((List) chunk); + } + return null; + } + }); + if (page != null) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + 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(); + + String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, 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; + } + SampleEntity user = new SampleEntity(); + user.setId(searchHit.getId()); + user.setMessage((String) searchHit.getSource().get("message")); + chunk.add(user); + } + if (chunk.size() > 0) { + return new AggregatedPageImpl((List) chunk); + } + return null; + } + }); + if (page != null) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + 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)); + + String scrollId = elasticsearchTemplate.scan(criteriaQuery, 1000, false, SampleEntity.class); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); + if (page.hasContent()) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + 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(); + + String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false, SampleEntity.class); + List sampleEntities = new ArrayList(); + boolean hasRecords = true; + while (hasRecords) { + Page page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class); + if (page.hasContent()) { + sampleEntities.addAll(page.getContent()); + } else { + hasRecords = false; + } + } + 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.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(expected = DocumentMissingException.class) + public void shouldThrowExceptionIfDocumentDoesNotExistWhileDoingPartialUpdate() { + // when + IndexRequest indexRequest = new IndexRequest(); + UpdateQuery updateQuery = new UpdateQueryBuilder().withId(randomNumeric(5)) + .withClass(SampleEntity.class).withIndexRequest(indexRequest).build(); + elasticsearchTemplate.update(updateQuery); + } + + @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); + + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(termQuery("message", "test")) + .withHighlightFields(new HighlightBuilder.Field("message")) + .build(); + + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.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; + } + SampleEntity user = new SampleEntity(); + user.setId(searchHit.getId()); + user.setMessage((String) searchHit.getSource().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 + 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.getSource().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(0.5F) + .build(); + + Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(page.getTotalElements(), is(1L)); + assertThat(page.getContent().get(0).getMessage(), is("ab")); + } + + + @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.getSource().get("userId")); + person.put("email", searchHit.getSource().get("email")); + person.put("title", searchHit.getSource().get("title")); + person.put("firstName", searchHit.getSource().get("firstName")); + person.put("lastName", searchHit.getSource().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("test-index"); + // 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("test-index") + .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("test-index"); + 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("test-index") + .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.refresh(SampleEntity.class); + + // then + Map map = elasticsearchTemplate.getSetting(SampleEntity.class); + assertThat(elasticsearchTemplate.indexExists("test-index"), 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.getSource().get("id")); + String firstName = StringUtils.isNotEmpty((String) searchHit.getSource().get("firstName")) ? (String) searchHit.getSource().get("firstName") : ""; + String lastName = StringUtils.isNotEmpty((String) searchHit.getSource().get("lastName")) ? (String) searchHit.getSource().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).build(); + } + + private List getIndexQueries(List sampleEntities) { + List indexQueries = new ArrayList(); + for (SampleEntity sampleEntity : sampleEntities) { + indexQueries.add(new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build()); + } + 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/convert/DateTimeConvertersTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/DateTimeConvertersTests.java index fcf0df6e..5c53b3e1 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/DateTimeConvertersTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/DateTimeConvertersTests.java @@ -1,73 +1,73 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.convert; - -import java.util.Calendar; -import java.util.TimeZone; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.LocalDateTime; -import org.junit.Assert; -import org.junit.Test; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class DateTimeConvertersTests { - - @Test - public void testJodaDateTimeConverterWithNullValue() { - Assert.assertNull(DateTimeConverters.JodaDateTimeConverter.INSTANCE.convert(null)); - } - - @Test - public void testJodaDateTimeConverter() { - DateTime dateTime = new DateTime(2013, 1, 24, 6, 35, 0, DateTimeZone.UTC); - Assert - .assertEquals("2013-01-24T06:35:00.000Z", DateTimeConverters.JodaDateTimeConverter.INSTANCE.convert(dateTime)); - } - - @Test - public void testJodaLocalDateTimeConverterWithNullValue() { - Assert.assertNull(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE.convert(null)); - } - - @Test - public void testJodaLocalDateTimeConverter() { - LocalDateTime dateTime = new LocalDateTime(new DateTime(2013, 1, 24, 6, 35, 0, DateTimeZone.UTC).getMillis(), - DateTimeZone.UTC); - Assert.assertEquals("2013-01-24T06:35:00.000Z", - DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE.convert(dateTime)); - } - - @Test - public void testJavaDateConverterWithNullValue() { - Assert.assertNull(DateTimeConverters.JavaDateConverter.INSTANCE.convert(null)); - } - - @Test - public void testJavaDateConverter() { - DateTime dateTime = new DateTime(2013, 1, 24, 6, 35, 0, DateTimeZone.UTC); - Calendar calendar = Calendar.getInstance(); - calendar.setTimeZone(TimeZone.getTimeZone("UTC")); - calendar.setTimeInMillis(dateTime.getMillis()); - - Assert.assertEquals("2013-01-24T06:35:00.000Z", - DateTimeConverters.JavaDateConverter.INSTANCE.convert(calendar.getTime())); - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.convert; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDateTime; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class DateTimeConvertersTests { + + @Test + public void testJodaDateTimeConverterWithNullValue() { + Assert.assertNull(DateTimeConverters.JodaDateTimeConverter.INSTANCE.convert(null)); + } + + @Test + public void testJodaDateTimeConverter() { + DateTime dateTime = new DateTime(2013, 1, 24, 6, 35, 0, DateTimeZone.UTC); + Assert + .assertEquals("2013-01-24T06:35:00.000Z", DateTimeConverters.JodaDateTimeConverter.INSTANCE.convert(dateTime)); + } + + @Test + public void testJodaLocalDateTimeConverterWithNullValue() { + Assert.assertNull(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE.convert(null)); + } + + @Test + public void testJodaLocalDateTimeConverter() { + LocalDateTime dateTime = new LocalDateTime(new DateTime(2013, 1, 24, 6, 35, 0, DateTimeZone.UTC).getMillis(), + DateTimeZone.UTC); + Assert.assertEquals("2013-01-24T06:35:00.000Z", + DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE.convert(dateTime)); + } + + @Test + public void testJavaDateConverterWithNullValue() { + Assert.assertNull(DateTimeConverters.JavaDateConverter.INSTANCE.convert(null)); + } + + @Test + public void testJavaDateConverter() { + DateTime dateTime = new DateTime(2013, 1, 24, 6, 35, 0, DateTimeZone.UTC); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + calendar.setTimeInMillis(dateTime.getMillis()); + + Assert.assertEquals("2013-01-24T06:35:00.000Z", + DateTimeConverters.JavaDateConverter.INSTANCE.convert(calendar.getTime())); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterTests.java index 88dd15cc..f0f76988 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterTests.java @@ -1,57 +1,57 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.convert; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - -import org.junit.Test; -import org.springframework.core.convert.ConversionService; -import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; -import org.springframework.data.mapping.context.MappingContext; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class MappingElasticsearchConverterTests { - - @Test(expected = IllegalArgumentException.class) - public void shouldFailToInitializeGivenMappingContextIsNull() { - // given - new MappingElasticsearchConverter(null); - } - - @Test - public void shouldReturnMappingContextWithWhichItWasInitialized() { - // given - MappingContext mappingContext = new SimpleElasticsearchMappingContext(); - MappingElasticsearchConverter converter = new MappingElasticsearchConverter(mappingContext); - // then - assertThat(converter.getMappingContext(), is(notNullValue())); - assertThat(converter.getMappingContext(), is(sameInstance(mappingContext))); - } - - @Test - public void shouldReturnDefaultConversionService() { - // given - MappingElasticsearchConverter converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()); - // when - ConversionService conversionService = converter.getConversionService(); - // then - assertThat(conversionService, is(notNullValue())); - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.convert; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; +import org.springframework.data.mapping.context.MappingContext; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class MappingElasticsearchConverterTests { + + @Test(expected = IllegalArgumentException.class) + public void shouldFailToInitializeGivenMappingContextIsNull() { + // given + new MappingElasticsearchConverter(null); + } + + @Test + public void shouldReturnMappingContextWithWhichItWasInitialized() { + // given + MappingContext mappingContext = new SimpleElasticsearchMappingContext(); + MappingElasticsearchConverter converter = new MappingElasticsearchConverter(mappingContext); + // then + assertThat(converter.getMappingContext(), is(notNullValue())); + assertThat(converter.getMappingContext(), is(sameInstance(mappingContext))); + } + + @Test + public void shouldReturnDefaultConversionService() { + // given + MappingElasticsearchConverter converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()); + // when + ConversionService conversionService = converter.getConversionService(); + // then + assertThat(conversionService, is(notNullValue())); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntity.java b/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntity.java index d35b43ec..04fb7c2b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntity.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntity.java @@ -1,114 +1,114 @@ -/* - * Copyright 2014 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.facet; - -import static org.springframework.data.elasticsearch.annotations.FieldIndex.*; -import static org.springframework.data.elasticsearch.annotations.FieldType.Integer; -import static org.springframework.data.elasticsearch.annotations.FieldType.String; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.MultiField; -import org.springframework.data.elasticsearch.annotations.InnerField; - -/** - * Simple type to test facets - * - * @author Artur Konczak - * @author Mohsin Husen - */ -@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1") -public class ArticleEntity { - - @Id - private String id; - private String title; - private String subject; - - @MultiField( - mainField = @Field(type = String, index = analyzed), - otherFields = { - @InnerField(suffix = "untouched", type = String, store = true, index = not_analyzed), - @InnerField(suffix = "sort", type = String, store = true, indexAnalyzer = "keyword") - } - ) - private List authors = new ArrayList(); - - @Field(type = Integer, store = true) - private List publishedYears = new ArrayList(); - - private int score; - - private ArticleEntity() { - - } - - public ArticleEntity(String id) { - this.id = id; - } - - public void setId(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getSubject() { - return subject; - } - - public void setSubject(String subject) { - this.subject = subject; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public List getPublishedYears() { - return publishedYears; - } - - public void setPublishedYears(List publishedYears) { - this.publishedYears = publishedYears; - } - - public int getScore() { - return score; - } - - public void setScore(int score) { - this.score = score; - } -} +/* + * Copyright 2014 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.facet; + +import static org.springframework.data.elasticsearch.annotations.FieldIndex.*; +import static org.springframework.data.elasticsearch.annotations.FieldType.Integer; +import static org.springframework.data.elasticsearch.annotations.FieldType.String; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.MultiField; +import org.springframework.data.elasticsearch.annotations.InnerField; + +/** + * Simple type to test facets + * + * @author Artur Konczak + * @author Mohsin Husen + */ +@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1") +public class ArticleEntity { + + @Id + private String id; + private String title; + private String subject; + + @MultiField( + mainField = @Field(type = String, index = analyzed), + otherFields = { + @InnerField(suffix = "untouched", type = String, store = true, index = not_analyzed), + @InnerField(suffix = "sort", type = String, store = true, indexAnalyzer = "keyword") + } + ) + private List authors = new ArrayList(); + + @Field(type = Integer, store = true) + private List publishedYears = new ArrayList(); + + private int score; + + private ArticleEntity() { + + } + + public ArticleEntity(String id) { + this.id = id; + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(List authors) { + this.authors = authors; + } + + public List getPublishedYears() { + return publishedYears; + } + + public void setPublishedYears(List publishedYears) { + this.publishedYears = publishedYears; + } + + public int getScore() { + return score; + } + + public void setScore(int score) { + this.score = score; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntityBuilder.java b/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntityBuilder.java index 9f0ddbde..65d00f72 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntityBuilder.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntityBuilder.java @@ -1,69 +1,69 @@ -/* - * Copyright 2014 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.facet; - -import org.springframework.data.elasticsearch.core.query.IndexQuery; - -/** - * Simple type to test facets - * - * @author Artur Konczak - * @author Mohsin Husen - */ -public class ArticleEntityBuilder { - - private ArticleEntity result; - - public ArticleEntityBuilder(String id) { - result = new ArticleEntity(id); - } - - public ArticleEntityBuilder title(String title) { - result.setTitle(title); - return this; - } - - public ArticleEntityBuilder subject(String subject) { - result.setSubject(subject); - return this; - } - - public ArticleEntityBuilder addAuthor(String author) { - result.getAuthors().add(author); - return this; - } - - public ArticleEntityBuilder addPublishedYear(Integer year) { - result.getPublishedYears().add(year); - return this; - } - - public ArticleEntityBuilder score(int score) { - result.setScore(score); - return this; - } - - public ArticleEntity build() { - return result; - } - - public IndexQuery buildIndex() { - IndexQuery indexQuery = new IndexQuery(); - indexQuery.setId(result.getId()); - indexQuery.setObject(result); - return indexQuery; - } -} +/* + * Copyright 2014 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.facet; + +import org.springframework.data.elasticsearch.core.query.IndexQuery; + +/** + * Simple type to test facets + * + * @author Artur Konczak + * @author Mohsin Husen + */ +public class ArticleEntityBuilder { + + private ArticleEntity result; + + public ArticleEntityBuilder(String id) { + result = new ArticleEntity(id); + } + + public ArticleEntityBuilder title(String title) { + result.setTitle(title); + return this; + } + + public ArticleEntityBuilder subject(String subject) { + result.setSubject(subject); + return this; + } + + public ArticleEntityBuilder addAuthor(String author) { + result.getAuthors().add(author); + return this; + } + + public ArticleEntityBuilder addPublishedYear(Integer year) { + result.getPublishedYears().add(year); + return this; + } + + public ArticleEntityBuilder score(int score) { + result.setScore(score); + return this; + } + + public ArticleEntity build() { + return result; + } + + public IndexQuery buildIndex() { + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId(result.getId()); + indexQuery.setObject(result); + return indexQuery; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java index bd891aba..9e0861cf 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTests.java @@ -1,111 +1,111 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.mapping; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; - -import org.junit.Test; -import org.springframework.data.annotation.Version; -import org.springframework.data.mapping.model.MappingException; -import org.springframework.data.mapping.model.SimpleTypeHolder; -import org.springframework.data.util.ClassTypeInformation; -import org.springframework.data.util.TypeInformation; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class SimpleElasticsearchPersistentEntityTests { - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionGivenVersionPropertyIsNotLong() throws NoSuchFieldException, IntrospectionException { - // given - TypeInformation typeInformation = ClassTypeInformation.from(EntityWithWrongVersionType.class); - SimpleElasticsearchPersistentProperty persistentProperty = new SimpleElasticsearchPersistentProperty( - EntityWithWrongVersionType.class.getDeclaredField("version"), new PropertyDescriptor("version", - EntityWithWrongVersionType.class), new SimpleElasticsearchPersistentEntity( - typeInformation), new SimpleTypeHolder() - ); - - // when - new SimpleElasticsearchPersistentEntity(typeInformation).addPersistentProperty(persistentProperty); - } - - @Test(expected = MappingException.class) - public void shouldThrowExceptionGivenMultipleVersionPropertiesArePresent() throws NoSuchFieldException, - IntrospectionException { - // given - TypeInformation typeInformation = ClassTypeInformation.from(EntityWithMultipleVersionField.class); - SimpleElasticsearchPersistentProperty persistentProperty1 = new SimpleElasticsearchPersistentProperty( - EntityWithMultipleVersionField.class.getDeclaredField("version1"), new PropertyDescriptor("version1", - EntityWithMultipleVersionField.class), - new SimpleElasticsearchPersistentEntity(typeInformation), - new SimpleTypeHolder() - ); - - SimpleElasticsearchPersistentProperty persistentProperty2 = new SimpleElasticsearchPersistentProperty( - EntityWithMultipleVersionField.class.getDeclaredField("version2"), new PropertyDescriptor("version2", - EntityWithMultipleVersionField.class), - new SimpleElasticsearchPersistentEntity(typeInformation), - new SimpleTypeHolder() - ); - - SimpleElasticsearchPersistentEntity simpleElasticsearchPersistentEntity = new SimpleElasticsearchPersistentEntity( - typeInformation); - simpleElasticsearchPersistentEntity.addPersistentProperty(persistentProperty1); - // when - simpleElasticsearchPersistentEntity.addPersistentProperty(persistentProperty2); - } - - private class EntityWithWrongVersionType { - - @Version - private String version; - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - } - - private class EntityWithMultipleVersionField { - - @Version - private Long version1; - @Version - private Long version2; - - public Long getVersion1() { - return version1; - } - - public void setVersion1(Long version1) { - this.version1 = version1; - } - - public Long getVersion2() { - return version2; - } - - public void setVersion2(Long version2) { - this.version2 = version2; - } - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.mapping; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; + +import org.junit.Test; +import org.springframework.data.annotation.Version; +import org.springframework.data.mapping.model.MappingException; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class SimpleElasticsearchPersistentEntityTests { + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionGivenVersionPropertyIsNotLong() throws NoSuchFieldException, IntrospectionException { + // given + TypeInformation typeInformation = ClassTypeInformation.from(EntityWithWrongVersionType.class); + SimpleElasticsearchPersistentProperty persistentProperty = new SimpleElasticsearchPersistentProperty( + EntityWithWrongVersionType.class.getDeclaredField("version"), new PropertyDescriptor("version", + EntityWithWrongVersionType.class), new SimpleElasticsearchPersistentEntity( + typeInformation), new SimpleTypeHolder() + ); + + // when + new SimpleElasticsearchPersistentEntity(typeInformation).addPersistentProperty(persistentProperty); + } + + @Test(expected = MappingException.class) + public void shouldThrowExceptionGivenMultipleVersionPropertiesArePresent() throws NoSuchFieldException, + IntrospectionException { + // given + TypeInformation typeInformation = ClassTypeInformation.from(EntityWithMultipleVersionField.class); + SimpleElasticsearchPersistentProperty persistentProperty1 = new SimpleElasticsearchPersistentProperty( + EntityWithMultipleVersionField.class.getDeclaredField("version1"), new PropertyDescriptor("version1", + EntityWithMultipleVersionField.class), + new SimpleElasticsearchPersistentEntity(typeInformation), + new SimpleTypeHolder() + ); + + SimpleElasticsearchPersistentProperty persistentProperty2 = new SimpleElasticsearchPersistentProperty( + EntityWithMultipleVersionField.class.getDeclaredField("version2"), new PropertyDescriptor("version2", + EntityWithMultipleVersionField.class), + new SimpleElasticsearchPersistentEntity(typeInformation), + new SimpleTypeHolder() + ); + + SimpleElasticsearchPersistentEntity simpleElasticsearchPersistentEntity = new SimpleElasticsearchPersistentEntity( + typeInformation); + simpleElasticsearchPersistentEntity.addPersistentProperty(persistentProperty1); + // when + simpleElasticsearchPersistentEntity.addPersistentProperty(persistentProperty2); + } + + private class EntityWithWrongVersionType { + + @Version + private String version; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + } + + private class EntityWithMultipleVersionField { + + @Version + private Long version1; + @Version + private Long version2; + + public Long getVersion1() { + return version1; + } + + public void setVersion1(Long version1) { + this.version1 = version1; + } + + public Long getVersion2() { + return version2; + } + + public void setVersion2(Long version2) { + this.version2 = version2; + } + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java index 358cdedd..d5969f2f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java @@ -1,724 +1,724 @@ -/* - * 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.query; - -import static org.apache.commons.lang.RandomStringUtils.*; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.springframework.data.elasticsearch.utils.IndexBuilder.*; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Ignore; -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.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.entities.SampleEntity; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:elasticsearch-template-test.xml") -public class CriteriaQueryTests { - - @Autowired - private ElasticsearchTemplate elasticsearchTemplate; - - @Before - public void before() { - elasticsearchTemplate.deleteIndex(SampleEntity.class); - elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.refresh(SampleEntity.class); - } - - @Test - public void shouldPerformAndOperation() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("some test message"); - sampleEntity.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery = new IndexQuery(); - indexQuery.setId(documentId); - indexQuery.setObject(sampleEntity); - elasticsearchTemplate.index(indexQuery); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test").and("message") - .contains("some")); - // when - SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat(sampleEntity1, is(notNullValue())); - } - - @Ignore("DATAES-30") - @Test - public void shouldPerformOrOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("some message"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - - indexQueries.add(indexQuery2); - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("some").or("message") - .contains("test")); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformAndOperationWithinCriteria() { - // given - List indexQueries = new ArrayList(); - // first document - 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); - indexQueries.add(indexQuery); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria().and(new Criteria("message").contains("some"))); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Ignore("DATAES-30") - @Test - public void shouldPerformOrOperationWithinCriteria() { - // given - List indexQueries = new ArrayList(); - // first document - 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); - indexQueries.add(indexQuery); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria().or(new Criteria("message").contains("some"))); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformIsOperation() { - // given - List indexQueries = new ArrayList(); - // first document - 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); - indexQueries.add(indexQuery); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").is("some message")); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformMultipleIsOperations() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("some message"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").is("some message")); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(page.getTotalElements(), is(equalTo(1L))); - } - - @Test - public void shouldPerformEndsWithOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("some message"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test message end"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - Criteria criteria = new Criteria("message").endsWith("end"); - CriteriaQuery criteriaQuery = new CriteriaQuery(criteria); - // when - SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(sampleEntity, is(notNullValue())); - } - - @Test - public void shouldPerformStartsWithOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("start some message"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - Criteria criteria = new Criteria("message").startsWith("start"); - CriteriaQuery criteriaQuery = new CriteriaQuery(criteria); - // when - SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(sampleEntity, is(notNullValue())); - } - - @Test - public void shouldPerformContainsOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("contains some message"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("contains")); - // when - SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(sampleEntity, is(notNullValue())); - } - - @Test - public void shouldExecuteExpression() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("elasticsearch search"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").expression("+elasticsearch || test")); - // when - SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(sampleEntity, is(notNullValue())); - } - - @Test - public void shouldExecuteCriteriaChain() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("some message search"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("test test message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").startsWith("some").endsWith("search") - .contains("message").is("some message search")); - // when - SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); - assertThat(sampleEntity, is(notNullValue())); - } - - @Test - public void shouldPerformIsNotOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("bar"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").is("foo").not()); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertTrue(criteriaQuery.getCriteria().isNegating()); - assertThat(page, is(notNullValue())); - assertFalse(page.iterator().next().getMessage().contains("foo")); - } - - @Test - public void shouldPerformBetweenOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setRate(100); - sampleEntity1.setMessage("bar"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setRate(200); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").between(100, 150)); - // when - SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); - // then - assertThat(sampleEntity, is(notNullValue())); - } - - @Test - public void shouldPerformBetweenOperationWithoutUpperBound() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setRate(300); - sampleEntity1.setMessage("bar"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setRate(400); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").between(350, null)); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformBetweenOperationWithoutLowerBound() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setRate(500); - sampleEntity1.setMessage("bar"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setRate(600); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").between(null, 550)); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformLessThanEqualOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setRate(700); - sampleEntity1.setMessage("bar"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setRate(800); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").lessThanEqual(750)); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformGreaterThanEquals() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setRate(900); - sampleEntity1.setMessage("bar"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setRate(1000); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").greaterThanEqual(950)); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldPerformBoostOperation() { - // given - List indexQueries = new ArrayList(); - // first document - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setRate(700); - sampleEntity1.setMessage("bar foo"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery1 = new IndexQuery(); - indexQuery1.setId(documentId); - indexQuery1.setObject(sampleEntity1); - indexQueries.add(indexQuery1); - - // second document - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setRate(800); - sampleEntity2.setMessage("foo"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - IndexQuery indexQuery2 = new IndexQuery(); - indexQuery2.setId(documentId2); - indexQuery2.setObject(sampleEntity2); - indexQueries.add(indexQuery2); - - elasticsearchTemplate.bulkIndex(indexQueries); - elasticsearchTemplate.refresh(SampleEntity.class); - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("foo").boost(1)); - // when - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldReturnDocumentAboveMinimalScoreGivenCriteria() { - // 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 - CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("a").or(new Criteria("message").contains("b"))); - criteriaQuery.setMinScore(0.5F); - Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); - // then - assertThat(page.getTotalElements(), is(1L)); - assertThat(page.getContent().get(0).getMessage(), is("ab")); - } -} +/* + * 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.query; + +import static org.apache.commons.lang.RandomStringUtils.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.springframework.data.elasticsearch.utils.IndexBuilder.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Ignore; +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.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:elasticsearch-template-test.xml") +public class CriteriaQueryTests { + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + } + + @Test + public void shouldPerformAndOperation() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some test message"); + sampleEntity.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId(documentId); + indexQuery.setObject(sampleEntity); + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test").and("message") + .contains("some")); + // when + SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat(sampleEntity1, is(notNullValue())); + } + + @Ignore("DATAES-30") + @Test + public void shouldPerformOrOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + + indexQueries.add(indexQuery2); + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("some").or("message") + .contains("test")); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformAndOperationWithinCriteria() { + // given + List indexQueries = new ArrayList(); + // first document + 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); + indexQueries.add(indexQuery); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria().and(new Criteria("message").contains("some"))); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Ignore("DATAES-30") + @Test + public void shouldPerformOrOperationWithinCriteria() { + // given + List indexQueries = new ArrayList(); + // first document + 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); + indexQueries.add(indexQuery); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria().or(new Criteria("message").contains("some"))); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformIsOperation() { + // given + List indexQueries = new ArrayList(); + // first document + 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); + indexQueries.add(indexQuery); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").is("some message")); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformMultipleIsOperations() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").is("some message")); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + } + + @Test + public void shouldPerformEndsWithOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test message end"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + Criteria criteria = new Criteria("message").endsWith("end"); + CriteriaQuery criteriaQuery = new CriteriaQuery(criteria); + // when + SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(sampleEntity, is(notNullValue())); + } + + @Test + public void shouldPerformStartsWithOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("start some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + Criteria criteria = new Criteria("message").startsWith("start"); + CriteriaQuery criteriaQuery = new CriteriaQuery(criteria); + // when + SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(sampleEntity, is(notNullValue())); + } + + @Test + public void shouldPerformContainsOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("contains some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("contains")); + // when + SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(sampleEntity, is(notNullValue())); + } + + @Test + public void shouldExecuteExpression() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("elasticsearch search"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").expression("+elasticsearch || test")); + // when + SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(sampleEntity, is(notNullValue())); + } + + @Test + public void shouldExecuteCriteriaChain() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("some message search"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("test test message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").startsWith("some").endsWith("search") + .contains("message").is("some message search")); + // when + SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat("message", is(criteriaQuery.getCriteria().getField().getName())); + assertThat(sampleEntity, is(notNullValue())); + } + + @Test + public void shouldPerformIsNotOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("bar"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").is("foo").not()); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertTrue(criteriaQuery.getCriteria().isNegating()); + assertThat(page, is(notNullValue())); + assertFalse(page.iterator().next().getMessage().contains("foo")); + } + + @Test + public void shouldPerformBetweenOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setRate(100); + sampleEntity1.setMessage("bar"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setRate(200); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").between(100, 150)); + // when + SampleEntity sampleEntity = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class); + // then + assertThat(sampleEntity, is(notNullValue())); + } + + @Test + public void shouldPerformBetweenOperationWithoutUpperBound() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setRate(300); + sampleEntity1.setMessage("bar"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setRate(400); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").between(350, null)); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformBetweenOperationWithoutLowerBound() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setRate(500); + sampleEntity1.setMessage("bar"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setRate(600); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").between(null, 550)); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformLessThanEqualOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setRate(700); + sampleEntity1.setMessage("bar"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setRate(800); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").lessThanEqual(750)); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformGreaterThanEquals() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setRate(900); + sampleEntity1.setMessage("bar"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setRate(1000); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("rate").greaterThanEqual(950)); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldPerformBoostOperation() { + // given + List indexQueries = new ArrayList(); + // first document + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setRate(700); + sampleEntity1.setMessage("bar foo"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(documentId); + indexQuery1.setObject(sampleEntity1); + indexQueries.add(indexQuery1); + + // second document + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setRate(800); + sampleEntity2.setMessage("foo"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(documentId2); + indexQuery2.setObject(sampleEntity2); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(SampleEntity.class); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("foo").boost(1)); + // when + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldReturnDocumentAboveMinimalScoreGivenCriteria() { + // 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 + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("a").or(new Criteria("message").contains("b"))); + criteriaQuery.setMinScore(0.5F); + Page page = elasticsearchTemplate.queryForPage(criteriaQuery, SampleEntity.class); + // then + assertThat(page.getTotalElements(), is(1L)); + assertThat(page.getContent().get(0).getMessage(), is("ab")); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/Author.java b/src/test/java/org/springframework/data/elasticsearch/entities/Author.java index 7f6276d6..5507385e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/Author.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/Author.java @@ -1,42 +1,42 @@ -/* - * 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.entities; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class Author { - - private String id; - private String name; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +/* + * 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.entities; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class Author { + + private String id; + private String name; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/Book.java b/src/test/java/org/springframework/data/elasticsearch/entities/Book.java index 0b48896f..242fb6a7 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/Book.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/Book.java @@ -1,47 +1,47 @@ -/* - * Copyright 2013-2014 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.entities; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import lombok.*; -import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -@Document(indexName = "book", type = "book", shards = 1, replicas = 0, refreshInterval = "-1") -public class Book { - - @Id - private String id; - private String name; - @Field(type = FieldType.Object) - private Author author; - @Field(type = FieldType.Nested) - private Map> buckets = new HashMap>(); -} +/* + * Copyright 2013-2014 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.entities; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import lombok.*; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Document(indexName = "book", type = "book", shards = 1, replicas = 0, refreshInterval = "-1") +public class Book { + + @Id + private String id; + private String name; + @Field(type = FieldType.Object) + private Author author; + @Field(type = FieldType.Nested) + private Map> buckets = new HashMap>(); +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/GirlFriend.java b/src/test/java/org/springframework/data/elasticsearch/entities/GirlFriend.java index 7977c353..9613678c 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/GirlFriend.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/GirlFriend.java @@ -1,59 +1,59 @@ -/* - * Copyright 2014 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.entities; - -import java.util.List; - -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; - -/** - * @author Mohsin Husen - */ - -public class GirlFriend { - - private String name; - - private String type; - - @Field(type = FieldType.Nested) - private List cars; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getCars() { - return cars; - } - - public void setCars(List cars) { - this.cars = cars; - } -} +/* + * Copyright 2014 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.entities; + +import java.util.List; + +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +/** + * @author Mohsin Husen + */ + +public class GirlFriend { + + private String name; + + private String type; + + @Field(type = FieldType.Nested) + private List cars; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getCars() { + return cars; + } + + public void setCars(List cars) { + this.cars = cars; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/NonDocumentEntity.java b/src/test/java/org/springframework/data/elasticsearch/entities/NonDocumentEntity.java index 4547ac7e..7391fb8f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/NonDocumentEntity.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/NonDocumentEntity.java @@ -1,46 +1,46 @@ -/* - * 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.entities; - -import org.springframework.data.annotation.Id; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public class NonDocumentEntity { - - @Id - private String someId; - private String someField1; - private String someField2; - - public String getSomeField1() { - return someField1; - } - - public void setSomeField1(String someField1) { - this.someField1 = someField1; - } - - public String getSomeField2() { - return someField2; - } - - public void setSomeField2(String someField2) { - this.someField2 = someField2; - } -} +/* + * 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.entities; + +import org.springframework.data.annotation.Id; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public class NonDocumentEntity { + + @Id + private String someId; + private String someField1; + private String someField2; + + public String getSomeField1() { + return someField1; + } + + public void setSomeField1(String someField1) { + this.someField1 = someField1; + } + + public String getSomeField2() { + return someField2; + } + + public void setSomeField2(String someField2) { + this.someField2 = someField2; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/PersonMultipleLevelNested.java b/src/test/java/org/springframework/data/elasticsearch/entities/PersonMultipleLevelNested.java index a8fbbc16..53c23eb8 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/PersonMultipleLevelNested.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/PersonMultipleLevelNested.java @@ -1,88 +1,88 @@ -/* - * Copyright 2014 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.entities; - - -import java.util.List; - -import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Artur Konczak - */ - -@Document(indexName = "person-multiple-level-nested", type = "user", shards = 1, replicas = 0, refreshInterval = "-1") -public class PersonMultipleLevelNested { - - @Id - private String id; - - private String name; - - @Field(type = FieldType.Nested) - private List girlFriends; - - @Field(type = FieldType.Nested) - private List cars; - - @Field(type = FieldType.Nested, includeInParent = true) - private List bestCars; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getGirlFriends() { - return girlFriends; - } - - public void setGirlFriends(List girlFriends) { - this.girlFriends = girlFriends; - } - - public List getCars() { - return cars; - } - - public void setCars(List cars) { - this.cars = cars; - } - - public List getBestCars() { - return bestCars; - } - - public void setBestCars(List bestCars) { - this.bestCars = bestCars; - } -} +/* + * Copyright 2014 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.entities; + + +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Artur Konczak + */ + +@Document(indexName = "person-multiple-level-nested", type = "user", shards = 1, replicas = 0, refreshInterval = "-1") +public class PersonMultipleLevelNested { + + @Id + private String id; + + private String name; + + @Field(type = FieldType.Nested) + private List girlFriends; + + @Field(type = FieldType.Nested) + private List cars; + + @Field(type = FieldType.Nested, includeInParent = true) + private List bestCars; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getGirlFriends() { + return girlFriends; + } + + public void setGirlFriends(List girlFriends) { + this.girlFriends = girlFriends; + } + + public List getCars() { + return cars; + } + + public void setCars(List cars) { + this.cars = cars; + } + + public List getBestCars() { + return bestCars; + } + + public void setBestCars(List bestCars) { + this.bestCars = bestCars; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/Product.java b/src/test/java/org/springframework/data/elasticsearch/entities/Product.java index d9e76489..da608721 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/Product.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/Product.java @@ -1,92 +1,92 @@ -/* - * Copyright 2014 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.entities; - -import java.util.Date; -import java.util.List; - -import lombok.*; -import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; - -/** - * @author Mohsin Husen - * @author Artur Konczak - */ -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -@Document(indexName = "test-product-index", type = "test-product-type", shards = 1, replicas = 0, refreshInterval = "-1") -public class Product { - - @Id - private String id; - - private List title; - - private String name; - - private String description; - - private String text; - - private List categories; - - private Float weight; - - @Field(type = FieldType.Float) - private Float price; - - private Integer popularity; - - private boolean available; - - private String location; - - private Date lastModified; - - - @Override - public int hashCode() { - return id.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Product other = (Product) obj; - if (id == null) { - if (other.id != null) { - return false; - } - } else if (!id.equals(other.id)) { - return false; - } - return true; - } -} +/* + * Copyright 2014 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.entities; + +import java.util.Date; +import java.util.List; + +import lombok.*; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +/** + * @author Mohsin Husen + * @author Artur Konczak + */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Document(indexName = "test-product-index", type = "test-product-type", shards = 1, replicas = 0, refreshInterval = "-1") +public class Product { + + @Id + private String id; + + private List title; + + private String name; + + private String description; + + private String text; + + private List categories; + + private Float weight; + + @Field(type = FieldType.Float) + private Float price; + + private Integer popularity; + + private boolean available; + + private String location; + + private Date lastModified; + + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Product other = (Product) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + return true; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/SampleEntity.java b/src/test/java/org/springframework/data/elasticsearch/entities/SampleEntity.java index dd50d401..0683afde 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/SampleEntity.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/SampleEntity.java @@ -1,88 +1,88 @@ -/* - * 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.entities; - -import lombok.*; -import org.springframework.data.annotation.Id; -import org.springframework.data.annotation.Version; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; -import org.springframework.data.elasticsearch.annotations.ScriptedField; -import org.springframework.data.elasticsearch.core.geo.GeoPoint; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ - -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -@Document(indexName = "test-index", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1") -public class SampleEntity { - - @Id - private String id; - private String type; - @Field(type = FieldType.String) - private String message; - private int rate; - @ScriptedField - private Long scriptedRate; - private boolean available; - private String highlightedMessage; - - private GeoPoint location; - - @Version - private Long version; - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - SampleEntity that = (SampleEntity) o; - - if (available != that.available) return false; - if (rate != that.rate) return false; - if (highlightedMessage != null ? !highlightedMessage.equals(that.highlightedMessage) : that.highlightedMessage != null) - return false; - if (id != null ? !id.equals(that.id) : that.id != null) return false; - if (location != null ? !location.equals(that.location) : that.location != null) return false; - if (message != null ? !message.equals(that.message) : that.message != null) return false; - if (type != null ? !type.equals(that.type) : that.type != null) return false; - if (version != null ? !version.equals(that.version) : that.version != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = id != null ? id.hashCode() : 0; - result = 31 * result + (type != null ? type.hashCode() : 0); - result = 31 * result + (message != null ? message.hashCode() : 0); - result = 31 * result + rate; - result = 31 * result + (available ? 1 : 0); - result = 31 * result + (highlightedMessage != null ? highlightedMessage.hashCode() : 0); - result = 31 * result + (location != null ? location.hashCode() : 0); - result = 31 * result + (version != null ? version.hashCode() : 0); - return result; - } -} +/* + * 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.entities; + +import lombok.*; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.annotations.ScriptedField; +import org.springframework.data.elasticsearch.core.geo.GeoPoint; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ + +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Document(indexName = "test-index", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1") +public class SampleEntity { + + @Id + private String id; + private String type; + @Field(type = FieldType.String) + private String message; + private int rate; + @ScriptedField + private Long scriptedRate; + private boolean available; + private String highlightedMessage; + + private GeoPoint location; + + @Version + private Long version; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SampleEntity that = (SampleEntity) o; + + if (available != that.available) return false; + if (rate != that.rate) return false; + if (highlightedMessage != null ? !highlightedMessage.equals(that.highlightedMessage) : that.highlightedMessage != null) + return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (location != null ? !location.equals(that.location) : that.location != null) return false; + if (message != null ? !message.equals(that.message) : that.message != null) return false; + if (type != null ? !type.equals(that.type) : that.type != null) return false; + if (version != null ? !version.equals(that.version) : that.version != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (type != null ? type.hashCode() : 0); + result = 31 * result + (message != null ? message.hashCode() : 0); + result = 31 * result + rate; + result = 31 * result + (available ? 1 : 0); + result = 31 * result + (highlightedMessage != null ? highlightedMessage.hashCode() : 0); + result = 31 * result + (location != null ? location.hashCode() : 0); + result = 31 * result + (version != null ? version.hashCode() : 0); + return result; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/SampleMappingEntity.java b/src/test/java/org/springframework/data/elasticsearch/entities/SampleMappingEntity.java index 34fd62f7..dcd50f56 100644 --- a/src/test/java/org/springframework/data/elasticsearch/entities/SampleMappingEntity.java +++ b/src/test/java/org/springframework/data/elasticsearch/entities/SampleMappingEntity.java @@ -1,69 +1,69 @@ -/* - * 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.entities; - -import static org.springframework.data.elasticsearch.annotations.FieldIndex.*; -import static org.springframework.data.elasticsearch.annotations.FieldType.String; - -import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Field; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -@Document(indexName = "test-mapping", type = "mapping", shards = 1, replicas = 0, refreshInterval = "-1") -public class SampleMappingEntity { - - @Id - private String id; - - @Field(type = String, index = not_analyzed, store = true, analyzer = "standard") - private String message; - - private NestedEntity nested; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - static class NestedEntity { - - @Field(type = String) - private String someField; - - public String getSomeField() { - return someField; - } - - public void setSomeField(String someField) { - this.someField = someField; - } - } -} +/* + * 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.entities; + +import static org.springframework.data.elasticsearch.annotations.FieldIndex.*; +import static org.springframework.data.elasticsearch.annotations.FieldType.String; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +@Document(indexName = "test-mapping", type = "mapping", shards = 1, replicas = 0, refreshInterval = "-1") +public class SampleMappingEntity { + + @Id + private String id; + + @Field(type = String, index = not_analyzed, store = true, analyzer = "standard") + private String message; + + private NestedEntity nested; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + static class NestedEntity { + + @Field(type = String) + private String someField; + + public String getSomeField() { + return someField; + } + + public void setSomeField(String someField) { + this.someField = someField; + } + } +} 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 8206a97c..ad1690cf 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java @@ -1,1209 +1,1209 @@ -/* - * 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.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 - */ -@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.save(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 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.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 + */ +@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.save(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/book/SampleElasticSearchBookRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/book/SampleElasticSearchBookRepository.java index ac6a70fa..eb5b6f81 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/book/SampleElasticSearchBookRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/book/SampleElasticSearchBookRepository.java @@ -1,27 +1,27 @@ -/* - * Copyright 2013-2014 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.book; - -import org.springframework.data.elasticsearch.entities.Book; -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public interface SampleElasticSearchBookRepository extends ElasticsearchRepository { - -} +/* + * Copyright 2013-2014 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.book; + +import org.springframework.data.elasticsearch.entities.Book; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public interface SampleElasticSearchBookRepository extends ElasticsearchRepository { + +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiProductRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiProductRepository.java index 89afa882..2c74ff9e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiProductRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiProductRepository.java @@ -1,28 +1,28 @@ -/* - * Copyright 2014 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.cdi; - -import org.springframework.data.elasticsearch.entities.Product; -import org.springframework.data.repository.CrudRepository; - -/** - * @author Mohsin Husen - * @author Oliver Gierke - */ -public interface CdiProductRepository extends CrudRepository { - - Product findOne(String id); -} +/* + * Copyright 2014 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.cdi; + +import org.springframework.data.elasticsearch.entities.Product; +import org.springframework.data.repository.CrudRepository; + +/** + * @author Mohsin Husen + * @author Oliver Gierke + */ +public interface CdiProductRepository extends CrudRepository { + + Product findOne(String id); +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryClient.java b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryClient.java index 7103f313..72b99707 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryClient.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryClient.java @@ -1,58 +1,58 @@ -/* - * Copyright 2014-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.repositories.cdi; - -import javax.inject.Inject; - -/** - * @author Mohsin Husen - * @author Oliver Gierke - * @author Mark Paluch - */ -class CdiRepositoryClient { - - private CdiProductRepository repository; - private SamplePersonRepository samplePersonRepository; - private QualifiedProductRepository qualifiedProductRepository; - - public CdiProductRepository getRepository() { - return repository; - } - - @Inject - public void setRepository(CdiProductRepository repository) { - this.repository = repository; - } - - public SamplePersonRepository getSamplePersonRepository() { - return samplePersonRepository; - } - - @Inject - public void setSamplePersonRepository(SamplePersonRepository samplePersonRepository) { - this.samplePersonRepository = samplePersonRepository; - } - - public QualifiedProductRepository getQualifiedProductRepository() { - return qualifiedProductRepository; - } - - @Inject - public void setQualifiedProductRepository( - @PersonDB @OtherQualifier QualifiedProductRepository qualifiedProductRepository) { - this.qualifiedProductRepository = qualifiedProductRepository; - } -} +/* + * Copyright 2014-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.repositories.cdi; + +import javax.inject.Inject; + +/** + * @author Mohsin Husen + * @author Oliver Gierke + * @author Mark Paluch + */ +class CdiRepositoryClient { + + private CdiProductRepository repository; + private SamplePersonRepository samplePersonRepository; + private QualifiedProductRepository qualifiedProductRepository; + + public CdiProductRepository getRepository() { + return repository; + } + + @Inject + public void setRepository(CdiProductRepository repository) { + this.repository = repository; + } + + public SamplePersonRepository getSamplePersonRepository() { + return samplePersonRepository; + } + + @Inject + public void setSamplePersonRepository(SamplePersonRepository samplePersonRepository) { + this.samplePersonRepository = samplePersonRepository; + } + + public QualifiedProductRepository getQualifiedProductRepository() { + return qualifiedProductRepository; + } + + @Inject + public void setQualifiedProductRepository( + @PersonDB @OtherQualifier QualifiedProductRepository qualifiedProductRepository) { + this.qualifiedProductRepository = qualifiedProductRepository; + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java index ae55b171..0508dec6 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/CdiRepositoryTests.java @@ -1,128 +1,128 @@ -/* - * Copyright 2014-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.repositories.cdi; - -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; - -import org.apache.webbeans.cditest.CdiTestContainer; -import org.apache.webbeans.cditest.CdiTestContainerLoader; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.springframework.data.elasticsearch.entities.Product; - -/** - * @author Mohsin Husen - * @author Mark Paluch - */ -public class CdiRepositoryTests { - - private static CdiTestContainer cdiContainer; - private CdiProductRepository repository; - private SamplePersonRepository personRepository; - private QualifiedProductRepository qualifiedProductRepository; - - @BeforeClass - public static void init() throws Exception { - cdiContainer = CdiTestContainerLoader.getCdiContainer(); - cdiContainer.startApplicationScope(); - cdiContainer.bootContainer(); - } - - @AfterClass - public static void shutdown() throws Exception { - cdiContainer.stopContexts(); - cdiContainer.shutdownContainer(); - } - - @Before - public void setUp() { - CdiRepositoryClient client = cdiContainer.getInstance(CdiRepositoryClient.class); - repository = client.getRepository(); - personRepository = client.getSamplePersonRepository(); - qualifiedProductRepository = client.getQualifiedProductRepository(); - } - - @Test - public void testCdiRepository() { - assertNotNull(repository); - - Product bean = new Product(); - bean.setId("id-1"); - bean.setName("cidContainerTest-1"); - - repository.save(bean); - - assertTrue(repository.exists(bean.getId())); - - Product retrieved = repository.findOne(bean.getId()); - assertNotNull(retrieved); - assertEquals(bean.getId(), retrieved.getId()); - assertEquals(bean.getName(), retrieved.getName()); - - assertEquals(1, repository.count()); - - assertTrue(repository.exists(bean.getId())); - - repository.delete(bean); - - assertEquals(0, repository.count()); - retrieved = repository.findOne(bean.getId()); - assertNull(retrieved); - } - - /** - * @see DATAES-234 - */ - @Test - public void testQualifiedCdiRepository() { - assertNotNull(qualifiedProductRepository); - - Product bean = new Product(); - bean.setId("id-1"); - bean.setName("cidContainerTest-1"); - - qualifiedProductRepository.save(bean); - - assertTrue(qualifiedProductRepository.exists(bean.getId())); - - Product retrieved = qualifiedProductRepository.findOne(bean.getId()); - assertNotNull(retrieved); - assertEquals(bean.getId(), retrieved.getId()); - assertEquals(bean.getName(), retrieved.getName()); - - assertEquals(1, qualifiedProductRepository.count()); - - assertTrue(qualifiedProductRepository.exists(bean.getId())); - - qualifiedProductRepository.delete(bean); - - assertEquals(0, qualifiedProductRepository.count()); - retrieved = qualifiedProductRepository.findOne(bean.getId()); - assertNull(retrieved); - } - - /** - * @see DATAES-113 - */ - @Test - public void returnOneFromCustomImpl() { - - assertThat(personRepository.returnOne(), is(1)); - } -} +/* + * Copyright 2014-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.repositories.cdi; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.apache.webbeans.cditest.CdiTestContainer; +import org.apache.webbeans.cditest.CdiTestContainerLoader; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.data.elasticsearch.entities.Product; + +/** + * @author Mohsin Husen + * @author Mark Paluch + */ +public class CdiRepositoryTests { + + private static CdiTestContainer cdiContainer; + private CdiProductRepository repository; + private SamplePersonRepository personRepository; + private QualifiedProductRepository qualifiedProductRepository; + + @BeforeClass + public static void init() throws Exception { + cdiContainer = CdiTestContainerLoader.getCdiContainer(); + cdiContainer.startApplicationScope(); + cdiContainer.bootContainer(); + } + + @AfterClass + public static void shutdown() throws Exception { + cdiContainer.stopContexts(); + cdiContainer.shutdownContainer(); + } + + @Before + public void setUp() { + CdiRepositoryClient client = cdiContainer.getInstance(CdiRepositoryClient.class); + repository = client.getRepository(); + personRepository = client.getSamplePersonRepository(); + qualifiedProductRepository = client.getQualifiedProductRepository(); + } + + @Test + public void testCdiRepository() { + assertNotNull(repository); + + Product bean = new Product(); + bean.setId("id-1"); + bean.setName("cidContainerTest-1"); + + repository.save(bean); + + assertTrue(repository.exists(bean.getId())); + + Product retrieved = repository.findOne(bean.getId()); + assertNotNull(retrieved); + assertEquals(bean.getId(), retrieved.getId()); + assertEquals(bean.getName(), retrieved.getName()); + + assertEquals(1, repository.count()); + + assertTrue(repository.exists(bean.getId())); + + repository.delete(bean); + + assertEquals(0, repository.count()); + retrieved = repository.findOne(bean.getId()); + assertNull(retrieved); + } + + /** + * @see DATAES-234 + */ + @Test + public void testQualifiedCdiRepository() { + assertNotNull(qualifiedProductRepository); + + Product bean = new Product(); + bean.setId("id-1"); + bean.setName("cidContainerTest-1"); + + qualifiedProductRepository.save(bean); + + assertTrue(qualifiedProductRepository.exists(bean.getId())); + + Product retrieved = qualifiedProductRepository.findOne(bean.getId()); + assertNotNull(retrieved); + assertEquals(bean.getId(), retrieved.getId()); + assertEquals(bean.getName(), retrieved.getName()); + + assertEquals(1, qualifiedProductRepository.count()); + + assertTrue(qualifiedProductRepository.exists(bean.getId())); + + qualifiedProductRepository.delete(bean); + + assertEquals(0, qualifiedProductRepository.count()); + retrieved = qualifiedProductRepository.findOne(bean.getId()); + assertNull(retrieved); + } + + /** + * @see DATAES-113 + */ + @Test + public void returnOneFromCustomImpl() { + + assertThat(personRepository.returnOne(), is(1)); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/ElasticsearchTemplateProducer.java b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/ElasticsearchTemplateProducer.java index 69536c00..8623c352 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/ElasticsearchTemplateProducer.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/cdi/ElasticsearchTemplateProducer.java @@ -1,55 +1,55 @@ -/* - * Copyright 2014-2015 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.cdi; - -import javax.annotation.PreDestroy; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.inject.Produces; - -import org.elasticsearch.client.node.NodeClient; -import org.springframework.data.elasticsearch.Utils; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; - -/** - * @author Mohsin Husen - */ -@ApplicationScoped -class ElasticsearchTemplateProducer { - - @Produces - public NodeClient createNodeClient() { - return Utils.getNodeClient(); - } - - @Produces - public ElasticsearchOperations createElasticsearchTemplate(NodeClient nodeClient) { - return new ElasticsearchTemplate(nodeClient); - } - - @Produces - @OtherQualifier - @PersonDB - public ElasticsearchOperations createQualifiedElasticsearchTemplate(NodeClient nodeClient) { - return new ElasticsearchTemplate(nodeClient); - } - - @PreDestroy - public void shutdown() { - // remove everything to avoid conflicts with other tests in case server not shut down properly - } - -} +/* + * Copyright 2014-2015 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.cdi; + +import javax.annotation.PreDestroy; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; + +import org.elasticsearch.client.node.NodeClient; +import org.springframework.data.elasticsearch.Utils; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; + +/** + * @author Mohsin Husen + */ +@ApplicationScoped +class ElasticsearchTemplateProducer { + + @Produces + public NodeClient createNodeClient() { + return Utils.getNodeClient(); + } + + @Produces + public ElasticsearchOperations createElasticsearchTemplate(NodeClient nodeClient) { + return new ElasticsearchTemplate(nodeClient); + } + + @Produces + @OtherQualifier + @PersonDB + public ElasticsearchOperations createQualifiedElasticsearchTemplate(NodeClient nodeClient) { + return new ElasticsearchTemplate(nodeClient); + } + + @PreDestroy + public void shutdown() { + // remove everything to avoid conflicts with other tests in case server not shut down properly + } + +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java index 84a5d2a6..47ebfe70 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java @@ -1,132 +1,132 @@ -/* - * 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.repositories.custom; - -import java.util.List; -import java.util.stream.Stream; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.annotations.Query; -import org.springframework.data.elasticsearch.core.geo.GeoBox; -import org.springframework.data.elasticsearch.core.geo.GeoPoint; -import org.springframework.data.elasticsearch.entities.SampleEntity; -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; -import org.springframework.data.geo.Box; -import org.springframework.data.geo.Distance; -import org.springframework.data.geo.Point; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Kevin Leturc - */ -public interface SampleCustomMethodRepository extends ElasticsearchRepository { - - Page findByType(String type, Pageable pageable); - - Page findByTypeNot(String type, Pageable pageable); - - @Query("{\"bool\" : {\"must\" : {\"term\" : {\"message\" : \"?0\"}}}}") - Page findByMessage(String message, Pageable pageable); - - @Query("{\"bool\" : {\"must\" : {\"term\" : {\"message\" : \"?0\"}}}}") - List findByMessage(String message); - - Page findByAvailable(boolean available, Pageable pageable); - - Page findByRateLessThan(int rate, Pageable pageable); - - Page findByRateBefore(int rate, Pageable pageable); - - Page findByRateAfter(int rate, Pageable pageable); - - Page findByMessageLike(String message, Pageable pageable); - - Page findByMessageStartingWith(String message, Pageable pageable); - - Page findByMessageEndingWith(String message, Pageable pageable); - - Page findByMessageContaining(String message, Pageable pageable); - - Page findByIdIn(List ids, Pageable pageable); - - Page findByIdNotIn(List ids, Pageable pageable); - - Page findByAvailableTrue(Pageable pageable); - - Page findByAvailableFalse(Pageable pageable); - - Page findByMessageOrderByTypeAsc(String message, Pageable pageable); - - Page findByLocation(GeoPoint point, Pageable pageable); - - Page findByLocationAndMessage(GeoPoint point, String msg, Pageable pageable); - - Page findByLocationWithin(GeoPoint point, String distance, Pageable pageable); - - Page findByLocationWithin(Point point, Distance distance, Pageable pageable); - - Page findByLocationNear(GeoBox box, Pageable pageable); - - Page findByLocationNear(Box box, Pageable pageable); - - Page findByLocationNear(Point point, Distance distance, Pageable pageable); - - Page findByLocationNear(GeoPoint point, String distance, Pageable pageable); - - Stream findByType(String type); - - long countByType(String type); - - long countByTypeNot(String type); - - long countByAvailable(boolean available); - - long countByRateLessThan(int rate); - - long countByRateBefore(int rate); - - long countByRateAfter(int rate); - - long countByMessageLike(String message); - - long countByMessageStartingWith(String message); - - long countByMessageEndingWith(String message); - - long countByMessageContaining(String message); - - long countByIdIn(List ids); - - long countByIdNotIn(List ids); - - long countByAvailableTrue(); - - long countByAvailableFalse(); - - long countByLocationWithin(GeoPoint point, String distance); - - long countByLocationWithin(Point point, Distance distance); - - long countByLocationNear(GeoBox box); - - long countByLocationNear(Box box); - - long countByLocationNear(Point point, Distance distance); - - long countByLocationNear(GeoPoint point, String distance); -} +/* + * 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.repositories.custom; + +import java.util.List; +import java.util.stream.Stream; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.annotations.Query; +import org.springframework.data.elasticsearch.core.geo.GeoBox; +import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import org.springframework.data.geo.Box; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Kevin Leturc + */ +public interface SampleCustomMethodRepository extends ElasticsearchRepository { + + Page findByType(String type, Pageable pageable); + + Page findByTypeNot(String type, Pageable pageable); + + @Query("{\"bool\" : {\"must\" : {\"term\" : {\"message\" : \"?0\"}}}}") + Page findByMessage(String message, Pageable pageable); + + @Query("{\"bool\" : {\"must\" : {\"term\" : {\"message\" : \"?0\"}}}}") + List findByMessage(String message); + + Page findByAvailable(boolean available, Pageable pageable); + + Page findByRateLessThan(int rate, Pageable pageable); + + Page findByRateBefore(int rate, Pageable pageable); + + Page findByRateAfter(int rate, Pageable pageable); + + Page findByMessageLike(String message, Pageable pageable); + + Page findByMessageStartingWith(String message, Pageable pageable); + + Page findByMessageEndingWith(String message, Pageable pageable); + + Page findByMessageContaining(String message, Pageable pageable); + + Page findByIdIn(List ids, Pageable pageable); + + Page findByIdNotIn(List ids, Pageable pageable); + + Page findByAvailableTrue(Pageable pageable); + + Page findByAvailableFalse(Pageable pageable); + + Page findByMessageOrderByTypeAsc(String message, Pageable pageable); + + Page findByLocation(GeoPoint point, Pageable pageable); + + Page findByLocationAndMessage(GeoPoint point, String msg, Pageable pageable); + + Page findByLocationWithin(GeoPoint point, String distance, Pageable pageable); + + Page findByLocationWithin(Point point, Distance distance, Pageable pageable); + + Page findByLocationNear(GeoBox box, Pageable pageable); + + Page findByLocationNear(Box box, Pageable pageable); + + Page findByLocationNear(Point point, Distance distance, Pageable pageable); + + Page findByLocationNear(GeoPoint point, String distance, Pageable pageable); + + Stream findByType(String type); + + long countByType(String type); + + long countByTypeNot(String type); + + long countByAvailable(boolean available); + + long countByRateLessThan(int rate); + + long countByRateBefore(int rate); + + long countByRateAfter(int rate); + + long countByMessageLike(String message); + + long countByMessageStartingWith(String message); + + long countByMessageEndingWith(String message); + + long countByMessageContaining(String message); + + long countByIdIn(List ids); + + long countByIdNotIn(List ids); + + long countByAvailableTrue(); + + long countByAvailableFalse(); + + long countByLocationWithin(GeoPoint point, String distance); + + long countByLocationWithin(Point point, Distance distance); + + long countByLocationNear(GeoBox box); + + long countByLocationNear(Box box); + + long countByLocationNear(Point point, Distance distance); + + long countByLocationNear(GeoPoint point, String distance); +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityRepository.java index b51c3a26..998e3786 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityRepository.java @@ -1,30 +1,30 @@ -/* - * Copyright 2013-2014 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.nondocument; - -import org.springframework.context.annotation.Lazy; -import org.springframework.data.elasticsearch.entities.NonDocumentEntity; -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Oliver Gierke - */ -@Lazy -public interface NonDocumentEntityRepository extends ElasticsearchRepository { - -} +/* + * Copyright 2013-2014 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.nondocument; + +import org.springframework.context.annotation.Lazy; +import org.springframework.data.elasticsearch.entities.NonDocumentEntity; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + * @author Oliver Gierke + */ +@Lazy +public interface NonDocumentEntityRepository extends ElasticsearchRepository { + +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java index 009e5650..a38dcb4f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java @@ -1,34 +1,34 @@ -/* - * 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.repositories.sample; - -import java.util.List; - -import org.springframework.data.elasticsearch.entities.SampleEntity; -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -public interface SampleElasticsearchRepository extends ElasticsearchRepository { - - long deleteById(String id); - List deleteByAvailable(boolean available); - List deleteByMessage(String message); - void deleteByType(String type); - -} +/* + * 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.repositories.sample; + +import java.util.List; + +import org.springframework.data.elasticsearch.entities.SampleEntity; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +public interface SampleElasticsearchRepository extends ElasticsearchRepository { + + long deleteById(String id); + List deleteByAvailable(boolean available); + List deleteByMessage(String message); + void deleteByType(String type); + +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchRepositoryFactoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchRepositoryFactoryTests.java index 860fa449..2f83ba7f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchRepositoryFactoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchRepositoryFactoryTests.java @@ -1,63 +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.repository.support; - -import static org.mockito.Mockito.*; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; -import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; -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.mapping.context.MappingContext; -import org.springframework.data.querydsl.QueryDslPredicateExecutor; -import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - */ -@RunWith(MockitoJUnitRunner.class) -public class ElasticsearchRepositoryFactoryTests { - - @Mock - private ElasticsearchOperations operations; - private ElasticsearchConverter converter; - private ElasticsearchRepositoryFactory factory; - MappingContext, ElasticsearchPersistentProperty> mappingContext = new SimpleElasticsearchMappingContext(); - - @Before - public void before() { - converter = new MappingElasticsearchConverter(mappingContext); - when(operations.getElasticsearchConverter()).thenReturn(converter); - factory = new ElasticsearchRepositoryFactory(operations); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionGivenQueryDslRepository() { - // given - RepositoryMetadata metadata = new DefaultRepositoryMetadata(QueryDslPredicateExecutor.class); - // when - factory.getRepositoryBaseClass(metadata); - } -} +/* + * 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.repository.support; + +import static org.mockito.Mockito.*; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; +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.mapping.context.MappingContext; +import org.springframework.data.querydsl.QueryDslPredicateExecutor; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; + +/** + * @author Rizwan Idrees + * @author Mohsin Husen + */ +@RunWith(MockitoJUnitRunner.class) +public class ElasticsearchRepositoryFactoryTests { + + @Mock + private ElasticsearchOperations operations; + private ElasticsearchConverter converter; + private ElasticsearchRepositoryFactory factory; + MappingContext, ElasticsearchPersistentProperty> mappingContext = new SimpleElasticsearchMappingContext(); + + @Before + public void before() { + converter = new MappingElasticsearchConverter(mappingContext); + when(operations.getElasticsearchConverter()).thenReturn(converter); + factory = new ElasticsearchRepositoryFactory(operations); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionGivenQueryDslRepository() { + // given + RepositoryMetadata metadata = new DefaultRepositoryMetadata(QueryDslPredicateExecutor.class); + // when + factory.getRepositoryBaseClass(metadata); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java index 608d59d7..c536f36a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java @@ -1,548 +1,548 @@ -/* - * 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.repository.support; - -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 java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.google.common.collect.Lists; -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.query.NativeSearchQueryBuilder; -import org.springframework.data.elasticsearch.core.query.SearchQuery; -import org.springframework.data.elasticsearch.entities.SampleEntity; -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("classpath:/simple-repository-test.xml") -public class SimpleElasticsearchRepositoryTests { - - @Autowired - private SampleElasticsearchRepository repository; - - @Autowired - private ElasticsearchTemplate elasticsearchTemplate; - - - @Before - public void before() { - elasticsearchTemplate.deleteIndex(SampleEntity.class); - elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.refresh(SampleEntity.class); - } - - @Test - public void shouldDoBulkIndexDocument() { - // given - String documentId1 = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId1); - sampleEntity1.setMessage("some message"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("some message"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - // when - repository.save(Arrays.asList(sampleEntity1, sampleEntity2)); - // then - SampleEntity entity1FromElasticSearch = repository.findOne(documentId1); - assertThat(entity1FromElasticSearch, is(notNullValue())); - - SampleEntity entity2FromElasticSearch = repository.findOne(documentId2); - assertThat(entity2FromElasticSearch, is(notNullValue())); - } - - @Test - public void shouldSaveDocument() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("some message"); - sampleEntity.setVersion(System.currentTimeMillis()); - // when - repository.save(sampleEntity); - // then - SampleEntity entityFromElasticSearch = repository.findOne(documentId); - assertThat(entityFromElasticSearch, is(notNullValue())); - } - - @Test - public void shouldSaveDocumentWithoutId() { - // given - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setMessage("some message"); - sampleEntity.setVersion(System.currentTimeMillis()); - // when - repository.save(sampleEntity); - // then - assertThat(sampleEntity.getId(), is(notNullValue())); - } - - @Test - public void shouldFindDocumentById() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("some message"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - SampleEntity entityFromElasticSearch = repository.findOne(documentId); - // then - assertThat(entityFromElasticSearch, is(notNullValue())); - assertThat(sampleEntity, is((equalTo(sampleEntity)))); - } - - @Test - public void shouldReturnCountOfDocuments() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("some message"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - Long count = repository.count(); - // then - assertThat(count, is(greaterThanOrEqualTo(1L))); - } - - @Test - public void shouldFindAllDocuments() { - // when - Iterable results = repository.findAll(); - // then - assertThat(results, is(notNullValue())); - } - - @Test - public void shouldDeleteDocument() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("some message"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - repository.delete(documentId); - // then - SampleEntity entityFromElasticSearch = repository.findOne(documentId); - assertThat(entityFromElasticSearch, is(nullValue())); - } - - @Test - public void shouldSearchDocumentsGivenSearchQuery() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("some test message"); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - - SearchQuery query = new NativeSearchQueryBuilder().withQuery(termQuery("message", "test")).build(); - // when - Page page = repository.search(query); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getNumberOfElements(), is(greaterThanOrEqualTo(1))); - } - - @Test - public void shouldSearchDocumentsGivenElasticsearchQuery() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("hello world."); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - Page page = repository.search(termQuery("message", "world"), new PageRequest(0, 50)); - // then - assertThat(page, is(notNullValue())); - assertThat(page.getNumberOfElements(), is(greaterThanOrEqualTo(1))); - } - - /* - DATAES-82 - */ - @Test - public void shouldFindAllByIdQuery() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("hello world."); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("hello world."); - sampleEntity2.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity2); - - // when - Iterable sampleEntities = repository.findAll(Arrays.asList(documentId, documentId2)); - - // then - assertNotNull("sample entities cant be null..", sampleEntities); - List entities = Lists.newArrayList(sampleEntities); - assertThat(entities.size(), is(2)); - } - - @Test - public void shouldSaveIterableEntities() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("hello world."); - sampleEntity1.setVersion(System.currentTimeMillis()); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("hello world."); - sampleEntity2.setVersion(System.currentTimeMillis()); - - Iterable sampleEntities = Arrays.asList(sampleEntity1, sampleEntity2); - // when - repository.save(sampleEntities); - // then - Page entities = repository.search(termQuery("id", documentId), new PageRequest(0, 50)); - assertNotNull(entities); - } - - @Test - public void shouldReturnTrueGivenDocumentWithIdExists() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("hello world."); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - - // when - boolean exist = repository.exists(documentId); - - // then - assertEquals(exist, true); - } - - @Test - public void shouldReturnResultsForGivenSearchQuery() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("hello world."); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = repository.search(searchQuery); - // then - assertThat(sampleEntities.getTotalElements(), equalTo(1L)); - } - - @Test - public void shouldDeleteAll() { - // when - repository.deleteAll(); - // then - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = repository.search(searchQuery); - assertThat(sampleEntities.getTotalElements(), equalTo(0L)); - } - - @Test - public void shouldDeleteById() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("hello world."); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - long result = repository.deleteById(documentId); - repository.refresh(); - - // then - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = repository.search(searchQuery); - assertThat(sampleEntities.getTotalElements(), equalTo(0L)); - assertThat(result, equalTo(1L)); - } - - @Test - public void shouldDeleteByMessageAndReturnList() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("hello world 1"); - sampleEntity1.setAvailable(true); - sampleEntity1.setVersion(System.currentTimeMillis()); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setMessage("hello world 2"); - sampleEntity2.setAvailable(true); - sampleEntity2.setVersion(System.currentTimeMillis()); - - documentId = randomNumeric(5); - SampleEntity sampleEntity3 = new SampleEntity(); - sampleEntity3.setId(documentId); - sampleEntity3.setMessage("hello world 3"); - sampleEntity3.setAvailable(false); - sampleEntity3.setVersion(System.currentTimeMillis()); - repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - // when - List result = repository.deleteByAvailable(true); - repository.refresh(); - // then - assertThat(result.size(), equalTo(2)); - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = repository.search(searchQuery); - assertThat(sampleEntities.getTotalElements(), equalTo(1L)); - } - - @Test - public void shouldDeleteByListForMessage() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setMessage("hello world 1"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setMessage("hello world 2"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - documentId = randomNumeric(5); - SampleEntity sampleEntity3 = new SampleEntity(); - sampleEntity3.setId(documentId); - sampleEntity3.setMessage("hello world 3"); - sampleEntity3.setVersion(System.currentTimeMillis()); - repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - // when - List result = repository.deleteByMessage("hello world 3"); - repository.refresh(); - // then - assertThat(result.size(), equalTo(1)); - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = repository.search(searchQuery); - assertThat(sampleEntities.getTotalElements(), equalTo(2L)); - } - - @Test - public void shouldDeleteByType() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId); - sampleEntity1.setType("book"); - sampleEntity1.setVersion(System.currentTimeMillis()); - - documentId = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId); - sampleEntity2.setType("article"); - sampleEntity2.setVersion(System.currentTimeMillis()); - - documentId = randomNumeric(5); - SampleEntity sampleEntity3 = new SampleEntity(); - sampleEntity3.setId(documentId); - sampleEntity3.setType("image"); - sampleEntity3.setVersion(System.currentTimeMillis()); - repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - // when - repository.deleteByType("article"); - repository.refresh(); - // then - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = repository.search(searchQuery); - assertThat(sampleEntities.getTotalElements(), equalTo(2L)); - } - - @Test - public void shouldDeleteEntity() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("hello world."); - sampleEntity.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity); - // when - repository.delete(sampleEntity); - // then - SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = repository.search(searchQuery); - assertThat(sampleEntities.getTotalElements(), equalTo(0L)); - } - - @Test - public void shouldReturnIterableEntities() { - // given - String documentId1 = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId1); - sampleEntity1.setMessage("hello world."); - sampleEntity1.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity1); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("hello world."); - sampleEntity2.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity2); - - // when - Iterable sampleEntities = repository.search(termQuery("id", documentId1)); - // then - assertNotNull("sample entities cant be null..", sampleEntities); - } - - @Test - public void shouldDeleteIterableEntities() { - // given - String documentId1 = randomNumeric(5); - SampleEntity sampleEntity1 = new SampleEntity(); - sampleEntity1.setId(documentId1); - sampleEntity1.setMessage("hello world."); - sampleEntity1.setVersion(System.currentTimeMillis()); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("hello world."); - sampleEntity2.setVersion(System.currentTimeMillis()); - repository.save(sampleEntity2); - - Iterable sampleEntities = Arrays.asList(sampleEntity2, sampleEntity2); - // when - repository.delete(sampleEntities); - // then - assertThat(repository.findOne(documentId1), is(nullValue())); - assertThat(repository.findOne(documentId2), is(nullValue())); - } - - @Test - public void shouldIndexEntity() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setVersion(System.currentTimeMillis()); - sampleEntity.setMessage("some message"); - // when - repository.index(sampleEntity); - // then - Page entities = repository.search(termQuery("id", documentId), new PageRequest(0, 50)); - assertThat(entities.getTotalElements(), equalTo(1L)); - } - - @Test - public void shouldSortByGivenField() { - // given - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage("world"); - repository.save(sampleEntity); - - String documentId2 = randomNumeric(5); - SampleEntity sampleEntity2 = new SampleEntity(); - sampleEntity2.setId(documentId2); - sampleEntity2.setMessage("hello"); - repository.save(sampleEntity2); - // when - Iterable sampleEntities = repository.findAll(new Sort(new Sort.Order(Sort.Direction.ASC, "message"))); - // then - assertThat(sampleEntities, is(notNullValue())); - } - - @Test - public void shouldReturnSimilarEntities() { - // 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."; - - List sampleEntities = createSampleEntitiesWithMessage(sampleMessage, 30); - repository.save(sampleEntities); - - // when - Page results = repository.searchSimilar(sampleEntities.get(0), new String[]{"message"}, new PageRequest(0, 5)); - - // then - assertThat(results.getTotalElements(), is(greaterThanOrEqualTo(1L))); - } - - private static List createSampleEntitiesWithMessage(String message, int numberOfEntities) { - List sampleEntities = new ArrayList(); - for (int i = 0; i < numberOfEntities; i++) { - String documentId = randomNumeric(5); - SampleEntity sampleEntity = new SampleEntity(); - sampleEntity.setId(documentId); - sampleEntity.setMessage(message); - sampleEntity.setRate(2); - sampleEntity.setVersion(System.currentTimeMillis()); - sampleEntities.add(sampleEntity); - } - return sampleEntities; - } -} +/* + * 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.repository.support; + +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.google.common.collect.Lists; +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.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.data.elasticsearch.entities.SampleEntity; +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("classpath:/simple-repository-test.xml") +public class SimpleElasticsearchRepositoryTests { + + @Autowired + private SampleElasticsearchRepository repository; + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(SampleEntity.class); + elasticsearchTemplate.createIndex(SampleEntity.class); + elasticsearchTemplate.refresh(SampleEntity.class); + } + + @Test + public void shouldDoBulkIndexDocument() { + // given + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId1); + sampleEntity1.setMessage("some message"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("some message"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + // when + repository.save(Arrays.asList(sampleEntity1, sampleEntity2)); + // then + SampleEntity entity1FromElasticSearch = repository.findOne(documentId1); + assertThat(entity1FromElasticSearch, is(notNullValue())); + + SampleEntity entity2FromElasticSearch = repository.findOne(documentId2); + assertThat(entity2FromElasticSearch, is(notNullValue())); + } + + @Test + public void shouldSaveDocument() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + // when + repository.save(sampleEntity); + // then + SampleEntity entityFromElasticSearch = repository.findOne(documentId); + assertThat(entityFromElasticSearch, is(notNullValue())); + } + + @Test + public void shouldSaveDocumentWithoutId() { + // given + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + // when + repository.save(sampleEntity); + // then + assertThat(sampleEntity.getId(), is(notNullValue())); + } + + @Test + public void shouldFindDocumentById() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + SampleEntity entityFromElasticSearch = repository.findOne(documentId); + // then + assertThat(entityFromElasticSearch, is(notNullValue())); + assertThat(sampleEntity, is((equalTo(sampleEntity)))); + } + + @Test + public void shouldReturnCountOfDocuments() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + Long count = repository.count(); + // then + assertThat(count, is(greaterThanOrEqualTo(1L))); + } + + @Test + public void shouldFindAllDocuments() { + // when + Iterable results = repository.findAll(); + // then + assertThat(results, is(notNullValue())); + } + + @Test + public void shouldDeleteDocument() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some message"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + repository.delete(documentId); + // then + SampleEntity entityFromElasticSearch = repository.findOne(documentId); + assertThat(entityFromElasticSearch, is(nullValue())); + } + + @Test + public void shouldSearchDocumentsGivenSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("some test message"); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + + SearchQuery query = new NativeSearchQueryBuilder().withQuery(termQuery("message", "test")).build(); + // when + Page page = repository.search(query); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getNumberOfElements(), is(greaterThanOrEqualTo(1))); + } + + @Test + public void shouldSearchDocumentsGivenElasticsearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + Page page = repository.search(termQuery("message", "world"), new PageRequest(0, 50)); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getNumberOfElements(), is(greaterThanOrEqualTo(1))); + } + + /* + DATAES-82 + */ + @Test + public void shouldFindAllByIdQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("hello world."); + sampleEntity2.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity2); + + // when + Iterable sampleEntities = repository.findAll(Arrays.asList(documentId, documentId2)); + + // then + assertNotNull("sample entities cant be null..", sampleEntities); + List entities = Lists.newArrayList(sampleEntities); + assertThat(entities.size(), is(2)); + } + + @Test + public void shouldSaveIterableEntities() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("hello world."); + sampleEntity1.setVersion(System.currentTimeMillis()); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("hello world."); + sampleEntity2.setVersion(System.currentTimeMillis()); + + Iterable sampleEntities = Arrays.asList(sampleEntity1, sampleEntity2); + // when + repository.save(sampleEntities); + // then + Page entities = repository.search(termQuery("id", documentId), new PageRequest(0, 50)); + assertNotNull(entities); + } + + @Test + public void shouldReturnTrueGivenDocumentWithIdExists() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + + // when + boolean exist = repository.exists(documentId); + + // then + assertEquals(exist, true); + } + + @Test + public void shouldReturnResultsForGivenSearchQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = repository.search(searchQuery); + // then + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + } + + @Test + public void shouldDeleteAll() { + // when + repository.deleteAll(); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + } + + @Test + public void shouldDeleteById() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + long result = repository.deleteById(documentId); + repository.refresh(); + + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + assertThat(result, equalTo(1L)); + } + + @Test + public void shouldDeleteByMessageAndReturnList() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("hello world 1"); + sampleEntity1.setAvailable(true); + sampleEntity1.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setMessage("hello world 2"); + sampleEntity2.setAvailable(true); + sampleEntity2.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId); + sampleEntity3.setMessage("hello world 3"); + sampleEntity3.setAvailable(false); + sampleEntity3.setVersion(System.currentTimeMillis()); + repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + // when + List result = repository.deleteByAvailable(true); + repository.refresh(); + // then + assertThat(result.size(), equalTo(2)); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + } + + @Test + public void shouldDeleteByListForMessage() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("hello world 1"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setMessage("hello world 2"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId); + sampleEntity3.setMessage("hello world 3"); + sampleEntity3.setVersion(System.currentTimeMillis()); + repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + // when + List result = repository.deleteByMessage("hello world 3"); + repository.refresh(); + // then + assertThat(result.size(), equalTo(1)); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(2L)); + } + + @Test + public void shouldDeleteByType() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setType("book"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("article"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId); + sampleEntity3.setType("image"); + sampleEntity3.setVersion(System.currentTimeMillis()); + repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + // when + repository.deleteByType("article"); + repository.refresh(); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(2L)); + } + + @Test + public void shouldDeleteEntity() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + repository.delete(sampleEntity); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + } + + @Test + public void shouldReturnIterableEntities() { + // given + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId1); + sampleEntity1.setMessage("hello world."); + sampleEntity1.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity1); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("hello world."); + sampleEntity2.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity2); + + // when + Iterable sampleEntities = repository.search(termQuery("id", documentId1)); + // then + assertNotNull("sample entities cant be null..", sampleEntities); + } + + @Test + public void shouldDeleteIterableEntities() { + // given + String documentId1 = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId1); + sampleEntity1.setMessage("hello world."); + sampleEntity1.setVersion(System.currentTimeMillis()); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("hello world."); + sampleEntity2.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity2); + + Iterable sampleEntities = Arrays.asList(sampleEntity2, sampleEntity2); + // when + repository.delete(sampleEntities); + // then + assertThat(repository.findOne(documentId1), is(nullValue())); + assertThat(repository.findOne(documentId2), is(nullValue())); + } + + @Test + public void shouldIndexEntity() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setVersion(System.currentTimeMillis()); + sampleEntity.setMessage("some message"); + // when + repository.index(sampleEntity); + // then + Page entities = repository.search(termQuery("id", documentId), new PageRequest(0, 50)); + assertThat(entities.getTotalElements(), equalTo(1L)); + } + + @Test + public void shouldSortByGivenField() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("world"); + repository.save(sampleEntity); + + String documentId2 = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId2); + sampleEntity2.setMessage("hello"); + repository.save(sampleEntity2); + // when + Iterable sampleEntities = repository.findAll(new Sort(new Sort.Order(Sort.Direction.ASC, "message"))); + // then + assertThat(sampleEntities, is(notNullValue())); + } + + @Test + public void shouldReturnSimilarEntities() { + // 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."; + + List sampleEntities = createSampleEntitiesWithMessage(sampleMessage, 30); + repository.save(sampleEntities); + + // when + Page results = repository.searchSimilar(sampleEntities.get(0), new String[]{"message"}, new PageRequest(0, 5)); + + // then + assertThat(results.getTotalElements(), is(greaterThanOrEqualTo(1L))); + } + + private static List createSampleEntitiesWithMessage(String message, int numberOfEntities) { + List sampleEntities = new ArrayList(); + for (int i = 0; i < numberOfEntities; i++) { + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage(message); + sampleEntity.setRate(2); + sampleEntity.setVersion(System.currentTimeMillis()); + sampleEntities.add(sampleEntity); + } + return sampleEntities; + } +} diff --git a/src/test/resources/META-INF/beans.xml b/src/test/resources/META-INF/beans.xml index cc7c5873..4ca8195b 100644 --- a/src/test/resources/META-INF/beans.xml +++ b/src/test/resources/META-INF/beans.xml @@ -1,5 +1,5 @@ - - - + + + diff --git a/src/test/resources/custom-method-repository-test.xml b/src/test/resources/custom-method-repository-test.xml index 5b54cdb0..19c78df8 100644 --- a/src/test/resources/custom-method-repository-test.xml +++ b/src/test/resources/custom-method-repository-test.xml @@ -1,19 +1,19 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/elasticsearch-template-test.xml b/src/test/resources/elasticsearch-template-test.xml index afc5bbd2..310b954f 100644 --- a/src/test/resources/elasticsearch-template-test.xml +++ b/src/test/resources/elasticsearch-template-test.xml @@ -1,13 +1,13 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/infrastructure.xml b/src/test/resources/infrastructure.xml index 06bb606b..f656d689 100644 --- a/src/test/resources/infrastructure.xml +++ b/src/test/resources/infrastructure.xml @@ -1,18 +1,18 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/repository-non-document-entity.xml b/src/test/resources/repository-non-document-entity.xml index 1c540f6e..df7400eb 100644 --- a/src/test/resources/repository-non-document-entity.xml +++ b/src/test/resources/repository-non-document-entity.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/repository-test-nested-object.xml b/src/test/resources/repository-test-nested-object.xml index af1135ef..2303931b 100644 --- a/src/test/resources/repository-test-nested-object.xml +++ b/src/test/resources/repository-test-nested-object.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/simple-repository-test.xml b/src/test/resources/simple-repository-test.xml index 907e2cc4..09fe3721 100644 --- a/src/test/resources/simple-repository-test.xml +++ b/src/test/resources/simple-repository-test.xml @@ -1,19 +1,19 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file