Compare commits
93 Commits
5.5.12
...
3.0.11.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 1048972ffb | |||
| 37f0dde79c | |||
| d149b3af58 | |||
| ba15cf1242 | |||
| fdc10888f4 | |||
| 0154d8fc16 | |||
| a019f24bb2 | |||
| 0bda2e7d66 | |||
| 4bdc67ec5b | |||
| 5b26ab3e08 | |||
| 82334e5668 | |||
| dcdf9a7630 | |||
| 30615008a9 | |||
| e1353ac956 | |||
| f42c6eaa06 | |||
| 415464a957 | |||
| 3be999e23d | |||
| eb59b657d2 | |||
| 076303bf2f | |||
| 3d2b5a0191 | |||
| 2497fcd64d | |||
| 0fbb4ca225 | |||
| 37bc97d5eb | |||
| 26eba03116 | |||
| 55bf1f233d | |||
| c9fbdb7126 | |||
| a1d508c656 | |||
| 04308394dd | |||
| be80d7eae4 | |||
| de1c28979d | |||
| bd668e6c2a | |||
| ba899a0017 | |||
| 8181c713c7 | |||
| c6419a1f05 | |||
| 09ee8f9026 | |||
| 13cfb039b5 | |||
| 4c9c03ac0b | |||
| cd597f059e | |||
| 7cf251a24e | |||
| fe5426b870 | |||
| 01a37c4fc3 | |||
| 021495580f | |||
| 4970783ca4 | |||
| 5ac31b3d2b | |||
| 71b2ffc128 | |||
| 2642836e4d | |||
| 849d7da652 | |||
| 5e29b958e5 | |||
| 1b1ef4b5f4 | |||
| 79636c2a29 | |||
| 787fc897d3 | |||
| 4bdaf039c2 | |||
| 35003bf942 | |||
| be230f4003 | |||
| 8c1821e7a6 | |||
| 72a2f9f758 | |||
| d9d3521518 | |||
| d50ae96c5e | |||
| 734a28fb03 | |||
| ac403b9198 | |||
| 477c4d1dc3 | |||
| 2b543ff026 | |||
| 02a3e120c2 | |||
| 92286a725d | |||
| 462288be0e | |||
| b844f47795 | |||
| fe488eac32 | |||
| a77b81ecb3 | |||
| 81795f67cd | |||
| 485859ca3d | |||
| 8973d2d7eb | |||
| a525a38825 | |||
| b392090e61 | |||
| ca4a864f9e | |||
| 3a31030f89 | |||
| 34a7900e34 | |||
| 361bc2a333 | |||
| c2c21581d8 | |||
| ecf2efa6e5 | |||
| 418d259fbf | |||
| 737a023b5a | |||
| cc3f578312 | |||
| 81b21f4e6f | |||
| 552cbff6a4 | |||
| 000eb152dc | |||
| ad55402973 | |||
| ef68623d5b | |||
| c075f170c3 | |||
| 02b7dde196 | |||
| 51b7fa2a26 | |||
| 4e5051c57b | |||
| 31d499e6e0 | |||
| 311a06aa67 |
@@ -52,17 +52,12 @@ the appropriate dependency version.
|
|||||||
</repository>
|
</repository>
|
||||||
```
|
```
|
||||||
|
|
||||||
| spring data elasticsearch | elasticsearch |
|
| spring data elasticsearch | elasticsearch |
|
||||||
|:-----------------------------------:|:-------------:|
|
|:-------------------------:|:-------------:|
|
||||||
| 3.0.0.RC2 | 5.5.0 |
|
| 3.0.x | 5.5.0 |
|
||||||
| 3.0.0.M4 | 5.4.0 |
|
| 2.1.x | 2.4.0 |
|
||||||
| 2.0.4.RELEASE | 2.4.0 |
|
| 2.0.x | 2.2.0 |
|
||||||
| 2.0.0.RELEASE | 2.2.0 |
|
| 1.3.x | 1.5.2 |
|
||||||
| 1.4.0.M1 | 1.7.3 |
|
|
||||||
| 1.3.0.RELEASE | 1.5.2 |
|
|
||||||
| 1.2.0.RELEASE | 1.4.4 |
|
|
||||||
| 1.1.0.RELEASE | 1.3.2 |
|
|
||||||
| 1.0.0.RELEASE | 1.1.1 |
|
|
||||||
|
|
||||||
|
|
||||||
### ElasticsearchRepository
|
### ElasticsearchRepository
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-elasticsearch</artifactId>
|
<artifactId>spring-data-elasticsearch</artifactId>
|
||||||
<version>3.0.0.RELEASE</version>
|
<version>3.0.11.RELEASE</version>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data.build</groupId>
|
<groupId>org.springframework.data.build</groupId>
|
||||||
<artifactId>spring-data-parent</artifactId>
|
<artifactId>spring-data-parent</artifactId>
|
||||||
<version>2.0.0.RELEASE</version>
|
<version>2.0.11.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<name>Spring Data Elasticsearch</name>
|
<name>Spring Data Elasticsearch</name>
|
||||||
@@ -20,7 +20,8 @@
|
|||||||
<commonscollections>3.2.1</commonscollections>
|
<commonscollections>3.2.1</commonscollections>
|
||||||
<commonslang>2.6</commonslang>
|
<commonslang>2.6</commonslang>
|
||||||
<elasticsearch>5.5.0</elasticsearch>
|
<elasticsearch>5.5.0</elasticsearch>
|
||||||
<springdata.commons>2.0.0.RELEASE</springdata.commons>
|
<log4j>2.8.2</log4j>
|
||||||
|
<springdata.commons>2.0.11.RELEASE</springdata.commons>
|
||||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
<groupId>commons-lang</groupId>
|
<groupId>commons-lang</groupId>
|
||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang</artifactId>
|
||||||
<version>${commonslang}</version>
|
<version>${commonslang}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JODA Time -->
|
<!-- JODA Time -->
|
||||||
@@ -65,12 +67,6 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Elasticsearch -->
|
<!-- Elasticsearch -->
|
||||||
<dependency>
|
|
||||||
<groupId>org.elasticsearch</groupId>
|
|
||||||
<artifactId>elasticsearch</artifactId>
|
|
||||||
<version>${elasticsearch}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.elasticsearch.client</groupId>
|
<groupId>org.elasticsearch.client</groupId>
|
||||||
<artifactId>transport</artifactId>
|
<artifactId>transport</artifactId>
|
||||||
@@ -80,31 +76,41 @@
|
|||||||
<groupId>commons-logging</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.elasticsearch.plugin</groupId>
|
||||||
|
<artifactId>transport-netty3-client</artifactId>
|
||||||
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.elasticsearch.plugin</groupId>
|
||||||
|
<artifactId>transport-netty4-client</artifactId>
|
||||||
|
<version>${elasticsearch}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>log4j-over-slf4j</artifactId>
|
<artifactId>log4j-over-slf4j</artifactId>
|
||||||
<version>1.7.22</version>
|
<version>${slf4j}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-core</artifactId>
|
<artifactId>log4j-core</artifactId>
|
||||||
<version>2.8.2</version>
|
<version>${log4j}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Jackson JSON Mapper -->
|
<!-- Jackson JSON Mapper -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-core</artifactId>
|
<artifactId>jackson-core</artifactId>
|
||||||
<version>${jackson}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>${jackson}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- CDI -->
|
<!-- CDI -->
|
||||||
@@ -161,14 +167,6 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<!-- required by elasticsearch -->
|
|
||||||
<groupId>org.elasticsearch.plugin</groupId>
|
|
||||||
<artifactId>transport-netty4-client</artifactId>
|
|
||||||
<version>${elasticsearch}</version>
|
|
||||||
<!--<scope>test</scope>-->
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
@@ -176,8 +174,6 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.annotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Artur Konczak
|
|
||||||
* @author Mohsin Husen
|
|
||||||
* @author Alexander Volz
|
|
||||||
* @author Dennis Maaß
|
|
||||||
*/
|
|
||||||
public enum FieldIndex {
|
|
||||||
not_analyzed, analyzed, no
|
|
||||||
}
|
|
||||||
@@ -21,5 +21,17 @@ package org.springframework.data.elasticsearch.annotations;
|
|||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
*/
|
*/
|
||||||
public enum FieldType {
|
public enum FieldType {
|
||||||
text, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment, keyword
|
Text,
|
||||||
|
Integer,
|
||||||
|
Long,
|
||||||
|
Date,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
Boolean,
|
||||||
|
Object,
|
||||||
|
Auto,
|
||||||
|
Nested,
|
||||||
|
Ip,
|
||||||
|
Attachment,
|
||||||
|
Keyword
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,11 +33,15 @@ public @interface InnerField {
|
|||||||
|
|
||||||
boolean index() default true;
|
boolean index() default true;
|
||||||
|
|
||||||
|
DateFormat format() default DateFormat.none;
|
||||||
|
|
||||||
|
String pattern() default "";
|
||||||
|
|
||||||
boolean store() default false;
|
boolean store() default false;
|
||||||
|
|
||||||
boolean fielddata() default false;
|
boolean fielddata() default false;
|
||||||
|
|
||||||
String searchAnalyzer() default "";
|
String searchAnalyzer() default "";
|
||||||
|
|
||||||
String indexAnalyzer() default "";
|
String analyzer() default "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.elasticsearch.client;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||||
|
import org.elasticsearch.common.transport.TransportAddress;
|
||||||
|
import org.springframework.data.util.Streamable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to represent a list of cluster nodes.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 3.0.9
|
||||||
|
*/
|
||||||
|
class ClusterNodes implements Streamable<TransportAddress> {
|
||||||
|
|
||||||
|
public static ClusterNodes DEFAULT = ClusterNodes.of("127.0.0.1:9300");
|
||||||
|
|
||||||
|
private static final String COLON = ":";
|
||||||
|
private static final String COMMA = ",";
|
||||||
|
|
||||||
|
private final List<TransportAddress> clusterNodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ClusterNodes} by parsing the given source.
|
||||||
|
*
|
||||||
|
* @param source must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
private ClusterNodes(String source) {
|
||||||
|
|
||||||
|
Assert.hasText(source, "Cluster nodes source must not be null or empty!");
|
||||||
|
|
||||||
|
String[] nodes = StringUtils.delimitedListToStringArray(source, COMMA);
|
||||||
|
|
||||||
|
this.clusterNodes = Arrays.stream(nodes).map(node -> {
|
||||||
|
|
||||||
|
String[] segments = StringUtils.delimitedListToStringArray(node, COLON);
|
||||||
|
|
||||||
|
Assert.isTrue(segments.length == 2,
|
||||||
|
() -> String.format("Invalid cluster node %s in %s! Must be in the format host:port!", node, source));
|
||||||
|
|
||||||
|
String host = segments[0].trim();
|
||||||
|
String port = segments[1].trim();
|
||||||
|
|
||||||
|
Assert.hasText(host, () -> String.format("No host name given cluster node %s!", node));
|
||||||
|
Assert.hasText(port, () -> String.format("No port given in cluster node %s!", node));
|
||||||
|
|
||||||
|
return new InetSocketTransportAddress(toInetAddress(host), Integer.valueOf(port));
|
||||||
|
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ClusterNodes} by parsing the given source. The expected format is a comma separated list of
|
||||||
|
* host-port-combinations separated by a colon: {@code host:port,host:port,…}.
|
||||||
|
*
|
||||||
|
* @param source must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ClusterNodes of(String source) {
|
||||||
|
return new ClusterNodes(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Iterable#iterator()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<TransportAddress> iterator() {
|
||||||
|
return clusterNodes.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InetAddress toInetAddress(String host) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return InetAddress.getByName(host);
|
||||||
|
} catch (UnknownHostException o_O) {
|
||||||
|
throw new IllegalArgumentException(o_O);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-3
@@ -15,10 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.client;
|
package org.springframework.data.elasticsearch.client;
|
||||||
|
|
||||||
|
import static java.util.Arrays.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.client.node.NodeClient;
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
@@ -31,7 +33,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import static java.util.Arrays.*;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeClientFactoryBean
|
* NodeClientFactoryBean
|
||||||
@@ -96,7 +98,7 @@ public class NodeClientFactoryBean implements FactoryBean<Client>, InitializingB
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Settings loadConfig() throws IOException {
|
private Settings loadConfig() throws IOException {
|
||||||
if (StringUtils.isNotBlank(pathConfiguration)) {
|
if (!StringUtils.isEmpty(pathConfiguration)) {
|
||||||
InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration);
|
InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration);
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration)).build();
|
return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration)).build();
|
||||||
|
|||||||
+122
-23
@@ -15,14 +15,27 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.client;
|
package org.springframework.data.elasticsearch.client;
|
||||||
|
|
||||||
import static org.apache.commons.lang.StringUtils.*;
|
import io.netty.util.ThreadDeathWatcher;
|
||||||
|
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.elasticsearch.client.transport.TransportClient;
|
import org.elasticsearch.client.transport.TransportClient;
|
||||||
|
import org.elasticsearch.common.SuppressForbidden;
|
||||||
|
import org.elasticsearch.common.network.NetworkModule;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
import org.elasticsearch.index.reindex.ReindexPlugin;
|
||||||
|
import org.elasticsearch.join.ParentJoinPlugin;
|
||||||
|
import org.elasticsearch.percolator.PercolatorPlugin;
|
||||||
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.script.mustache.MustachePlugin;
|
||||||
|
import org.elasticsearch.transport.Netty4Plugin;
|
||||||
import org.elasticsearch.transport.client.PreBuiltTransportClient;
|
import org.elasticsearch.transport.client.PreBuiltTransportClient;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -30,6 +43,7 @@ import org.springframework.beans.factory.DisposableBean;
|
|||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TransportClientFactoryBean
|
* TransportClientFactoryBean
|
||||||
@@ -38,12 +52,12 @@ import org.springframework.util.Assert;
|
|||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
* @author Jakub Vavrik
|
* @author Jakub Vavrik
|
||||||
* @author Piotr Betkier
|
* @author Piotr Betkier
|
||||||
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TransportClientFactoryBean implements FactoryBean<TransportClient>, InitializingBean, DisposableBean {
|
public class TransportClientFactoryBean implements FactoryBean<TransportClient>, InitializingBean, DisposableBean {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
|
private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
|
||||||
private String clusterNodes = "127.0.0.1:9300";
|
private ClusterNodes clusterNodes = ClusterNodes.of("127.0.0.1:9300");
|
||||||
private String clusterName = "elasticsearch";
|
private String clusterName = "elasticsearch";
|
||||||
private Boolean clientTransportSniff = true;
|
private Boolean clientTransportSniff = true;
|
||||||
private Boolean clientIgnoreClusterName = Boolean.FALSE;
|
private Boolean clientIgnoreClusterName = Boolean.FALSE;
|
||||||
@@ -51,8 +65,6 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
private String clientNodesSamplerInterval = "5s";
|
private String clientNodesSamplerInterval = "5s";
|
||||||
private TransportClient client;
|
private TransportClient client;
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
static final String COLON = ":";
|
|
||||||
static final String COMMA = ",";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() throws Exception {
|
public void destroy() throws Exception {
|
||||||
@@ -88,16 +100,12 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
|
|
||||||
protected void buildClient() throws Exception {
|
protected void buildClient() throws Exception {
|
||||||
|
|
||||||
client = new PreBuiltTransportClient(settings());
|
client = new SpringDataTransportClient(settings());
|
||||||
Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing.");
|
|
||||||
for (String clusterNode : split(clusterNodes, COMMA)) {
|
clusterNodes.stream() //
|
||||||
String hostName = substringBeforeLast(clusterNode, COLON);
|
.peek(it -> logger.info("Adding transport node : " + it.toString())) //
|
||||||
String port = substringAfterLast(clusterNode, COLON);
|
.forEach(client::addTransportAddress);
|
||||||
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();
|
client.connectedNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,17 +113,14 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
return Settings.builder().put(properties).build();
|
return Settings.builder().put(properties).build();
|
||||||
}
|
}
|
||||||
return Settings.builder()
|
return Settings.builder().put("cluster.name", clusterName).put("client.transport.sniff", clientTransportSniff)
|
||||||
.put("cluster.name", clusterName)
|
|
||||||
.put("client.transport.sniff", clientTransportSniff)
|
|
||||||
.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
|
.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
|
||||||
.put("client.transport.ping_timeout", clientPingTimeout)
|
.put("client.transport.ping_timeout", clientPingTimeout)
|
||||||
.put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval)
|
.put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval).build();
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClusterNodes(String clusterNodes) {
|
public void setClusterNodes(String clusterNodes) {
|
||||||
this.clusterNodes = clusterNodes;
|
this.clusterNodes = ClusterNodes.of(clusterNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClusterName(String clusterName) {
|
public void setClusterName(String clusterName) {
|
||||||
@@ -153,4 +158,98 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
public void setProperties(Properties properties) {
|
public void setProperties(Properties properties) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pretty exact copy of {@link PreBuiltTransportClient} except that we're inspecting the classpath for Netty
|
||||||
|
* dependencies to only include the ones available. {@link PreBuiltTransportClient} expects both Netty 3 and Netty 4
|
||||||
|
* to be present.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @see https://github.com/elastic/elasticsearch/issues/31240
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static class SpringDataTransportClient extends TransportClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Netty wants to do some unwelcome things like use unsafe and replace a private field, or use a poorly considered
|
||||||
|
* buffer recycler. This method disables these things by default, but can be overridden by setting the corresponding
|
||||||
|
* system properties.
|
||||||
|
*/
|
||||||
|
private static void initializeNetty() {
|
||||||
|
/*
|
||||||
|
* We disable three pieces of Netty functionality here:
|
||||||
|
* - we disable Netty from being unsafe
|
||||||
|
* - we disable Netty from replacing the selector key set
|
||||||
|
* - we disable Netty from using the recycler
|
||||||
|
*
|
||||||
|
* While permissions are needed to read and set these, the permissions needed here are innocuous and thus should simply be granted
|
||||||
|
* rather than us handling a security exception here.
|
||||||
|
*/
|
||||||
|
setSystemPropertyIfUnset("io.netty.noUnsafe", Boolean.toString(true));
|
||||||
|
setSystemPropertyIfUnset("io.netty.noKeySetOptimization", Boolean.toString(true));
|
||||||
|
setSystemPropertyIfUnset("io.netty.recycler.maxCapacityPerThread", Integer.toString(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressForbidden(reason = "set system properties to configure Netty")
|
||||||
|
private static void setSystemPropertyIfUnset(final String key, final String value) {
|
||||||
|
final String currentValue = System.getProperty(key);
|
||||||
|
if (currentValue == null) {
|
||||||
|
System.setProperty(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final List<String> OPTIONAL_DEPENDENCIES = Arrays.asList( //
|
||||||
|
"org.elasticsearch.transport.Netty3Plugin", //
|
||||||
|
"org.elasticsearch.transport.Netty4Plugin");
|
||||||
|
|
||||||
|
private static final Collection<Class<? extends Plugin>> PRE_INSTALLED_PLUGINS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
|
||||||
|
initializeNetty();
|
||||||
|
|
||||||
|
List<Class<? extends Plugin>> plugins = new ArrayList<>();
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (String dependency : OPTIONAL_DEPENDENCIES) {
|
||||||
|
try {
|
||||||
|
plugins.add((Class<? extends Plugin>) ClassUtils.forName(dependency,
|
||||||
|
SpringDataTransportClient.class.getClassLoader()));
|
||||||
|
found = true;
|
||||||
|
} catch (ClassNotFoundException | LinkageError e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.state(found,
|
||||||
|
"Neither Netty 3 or Netty 4 plugin found on the classpath. One of them is required to run the transport client!");
|
||||||
|
|
||||||
|
plugins.add(ReindexPlugin.class);
|
||||||
|
plugins.add(PercolatorPlugin.class);
|
||||||
|
plugins.add(MustachePlugin.class);
|
||||||
|
plugins.add(ParentJoinPlugin.class);
|
||||||
|
|
||||||
|
PRE_INSTALLED_PLUGINS = Collections.unmodifiableList(plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpringDataTransportClient(Settings settings) {
|
||||||
|
super(settings, PRE_INSTALLED_PLUGINS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
super.close();
|
||||||
|
if (NetworkModule.TRANSPORT_TYPE_SETTING.exists(settings) == false
|
||||||
|
|| NetworkModule.TRANSPORT_TYPE_SETTING.get(settings).equals(Netty4Plugin.NETTY_TRANSPORT_NAME)) {
|
||||||
|
try {
|
||||||
|
GlobalEventExecutor.INSTANCE.awaitInactivity(5, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ThreadDeathWatcher.awaitInactivity(5, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import static org.apache.commons.lang.StringUtils.*;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
@@ -33,7 +32,7 @@ public abstract class AbstractResultMapper implements ResultsMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> T mapEntity(String source, Class<T> clazz) {
|
public <T> T mapEntity(String source, Class<T> clazz) {
|
||||||
if (isBlank(source)) {
|
if (StringUtils.isEmpty(source)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.Collection;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.elasticsearch.action.get.GetResponse;
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
import org.elasticsearch.action.get.MultiGetItemResponse;
|
import org.elasticsearch.action.get.MultiGetItemResponse;
|
||||||
import org.elasticsearch.action.get.MultiGetResponse;
|
import org.elasticsearch.action.get.MultiGetResponse;
|
||||||
@@ -39,6 +38,8 @@ import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPa
|
|||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonEncoding;
|
import com.fasterxml.jackson.core.JsonEncoding;
|
||||||
import com.fasterxml.jackson.core.JsonFactory;
|
import com.fasterxml.jackson.core.JsonFactory;
|
||||||
@@ -49,6 +50,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
|||||||
* @author Petar Tahchiev
|
* @author Petar Tahchiev
|
||||||
* @author Young Gu
|
* @author Young Gu
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Chris White
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
public class DefaultResultMapper extends AbstractResultMapper {
|
public class DefaultResultMapper extends AbstractResultMapper {
|
||||||
@@ -82,12 +84,13 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
|||||||
for (SearchHit hit : response.getHits()) {
|
for (SearchHit hit : response.getHits()) {
|
||||||
if (hit != null) {
|
if (hit != null) {
|
||||||
T result = null;
|
T result = null;
|
||||||
if (StringUtils.isNotBlank(hit.sourceAsString())) {
|
if (StringUtils.hasText(hit.sourceAsString())) {
|
||||||
result = mapEntity(hit.sourceAsString(), clazz);
|
result = mapEntity(hit.sourceAsString(), clazz);
|
||||||
} else {
|
} else {
|
||||||
result = mapEntity(hit.getFields().values(), clazz);
|
result = mapEntity(hit.getFields().values(), clazz);
|
||||||
}
|
}
|
||||||
setPersistentEntityId(result, hit.getId(), clazz);
|
setPersistentEntityId(result, hit.getId(), clazz);
|
||||||
|
setPersistentEntityVersion(result, hit.getVersion(), clazz);
|
||||||
populateScriptFields(result, hit);
|
populateScriptFields(result, hit);
|
||||||
results.add(result);
|
results.add(result);
|
||||||
}
|
}
|
||||||
@@ -153,6 +156,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
|||||||
T result = mapEntity(response.getSourceAsString(), clazz);
|
T result = mapEntity(response.getSourceAsString(), clazz);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
setPersistentEntityId(result, response.getId(), clazz);
|
setPersistentEntityId(result, response.getId(), clazz);
|
||||||
|
setPersistentEntityVersion(result, response.getVersion(), clazz);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -164,6 +168,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
|||||||
if (!response.isFailed() && response.getResponse().isExists()) {
|
if (!response.isFailed() && response.getResponse().isExists()) {
|
||||||
T result = mapEntity(response.getResponse().getSourceAsString(), clazz);
|
T result = mapEntity(response.getResponse().getSourceAsString(), clazz);
|
||||||
setPersistentEntityId(result, response.getResponse().getId(), clazz);
|
setPersistentEntityId(result, response.getResponse().getId(), clazz);
|
||||||
|
setPersistentEntityVersion(result, response.getResponse().getVersion(), clazz);
|
||||||
list.add(result);
|
list.add(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,4 +189,20 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> void setPersistentEntityVersion(T result, long version, Class<T> clazz) {
|
||||||
|
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
|
||||||
|
|
||||||
|
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
|
||||||
|
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||||
|
|
||||||
|
// Only deal with Long because ES versions are longs !
|
||||||
|
if (versionProperty != null && versionProperty.getType().isAssignableFrom(Long.class)) {
|
||||||
|
// check that a version was actually returned in the response, -1 would indicate that
|
||||||
|
// a search didn't request the version ids in the response, which would be an issue
|
||||||
|
Assert.isTrue(version != -1, "Version in response is -1");
|
||||||
|
persistentEntity.getPropertyAccessor(result).setProperty(versionProperty, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+100
-42
@@ -15,6 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import static org.elasticsearch.client.Requests.*;
|
||||||
|
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.*;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@@ -26,6 +32,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.elasticsearch.action.ListenableActionFuture;
|
import org.elasticsearch.action.ListenableActionFuture;
|
||||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||||
@@ -44,6 +51,7 @@ import org.elasticsearch.action.get.MultiGetResponse;
|
|||||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.elasticsearch.action.search.SearchScrollRequestBuilder;
|
||||||
import org.elasticsearch.action.update.UpdateRequestBuilder;
|
import org.elasticsearch.action.update.UpdateRequestBuilder;
|
||||||
import org.elasticsearch.action.update.UpdateResponse;
|
import org.elasticsearch.action.update.UpdateResponse;
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
@@ -59,7 +67,10 @@ import org.elasticsearch.index.query.QueryBuilders;
|
|||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||||
|
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||||
|
import org.elasticsearch.search.sort.ScoreSortBuilder;
|
||||||
import org.elasticsearch.search.sort.SortBuilder;
|
import org.elasticsearch.search.sort.SortBuilder;
|
||||||
|
import org.elasticsearch.search.sort.SortBuilders;
|
||||||
import org.elasticsearch.search.sort.SortOrder;
|
import org.elasticsearch.search.sort.SortOrder;
|
||||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -84,15 +95,24 @@ import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
|||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
import org.springframework.data.elasticsearch.core.query.*;
|
import org.springframework.data.elasticsearch.core.query.AliasQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.GetQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.IndexBoost;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.Query;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.ScriptField;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.SearchQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
|
||||||
import org.springframework.data.util.CloseableIterator;
|
import org.springframework.data.util.CloseableIterator;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import static org.apache.commons.lang.StringUtils.*;
|
import org.springframework.util.StringUtils;
|
||||||
import static org.elasticsearch.client.Requests.*;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ElasticsearchTemplate
|
* ElasticsearchTemplate
|
||||||
@@ -105,11 +125,17 @@ import static org.springframework.util.CollectionUtils.isEmpty;
|
|||||||
* @author Young Gu
|
* @author Young Gu
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Janssen
|
* @author Mark Janssen
|
||||||
|
* @author Chris White
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
|
* @author Sascha Woo
|
||||||
|
* @author Ted Liang
|
||||||
*/
|
*/
|
||||||
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
|
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ElasticsearchTemplate.class);
|
private static final Logger QUERY_LOGGER = LoggerFactory.getLogger("org.springframework.data.elasticsearch.core.QUERY");
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchTemplate.class);
|
||||||
|
private static final String FIELD_SCORE = "_score";
|
||||||
|
|
||||||
private Client client;
|
private Client client;
|
||||||
private ElasticsearchConverter elasticsearchConverter;
|
private ElasticsearchConverter elasticsearchConverter;
|
||||||
private ResultsMapper resultsMapper;
|
private ResultsMapper resultsMapper;
|
||||||
@@ -173,13 +199,13 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
public <T> boolean putMapping(Class<T> clazz) {
|
public <T> boolean putMapping(Class<T> clazz) {
|
||||||
if (clazz.isAnnotationPresent(Mapping.class)) {
|
if (clazz.isAnnotationPresent(Mapping.class)) {
|
||||||
String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath();
|
String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath();
|
||||||
if (isNotBlank(mappingPath)) {
|
if (StringUtils.hasText(mappingPath)) {
|
||||||
String mappings = readFileFromClasspath(mappingPath);
|
String mappings = readFileFromClasspath(mappingPath);
|
||||||
if (isNotBlank(mappings)) {
|
if (StringUtils.hasText(mappings)) {
|
||||||
return putMapping(clazz, mappings);
|
return putMapping(clazz, mappings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info("mappingPath in @Mapping has to be defined. Building mappings using @Field");
|
LOGGER.info("mappingPath in @Mapping has to be defined. Building mappings using @Field");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||||
@@ -310,7 +336,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
if (query.getFilter() != null) {
|
if (query.getFilter() != null) {
|
||||||
request.setPostFilter(query.getFilter());
|
request.setPostFilter(query.getFilter());
|
||||||
}
|
}
|
||||||
SearchResponse response = getSearchResponse(request.execute());
|
SearchResponse response = getSearchResponse(request);
|
||||||
return extractIds(response);
|
return extractIds(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,11 +359,8 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
|
|
||||||
if (elasticsearchFilter != null)
|
if (elasticsearchFilter != null)
|
||||||
searchRequestBuilder.setPostFilter(elasticsearchFilter);
|
searchRequestBuilder.setPostFilter(elasticsearchFilter);
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("doSearch query:\n" + searchRequestBuilder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchResponse response = getSearchResponse(searchRequestBuilder.execute());
|
SearchResponse response = getSearchResponse(searchRequestBuilder);
|
||||||
return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable());
|
return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +371,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||||
SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(wrapperQuery(query.getSource())).execute());
|
SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(wrapperQuery(query.getSource())));
|
||||||
return mapper.mapResults(response, clazz, query.getPageable());
|
return mapper.mapResults(response, clazz, query.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,9 +582,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
}
|
}
|
||||||
|
|
||||||
private UpdateRequestBuilder prepareUpdate(UpdateQuery query) {
|
private UpdateRequestBuilder prepareUpdate(UpdateQuery query) {
|
||||||
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName()
|
String indexName = StringUtils.hasText(query.getIndexName()) ? query.getIndexName()
|
||||||
: getPersistentEntityFor(query.getClazz()).getIndexName();
|
: getPersistentEntityFor(query.getClazz()).getIndexName();
|
||||||
String type = isNotBlank(query.getType()) ? query.getType()
|
String type = StringUtils.hasText(query.getType()) ? query.getType()
|
||||||
: getPersistentEntityFor(query.getClazz()).getIndexType();
|
: getPersistentEntityFor(query.getClazz()).getIndexType();
|
||||||
Assert.notNull(indexName, "No index defined for Query");
|
Assert.notNull(indexName, "No index defined for Query");
|
||||||
Assert.notNull(type, "No type define for Query");
|
Assert.notNull(type, "No type define for Query");
|
||||||
@@ -661,9 +684,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
@Override
|
@Override
|
||||||
public <T> void delete(DeleteQuery deleteQuery, Class<T> clazz) {
|
public <T> void delete(DeleteQuery deleteQuery, Class<T> clazz) {
|
||||||
|
|
||||||
String indexName = isNotBlank(deleteQuery.getIndex()) ? deleteQuery.getIndex()
|
String indexName = StringUtils.hasText(deleteQuery.getIndex()) ? deleteQuery.getIndex()
|
||||||
: getPersistentEntityFor(clazz).getIndexName();
|
: getPersistentEntityFor(clazz).getIndexName();
|
||||||
String typeName = isNotBlank(deleteQuery.getType()) ? deleteQuery.getType()
|
String typeName = StringUtils.hasText(deleteQuery.getType()) ? deleteQuery.getType()
|
||||||
: getPersistentEntityFor(clazz).getIndexType();
|
: getPersistentEntityFor(clazz).getIndexType();
|
||||||
Integer pageSize = deleteQuery.getPageSize() != null ? deleteQuery.getPageSize() : 1000;
|
Integer pageSize = deleteQuery.getPageSize() != null ? deleteQuery.getPageSize() : 1000;
|
||||||
Long scrollTimeInMillis = deleteQuery.getScrollTimeInMillis() != null ? deleteQuery.getScrollTimeInMillis()
|
Long scrollTimeInMillis = deleteQuery.getScrollTimeInMillis() != null ? deleteQuery.getScrollTimeInMillis()
|
||||||
@@ -730,7 +753,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
|
|
||||||
private SearchRequestBuilder prepareScroll(Query query, long scrollTimeInMillis) {
|
private SearchRequestBuilder prepareScroll(Query query, long scrollTimeInMillis) {
|
||||||
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
||||||
.setTypes(toArray(query.getTypes())).setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0);
|
.setTypes(toArray(query.getTypes()))
|
||||||
|
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis))
|
||||||
|
.setFrom(0)
|
||||||
|
.setVersion(true);
|
||||||
|
|
||||||
if(query.getPageable().isPaged()){
|
if(query.getPageable().isPaged()){
|
||||||
requestBuilder.setSize(query.getPageable().getPageSize());
|
requestBuilder.setSize(query.getPageable().getPageSize());
|
||||||
@@ -761,7 +787,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
requestBuilder.setPostFilter(elasticsearchFilter);
|
requestBuilder.setPostFilter(elasticsearchFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSearchResponse(requestBuilder.execute());
|
return getSearchResponse(requestBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchResponse doScroll(SearchRequestBuilder requestBuilder, SearchQuery searchQuery) {
|
private SearchResponse doScroll(SearchRequestBuilder requestBuilder, SearchQuery searchQuery) {
|
||||||
@@ -773,7 +799,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
requestBuilder.setPostFilter(searchQuery.getFilter());
|
requestBuilder.setPostFilter(searchQuery.getFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()).execute());
|
return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> Page<T> startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class<T> clazz) {
|
public <T> Page<T> startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class<T> clazz) {
|
||||||
@@ -817,8 +843,8 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
|
public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
|
||||||
|
|
||||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||||
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
|
String indexName = StringUtils.hasText(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
|
||||||
String type = isNotBlank(query.getType()) ? query.getType() : persistentEntity.getIndexType();
|
String type = StringUtils.hasText(query.getType()) ? query.getType() : persistentEntity.getIndexType();
|
||||||
|
|
||||||
Assert.notNull(indexName, "No 'indexName' defined for MoreLikeThisQuery");
|
Assert.notNull(indexName, "No 'indexName' defined for MoreLikeThisQuery");
|
||||||
Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
|
Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
|
||||||
@@ -875,9 +901,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (searchQuery.getHighlightFields() != null) {
|
if (searchQuery.getHighlightFields() != null) {
|
||||||
|
HighlightBuilder highlightBuilder = new HighlightBuilder();
|
||||||
for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) {
|
for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) {
|
||||||
searchRequest.highlighter(new HighlightBuilder().field(highlightField));
|
highlightBuilder.field(highlightField);
|
||||||
}
|
}
|
||||||
|
searchRequest.highlighter(highlightBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(searchQuery.getIndicesBoost())) {
|
if (!isEmpty(searchQuery.getIndicesBoost())) {
|
||||||
@@ -897,7 +925,16 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
searchRequest.addAggregation(aggregatedFacet.getFacet());
|
searchRequest.addAggregation(aggregatedFacet.getFacet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getSearchResponse(searchRequest.setQuery(searchQuery.getQuery()).execute());
|
return getSearchResponse(searchRequest.setQuery(searchQuery.getQuery()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SearchResponse getSearchResponse(SearchRequestBuilder requestBuilder) {
|
||||||
|
|
||||||
|
if (QUERY_LOGGER.isDebugEnabled()) {
|
||||||
|
QUERY_LOGGER.debug(requestBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return getSearchResponse(requestBuilder.execute());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchResponse getSearchResponse(ListenableActionFuture<SearchResponse> response) {
|
private SearchResponse getSearchResponse(ListenableActionFuture<SearchResponse> response) {
|
||||||
@@ -911,13 +948,13 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
private <T> boolean createIndexWithSettings(Class<T> clazz) {
|
private <T> boolean createIndexWithSettings(Class<T> clazz) {
|
||||||
if (clazz.isAnnotationPresent(Setting.class)) {
|
if (clazz.isAnnotationPresent(Setting.class)) {
|
||||||
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
|
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
|
||||||
if (isNotBlank(settingPath)) {
|
if (StringUtils.hasText(settingPath)) {
|
||||||
String settings = readFileFromClasspath(settingPath);
|
String settings = readFileFromClasspath(settingPath);
|
||||||
if (isNotBlank(settings)) {
|
if (StringUtils.hasText(settings)) {
|
||||||
return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings);
|
return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info("settingPath in @Setting has to be defined. Using default instead.");
|
LOGGER.info("settingPath in @Setting has to be defined. Using default instead.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createIndex(getPersistentEntityFor(clazz).getIndexName(), getDefaultSettings(getPersistentEntityFor(clazz)));
|
return createIndex(getPersistentEntityFor(clazz).getIndexName(), getDefaultSettings(getPersistentEntityFor(clazz)));
|
||||||
@@ -975,7 +1012,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
|
|
||||||
int startRecord = 0;
|
int startRecord = 0;
|
||||||
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
||||||
.setSearchType(query.getSearchType()).setTypes(toArray(query.getTypes()));
|
.setSearchType(query.getSearchType())
|
||||||
|
.setTypes(toArray(query.getTypes()))
|
||||||
|
.setVersion(true);
|
||||||
|
|
||||||
if (query.getSourceFilter() != null) {
|
if (query.getSourceFilter() != null) {
|
||||||
SourceFilter sourceFilter = query.getSourceFilter();
|
SourceFilter sourceFilter = query.getSourceFilter();
|
||||||
@@ -994,8 +1033,27 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
|
|
||||||
if (query.getSort() != null) {
|
if (query.getSort() != null) {
|
||||||
for (Sort.Order order : query.getSort()) {
|
for (Sort.Order order : query.getSort()) {
|
||||||
searchRequestBuilder.addSort(order.getProperty(),
|
SortOrder sortOrder = order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC;
|
||||||
order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC : SortOrder.ASC);
|
|
||||||
|
if (FIELD_SCORE.equals(order.getProperty())) {
|
||||||
|
ScoreSortBuilder sort = SortBuilders //
|
||||||
|
.scoreSort() //
|
||||||
|
.order(sortOrder);
|
||||||
|
|
||||||
|
searchRequestBuilder.addSort(sort);
|
||||||
|
} else {
|
||||||
|
FieldSortBuilder sort = SortBuilders //
|
||||||
|
.fieldSort(order.getProperty()) //
|
||||||
|
.order(sortOrder);
|
||||||
|
|
||||||
|
if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) {
|
||||||
|
sort.missing("_first");
|
||||||
|
} else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) {
|
||||||
|
sort.missing("_last");
|
||||||
|
}
|
||||||
|
|
||||||
|
searchRequestBuilder.addSort(sort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,15 +1065,15 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
|
|
||||||
private IndexRequestBuilder prepareIndex(IndexQuery query) {
|
private IndexRequestBuilder prepareIndex(IndexQuery query) {
|
||||||
try {
|
try {
|
||||||
String indexName = isBlank(query.getIndexName())
|
String indexName = StringUtils.isEmpty(query.getIndexName())
|
||||||
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0] : query.getIndexName();
|
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0] : query.getIndexName();
|
||||||
String type = isBlank(query.getType()) ? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
String type = StringUtils.isEmpty(query.getType()) ? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||||
: query.getType();
|
: query.getType();
|
||||||
|
|
||||||
IndexRequestBuilder indexRequestBuilder = null;
|
IndexRequestBuilder indexRequestBuilder = null;
|
||||||
|
|
||||||
if (query.getObject() != null) {
|
if (query.getObject() != null) {
|
||||||
String id = isBlank(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
String id = StringUtils.isEmpty(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 we have a query id and a document id, do not ask ES to generate one.
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
||||||
@@ -1065,11 +1123,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
aliasAction.filter(query.getFilterBuilder());
|
aliasAction.filter(query.getFilterBuilder());
|
||||||
} else if (query.getFilter() != null) {
|
} else if (query.getFilter() != null) {
|
||||||
aliasAction.filter(query.getFilter());
|
aliasAction.filter(query.getFilter());
|
||||||
} else if (isNotBlank(query.getRouting())) {
|
} else if (StringUtils.hasText(query.getRouting())) {
|
||||||
aliasAction.routing(query.getRouting());
|
aliasAction.routing(query.getRouting());
|
||||||
} else if (isNotBlank(query.getSearchRouting())) {
|
} else if (StringUtils.hasText(query.getSearchRouting())) {
|
||||||
aliasAction.searchRouting(query.getSearchRouting());
|
aliasAction.searchRouting(query.getSearchRouting());
|
||||||
} else if (isNotBlank(query.getIndexRouting())) {
|
} else if (StringUtils.hasText(query.getIndexRouting())) {
|
||||||
aliasAction.indexRouting(query.getIndexRouting());
|
aliasAction.indexRouting(query.getIndexRouting());
|
||||||
}
|
}
|
||||||
return client.admin().indices().prepareAliases().addAliasAction(aliasAction).execute().actionGet().isAcknowledged();
|
return client.admin().indices().prepareAliases().addAliasAction(aliasAction).execute().actionGet().isAcknowledged();
|
||||||
@@ -1189,14 +1247,14 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
|||||||
stringBuilder.append(line).append(lineSeparator);
|
stringBuilder.append(line).append(lineSeparator);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
|
LOGGER.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
if (bufferedReader != null)
|
if (bufferedReader != null)
|
||||||
try {
|
try {
|
||||||
bufferedReader.close();
|
bufferedReader.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.debug(String.format("Unable to close buffered reader.. %s", e.getMessage()));
|
LOGGER.debug(String.format("Unable to close buffered reader.. %s", e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ import org.springframework.data.elasticsearch.core.facet.result.StatisticalResul
|
|||||||
import org.springframework.data.elasticsearch.core.facet.result.Term;
|
import org.springframework.data.elasticsearch.core.facet.result.Term;
|
||||||
import org.springframework.data.elasticsearch.core.facet.result.TermResult;
|
import org.springframework.data.elasticsearch.core.facet.result.TermResult;
|
||||||
|
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container for query result and facet results
|
* Container for query result and facet results
|
||||||
*
|
*
|
||||||
@@ -48,6 +50,7 @@ import org.springframework.data.elasticsearch.core.facet.result.TermResult;
|
|||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
* @author Jonathan Yan
|
* @author Jonathan Yan
|
||||||
* @author Philipp Kräutli
|
* @author Philipp Kräutli
|
||||||
|
* @author Remco Zigterman
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T>, AggregatedPage<T> {
|
public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T>, AggregatedPage<T> {
|
||||||
@@ -60,7 +63,7 @@ public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedP
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FacetedPageImpl(List<T> content, Pageable pageable, long total) {
|
public FacetedPageImpl(List<T> content, Pageable pageable, long total) {
|
||||||
super(content, Pageable.unpaged(), total);
|
super(content, ofNullable(pageable).orElse(Pageable.unpaged()), total);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,11 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import static org.elasticsearch.common.xcontent.XContentFactory.*;
|
||||||
|
import static org.springframework.util.StringUtils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
@@ -37,9 +41,7 @@ import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
|||||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||||
import org.springframework.data.util.ClassTypeInformation;
|
import org.springframework.data.util.ClassTypeInformation;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
import static org.apache.commons.lang.StringUtils.*;
|
import org.springframework.util.StringUtils;
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.*;
|
|
||||||
import static org.springframework.util.StringUtils.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
@@ -50,6 +52,8 @@ import static org.springframework.util.StringUtils.*;
|
|||||||
* @author Dennis Maaß
|
* @author Dennis Maaß
|
||||||
* @author Pavel Luhin
|
* @author Pavel Luhin
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
|
* @author Sascha Woo
|
||||||
|
* @author Nordine Bittich
|
||||||
*/
|
*/
|
||||||
class MappingBuilder {
|
class MappingBuilder {
|
||||||
|
|
||||||
@@ -67,8 +71,7 @@ class MappingBuilder {
|
|||||||
public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
|
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 COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
|
||||||
|
|
||||||
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
|
public static final String TYPE_VALUE_KEYWORD = "keyword";
|
||||||
public static final String TYPE_VALUE_STRING = "text";
|
|
||||||
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
|
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
|
||||||
public static final String TYPE_VALUE_COMPLETION = "completion";
|
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_PREFIX = "geohash_prefix";
|
||||||
@@ -87,7 +90,7 @@ class MappingBuilder {
|
|||||||
// Properties
|
// Properties
|
||||||
XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES);
|
XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES);
|
||||||
|
|
||||||
mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY, false, FieldType.Auto, null);
|
mapEntity(xContentBuilder, clazz, true, idFieldName, "", false, FieldType.Auto, null);
|
||||||
|
|
||||||
return xContentBuilder.endObject().endObject().endObject();
|
return xContentBuilder.endObject().endObject().endObject();
|
||||||
}
|
}
|
||||||
@@ -118,7 +121,7 @@ class MappingBuilder {
|
|||||||
|
|
||||||
if (field.isAnnotationPresent(Mapping.class)) {
|
if (field.isAnnotationPresent(Mapping.class)) {
|
||||||
String mappingPath = field.getAnnotation(Mapping.class).mappingPath();
|
String mappingPath = field.getAnnotation(Mapping.class).mappingPath();
|
||||||
if (isNotBlank(mappingPath)) {
|
if (StringUtils.hasText(mappingPath)) {
|
||||||
ClassPathResource mappings = new ClassPathResource(mappingPath);
|
ClassPathResource mappings = new ClassPathResource(mappingPath);
|
||||||
if (mappings.exists()) {
|
if (mappings.exists()) {
|
||||||
xContentBuilder.rawField(field.getName(), mappings.getInputStream());
|
xContentBuilder.rawField(field.getName(), mappings.getInputStream());
|
||||||
@@ -136,7 +139,7 @@ class MappingBuilder {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boolean nestedOrObject = isNestedOrObjectField(field);
|
boolean nestedOrObject = isNestedOrObjectField(field);
|
||||||
mapEntity(xContentBuilder, getFieldType(field), false, EMPTY, field.getName(), nestedOrObject, singleField.type(), field.getAnnotation(Field.class));
|
mapEntity(xContentBuilder, getFieldType(field), false, "", field.getName(), nestedOrObject, singleField.type(), field.getAnnotation(Field.class));
|
||||||
if (nestedOrObject) {
|
if (nestedOrObject) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -202,10 +205,10 @@ class MappingBuilder {
|
|||||||
xContentBuilder.field(COMPLETION_MAX_INPUT_LENGTH, annotation.maxInputLength());
|
xContentBuilder.field(COMPLETION_MAX_INPUT_LENGTH, annotation.maxInputLength());
|
||||||
xContentBuilder.field(COMPLETION_PRESERVE_POSITION_INCREMENTS, annotation.preservePositionIncrements());
|
xContentBuilder.field(COMPLETION_PRESERVE_POSITION_INCREMENTS, annotation.preservePositionIncrements());
|
||||||
xContentBuilder.field(COMPLETION_PRESERVE_SEPARATORS, annotation.preserveSeparators());
|
xContentBuilder.field(COMPLETION_PRESERVE_SEPARATORS, annotation.preserveSeparators());
|
||||||
if (isNotBlank(annotation.searchAnalyzer())) {
|
if (StringUtils.hasText(annotation.searchAnalyzer())) {
|
||||||
xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
|
xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
|
||||||
}
|
}
|
||||||
if (isNotBlank(annotation.analyzer())) {
|
if (StringUtils.hasText(annotation.analyzer())) {
|
||||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer());
|
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,89 +218,107 @@ class MappingBuilder {
|
|||||||
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
xContentBuilder.startObject(field.getName())
|
xContentBuilder.startObject(field.getName())
|
||||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
.field(FIELD_TYPE, TYPE_VALUE_KEYWORD)
|
||||||
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED);
|
.field(FIELD_INDEX, true);
|
||||||
xContentBuilder.endObject();
|
xContentBuilder.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply mapping for a single @Field annotation
|
* Add mapping for @Field annotation
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
|
private static void addSingleFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation, boolean nestedOrObjectField) throws IOException {
|
||||||
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
|
builder.startObject(field.getName());
|
||||||
xContentBuilder.startObject(field.getName());
|
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
||||||
if(!nestedOrObjectField) {
|
builder.endObject();
|
||||||
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add mapping for @MultiField annotation
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private static void addMultiFieldMapping(
|
||||||
|
XContentBuilder builder,
|
||||||
|
java.lang.reflect.Field field,
|
||||||
|
MultiField annotation,
|
||||||
|
boolean nestedOrObjectField) throws IOException {
|
||||||
|
|
||||||
|
// main field
|
||||||
|
builder.startObject(field.getName());
|
||||||
|
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
|
||||||
|
|
||||||
|
// inner fields
|
||||||
|
builder.startObject("fields");
|
||||||
|
for (InnerField innerField : annotation.otherFields()) {
|
||||||
|
builder.startObject(innerField.suffix());
|
||||||
|
addFieldMappingParameters(builder, innerField, false);
|
||||||
|
builder.endObject();
|
||||||
}
|
}
|
||||||
if(fieldAnnotation.fielddata()) {
|
builder.endObject();
|
||||||
xContentBuilder.field(FIELD_DATA, fieldAnnotation.fielddata());
|
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addFieldMappingParameters(XContentBuilder builder, Object annotation, boolean nestedOrObjectField) throws IOException {
|
||||||
|
boolean index = true;
|
||||||
|
boolean store = false;
|
||||||
|
boolean fielddata = false;
|
||||||
|
FieldType type = null;
|
||||||
|
DateFormat dateFormat = null;
|
||||||
|
String datePattern = null;
|
||||||
|
String analyzer = null;
|
||||||
|
String searchAnalyzer = null;
|
||||||
|
|
||||||
|
if (annotation instanceof Field) {
|
||||||
|
// @Field
|
||||||
|
Field fieldAnnotation = (Field) annotation;
|
||||||
|
index = fieldAnnotation.index();
|
||||||
|
store = fieldAnnotation.store();
|
||||||
|
fielddata = fieldAnnotation.fielddata();
|
||||||
|
type = fieldAnnotation.type();
|
||||||
|
dateFormat = fieldAnnotation.format();
|
||||||
|
datePattern = fieldAnnotation.pattern();
|
||||||
|
analyzer = fieldAnnotation.analyzer();
|
||||||
|
searchAnalyzer = fieldAnnotation.searchAnalyzer();
|
||||||
|
} else if (annotation instanceof InnerField) {
|
||||||
|
// @InnerField
|
||||||
|
InnerField fieldAnnotation = (InnerField) annotation;
|
||||||
|
index = fieldAnnotation.index();
|
||||||
|
store = fieldAnnotation.store();
|
||||||
|
fielddata = fieldAnnotation.fielddata();
|
||||||
|
type = fieldAnnotation.type();
|
||||||
|
dateFormat = fieldAnnotation.format();
|
||||||
|
datePattern = fieldAnnotation.pattern();
|
||||||
|
analyzer = fieldAnnotation.analyzer();
|
||||||
|
searchAnalyzer = fieldAnnotation.searchAnalyzer();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FieldType.Auto != fieldAnnotation.type()) {
|
if (!nestedOrObjectField) {
|
||||||
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
|
builder.field(FIELD_STORE, store);
|
||||||
if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) {
|
}
|
||||||
xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format()
|
if (fielddata) {
|
||||||
? fieldAnnotation.pattern() : fieldAnnotation.format());
|
builder.field(FIELD_DATA, fielddata);
|
||||||
|
}
|
||||||
|
if (type != FieldType.Auto) {
|
||||||
|
builder.field(FIELD_TYPE, type.name().toLowerCase());
|
||||||
|
|
||||||
|
if (type == FieldType.Date && dateFormat != DateFormat.none) {
|
||||||
|
builder.field(FIELD_FORMAT, dateFormat == DateFormat.custom ? datePattern : dateFormat.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!fieldAnnotation.index()) {
|
if (!index) {
|
||||||
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index());
|
builder.field(FIELD_INDEX, index);
|
||||||
}
|
}
|
||||||
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
|
if (StringUtils.hasText(analyzer)) {
|
||||||
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
|
builder.field(FIELD_INDEX_ANALYZER, analyzer);
|
||||||
}
|
}
|
||||||
if (isNotBlank(fieldAnnotation.analyzer())) {
|
if (StringUtils.hasText(searchAnalyzer)) {
|
||||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
|
builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer);
|
||||||
}
|
}
|
||||||
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(!annotation.index()) {
|
|
||||||
builder.field(FIELD_INDEX, annotation.index());
|
|
||||||
}
|
|
||||||
if (isNotBlank(annotation.searchAnalyzer())) {
|
|
||||||
builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
|
|
||||||
}
|
|
||||||
if (isNotBlank(annotation.indexAnalyzer())) {
|
|
||||||
builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
|
|
||||||
}
|
|
||||||
if (annotation.fielddata()) {
|
|
||||||
builder.field(FIELD_DATA, annotation.fielddata());
|
|
||||||
}
|
|
||||||
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, annotation.mainField().type());
|
|
||||||
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) {
|
protected static boolean isEntity(java.lang.reflect.Field field) {
|
||||||
|
|||||||
+2
-2
@@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
package org.springframework.data.elasticsearch.core.facet.request;
|
package org.springframework.data.elasticsearch.core.facet.request;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
|
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
|
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
|
||||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +54,7 @@ public class HistogramFacetRequest extends AbstractFacetRequest {
|
|||||||
|
|
||||||
public AbstractAggregationBuilder getFacet() {
|
public AbstractAggregationBuilder getFacet() {
|
||||||
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
||||||
Assert.isTrue(StringUtils.isNotBlank(field), "Please select field on which to build the facet !!!");
|
Assert.isTrue(StringUtils.hasText(field), "Please select field on which to build the facet !!!");
|
||||||
Assert.isTrue(interval > 0, "Please provide interval as positive value greater them zero !!!");
|
Assert.isTrue(interval > 0, "Please provide interval as positive value greater them zero !!!");
|
||||||
|
|
||||||
DateHistogramAggregationBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
|
DateHistogramAggregationBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
|
||||||
|
|||||||
+3
-3
@@ -19,12 +19,12 @@ package org.springframework.data.elasticsearch.core.facet.request;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||||
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
|
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
|
||||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,7 +77,7 @@ public class RangeFacetRequest extends AbstractFacetRequest {
|
|||||||
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
||||||
|
|
||||||
RangeAggregationBuilder rangeBuilder = AggregationBuilders.range(getName());
|
RangeAggregationBuilder rangeBuilder = AggregationBuilders.range(getName());
|
||||||
final String field = StringUtils.isNotBlank(keyField) ? keyField : this.field;
|
final String field = StringUtils.hasText(keyField) ? keyField : this.field;
|
||||||
rangeBuilder.field(field);
|
rangeBuilder.field(field);
|
||||||
|
|
||||||
for (Entry entry : entries) {
|
for (Entry entry : entries) {
|
||||||
@@ -86,7 +86,7 @@ public class RangeFacetRequest extends AbstractFacetRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rangeBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS).field(field));
|
rangeBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS).field(field));
|
||||||
if(StringUtils.isNotBlank(valueField)){
|
if(StringUtils.hasText(valueField)){
|
||||||
rangeBuilder.subAggregation(AggregationBuilders.sum(RANGE_INTERNAL_SUM).field(valueField));
|
rangeBuilder.subAggregation(AggregationBuilders.sum(RANGE_INTERNAL_SUM).field(valueField));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.data.elasticsearch.core.facet.request;
|
package org.springframework.data.elasticsearch.core.facet.request;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,7 +47,7 @@ public class StatisticalFacetRequest extends AbstractFacetRequest {
|
|||||||
|
|
||||||
public AbstractAggregationBuilder getFacet() {
|
public AbstractAggregationBuilder getFacet() {
|
||||||
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
||||||
Assert.isTrue(StringUtils.isNotBlank(field) && fields == null, "Please select field or fields on which to build the facets !!!");
|
Assert.isTrue(StringUtils.hasText(field) && fields == null, "Please select field or fields on which to build the facets !!!");
|
||||||
return AggregationBuilders.extendedStats(getName()).field(field);
|
return AggregationBuilders.extendedStats(getName()).field(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-6
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.data.elasticsearch.core.facet.request;
|
package org.springframework.data.elasticsearch.core.facet.request;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.apache.lucene.util.automaton.RegExp;
|
import org.apache.lucene.util.automaton.RegExp;
|
||||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||||
@@ -26,6 +24,8 @@ import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilde
|
|||||||
import org.elasticsearch.search.aggregations.bucket.terms.support.IncludeExclude;
|
import org.elasticsearch.search.aggregations.bucket.terms.support.IncludeExclude;
|
||||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,8 +48,8 @@ public class TermFacetRequest extends AbstractFacetRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setFields(String... fields) {
|
public void setFields(String... fields) {
|
||||||
Assert.isTrue(ArrayUtils.isNotEmpty(fields), "Term agg need one field only");
|
Assert.isTrue(!ObjectUtils.isEmpty(fields), "Term agg need one field only");
|
||||||
Assert.isTrue(ArrayUtils.getLength(fields) == 1, "Term agg need one field only");
|
Assert.isTrue(fields.length == 1, "Term agg need one field only");
|
||||||
this.fields = fields;
|
this.fields = fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ public class TermFacetRequest extends AbstractFacetRequest {
|
|||||||
default:
|
default:
|
||||||
termsBuilder.order(Terms.Order.count(true));
|
termsBuilder.order(Terms.Order.count(true));
|
||||||
}
|
}
|
||||||
if (ArrayUtils.isNotEmpty(excludeTerms)) {
|
if (!ObjectUtils.isEmpty(excludeTerms)) {
|
||||||
termsBuilder.includeExclude(new IncludeExclude(null,excludeTerms));
|
termsBuilder.includeExclude(new IncludeExclude(null,excludeTerms));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ public class TermFacetRequest extends AbstractFacetRequest {
|
|||||||
termsBuilder.size(Integer.MAX_VALUE);
|
termsBuilder.size(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(regex)) {
|
if (StringUtils.hasText(regex)) {
|
||||||
termsBuilder.includeExclude(new IncludeExclude(new RegExp(regex),null));
|
termsBuilder.includeExclude(new IncludeExclude(new RegExp(regex),null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core.query;
|
package org.springframework.data.elasticsearch.core.query;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
@@ -25,6 +30,7 @@ import org.springframework.data.geo.Box;
|
|||||||
import org.springframework.data.geo.Distance;
|
import org.springframework.data.geo.Distance;
|
||||||
import org.springframework.data.geo.Point;
|
import org.springframework.data.geo.Point;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Criteria is the central class when constructing queries. It follows more or less a fluent API style, which allows to
|
* Criteria is the central class when constructing queries. It follows more or less a fluent API style, which allows to
|
||||||
@@ -42,8 +48,8 @@ public class Criteria {
|
|||||||
"field=" + field.getName() +
|
"field=" + field.getName() +
|
||||||
", boost=" + boost +
|
", boost=" + boost +
|
||||||
", negating=" + negating +
|
", negating=" + negating +
|
||||||
", queryCriteria=" + StringUtils.join(queryCriteria, '|') +
|
", queryCriteria=" + StringUtils.collectionToDelimitedString(queryCriteria, "|") +
|
||||||
", filterCriteria=" + StringUtils.join(filterCriteria, '|') +
|
", filterCriteria=" + StringUtils.collectionToDelimitedString(filterCriteria, "|") +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +443,7 @@ public class Criteria {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria within(String geoLocation, String distance) {
|
public Criteria within(String geoLocation, String distance) {
|
||||||
Assert.isTrue(StringUtils.isNotBlank(geoLocation), "geoLocation value must not be null");
|
Assert.isTrue(StringUtils.hasText(geoLocation), "geoLocation value must not be null");
|
||||||
filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{geoLocation, distance}));
|
filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{geoLocation, distance}));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -474,8 +480,8 @@ public class Criteria {
|
|||||||
* @return Criteria the chaind criteria with the new 'boundedBy' criteria included.
|
* @return Criteria the chaind criteria with the new 'boundedBy' criteria included.
|
||||||
*/
|
*/
|
||||||
public Criteria boundedBy(String topLeftGeohash, String bottomRightGeohash) {
|
public Criteria boundedBy(String topLeftGeohash, String bottomRightGeohash) {
|
||||||
Assert.isTrue(StringUtils.isNotBlank(topLeftGeohash), "topLeftGeohash must not be empty");
|
Assert.isTrue(StringUtils.hasText(topLeftGeohash), "topLeftGeohash must not be empty");
|
||||||
Assert.isTrue(StringUtils.isNotBlank(bottomRightGeohash), "bottomRightGeohash must not be empty");
|
Assert.isTrue(StringUtils.hasText(bottomRightGeohash), "bottomRightGeohash must not be empty");
|
||||||
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeftGeohash, bottomRightGeohash}));
|
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeftGeohash, bottomRightGeohash}));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -502,7 +508,7 @@ public class Criteria {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
|
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
|
||||||
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
|
if (searchString != null && searchString.contains(CRITERIA_VALUE_SEPERATOR)) {
|
||||||
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
|
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
|
||||||
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use expression or multiple clauses instead.");
|
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use expression or multiple clauses instead.");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -55,6 +55,7 @@ import org.springframework.util.Assert;
|
|||||||
* @author Kevin Leturc
|
* @author Kevin Leturc
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
|
* @author Michael Wirth
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractElasticsearchRepository<T, ID extends Serializable>
|
public abstract class AbstractElasticsearchRepository<T, ID extends Serializable>
|
||||||
implements ElasticsearchRepository<T, ID> {
|
implements ElasticsearchRepository<T, ID> {
|
||||||
@@ -188,7 +189,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean existsById(ID id) {
|
public boolean existsById(ID id) {
|
||||||
return findById(id) != null;
|
return findById(id).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,180 @@
|
|||||||
Spring Data Elasticsearch Changelog
|
Spring Data Elasticsearch Changelog
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
Changes in version 3.0.11.RELEASE (2018-10-15)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-485 - Release 3.0.11 (Kay SR11).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.1.RELEASE (2018-10-15)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-486 - Release 3.1.1 (Lovelace SR1).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.0.RELEASE (2018-09-21)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-480 - Release 3.1 GA (Lovelace).
|
||||||
|
* DATAES-479 - NativeSearchQueryBuilder should have a withHighlighter() method.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.10.RELEASE (2018-09-10)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-473 - Release 3.0.10 (Kay SR10).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.15.RELEASE (2018-09-10)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-474 - Release 2.1.15 (Ingalls SR15).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.0.RC2 (2018-08-20)
|
||||||
|
-----------------------------------------
|
||||||
|
* DATAES-472 - Release 3.1 RC2 (Lovelace).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.14.RELEASE (2018-07-27)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-463 - Release 2.1.14 (Ingalls SR14).
|
||||||
|
* DATAES-283 - Remove dependency to Commons Lang.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.9.RELEASE (2018-07-26)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-470 - TransportClientFactoryBean does not parse clusterNodes correctly.
|
||||||
|
* DATAES-469 - Is org.elasticsearch:elasticsearch a necessary dependency?.
|
||||||
|
* DATAES-467 - No mapping found for [_score] in order to sort on.
|
||||||
|
* DATAES-465 - Release 3.0.9 (Kay SR9).
|
||||||
|
* DATAES-317 - Add query logging to ElasticsearchTemplate.
|
||||||
|
* DATAES-283 - Remove dependency to Commons Lang.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.0.RC1 (2018-07-26)
|
||||||
|
-----------------------------------------
|
||||||
|
* DATAES-471 - Adapt to changes in immutable entities support.
|
||||||
|
* DATAES-470 - TransportClientFactoryBean does not parse clusterNodes correctly.
|
||||||
|
* DATAES-469 - Is org.elasticsearch:elasticsearch a necessary dependency?.
|
||||||
|
* DATAES-467 - No mapping found for [_score] in order to sort on.
|
||||||
|
* DATAES-464 - Add support for @ReadOnlyProperty to prevent properties from being written.
|
||||||
|
* DATAES-462 - Add support for mapping document scores to entities.
|
||||||
|
* DATAES-452 - Release 3.1 RC1 (Lovelace).
|
||||||
|
* DATAES-317 - Add query logging to ElasticsearchTemplate.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.8.RELEASE (2018-06-13)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-460 - Avoid pulling in Netty 3 as dependency.
|
||||||
|
* DATAES-448 - Release 3.0.8 (Kay SR8).
|
||||||
|
* DATAES-420 - Analyzer of main field ignored when using @MultiField annotation.
|
||||||
|
* DATAES-312 - NullHandling.NULLS_LAST not working in query.sort.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.13.RELEASE (2018-06-13)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-447 - Release 2.1.13 (Ingalls SR13).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.0.M3 (2018-05-17)
|
||||||
|
----------------------------------------
|
||||||
|
* DATAES-451 - Adapt to SpEL extension API changes in Spring Data Commons.
|
||||||
|
* DATAES-440 - Release 3.1 M3 (Lovelace).
|
||||||
|
* DATAES-422 - Add support for IndicesOptions in search queries.
|
||||||
|
* DATAES-420 - Analyzer of main field ignored when using @MultiField annotation.
|
||||||
|
* DATAES-412 - Highlighted fields is not getting passed to the elastic search query.
|
||||||
|
* DATAES-363 - AbstractElasticsearchRepository.existsById(..) always returns true.
|
||||||
|
* DATAES-312 - NullHandling.NULLS_LAST not working in query.sort.
|
||||||
|
* DATAES-198 - @Version has no effect, so therefore is not useful with spring data elasticsearch.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.7.RELEASE (2018-05-08)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-438 - Expected a boolean [true/false] for property [index] but got [not_analyzed].
|
||||||
|
* DATAES-437 - Release 3.0.7 (Kay SR7).
|
||||||
|
* DATAES-412 - Highlighted fields is not getting passed to the elastic search query.
|
||||||
|
* DATAES-402 - Paging not working correctly.
|
||||||
|
* DATAES-363 - AbstractElasticsearchRepository.existsById(..) always returns true.
|
||||||
|
* DATAES-198 - @Version has no effect, so therefore is not useful with spring data elasticsearch.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.12.RELEASE (2018-05-08)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-436 - Release 2.1.12 (Ingalls SR12).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.0.M2 (2018-04-13)
|
||||||
|
----------------------------------------
|
||||||
|
* DATAES-439 - Adapt to API changes in Spring Data Commons.
|
||||||
|
* DATAES-434 - Remove explicit declaration of Jackson library versions.
|
||||||
|
* DATAES-432 - Export composable repositories via CDI.
|
||||||
|
* DATAES-427 - Release 3.1 M2 (Lovelace).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.6.RELEASE (2018-04-04)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-434 - Remove explicit declaration of Jackson library versions.
|
||||||
|
* DATAES-430 - Release 3.0.6 (Kay SR6).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.11.RELEASE (2018-04-04)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-434 - Remove explicit declaration of Jackson library versions.
|
||||||
|
* DATAES-424 - Fix line endings.
|
||||||
|
* DATAES-423 - Release 2.1.11 (Ingalls SR11).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.5.RELEASE (2018-02-28)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-429 - Release 3.0.5 (Kay SR5).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.4.RELEASE (2018-02-19)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-425 - Release 3.0.4 (Kay SR4).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.1.0.M1 (2018-02-06)
|
||||||
|
----------------------------------------
|
||||||
|
* DATAES-424 - Fix line endings.
|
||||||
|
* DATAES-414 - Reduce scope of Lo4j dependencies to test.
|
||||||
|
* DATAES-410 - Adapt API changes in Property in test cases.
|
||||||
|
* DATAES-401 - Release 3.1 M1 (Lovelace).
|
||||||
|
* DATAES-361 - log4j2.xml in classpath root of the library prevents Spring Boot's logging auto-configuration to work.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.3.RELEASE (2018-01-24)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-424 - Fix line endings.
|
||||||
|
* DATAES-417 - Release 3.0.3 (Kay SR3).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.10.RELEASE (2018-01-24)
|
||||||
|
----------------------------------------------
|
||||||
|
* DATAES-416 - Release 2.1.10 (Ingalls SR10).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.2.RELEASE (2017-11-27)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-414 - Reduce scope of Lo4j dependencies to test.
|
||||||
|
* DATAES-411 - Release 3.0.2 (Kay SR2).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.9.RELEASE (2017-11-27)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-408 - Ensure Spring 5 compatibility in Ingalls.
|
||||||
|
* DATAES-404 - Release 2.1.9 (Ingalls SR9).
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 3.0.1.RELEASE (2017-10-27)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-410 - Adapt API changes in Property in test cases.
|
||||||
|
* DATAES-400 - Release 3.0.1 (Kay SR1).
|
||||||
|
* DATAES-361 - log4j2.xml in classpath root of the library prevents Spring Boot's logging auto-configuration to work.
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 2.1.8.RELEASE (2017-10-11)
|
||||||
|
---------------------------------------------
|
||||||
|
* DATAES-391 - Release 2.1.8 (Ingalls SR8).
|
||||||
|
|
||||||
|
|
||||||
Changes in version 3.0.0.RELEASE (2017-10-02)
|
Changes in version 3.0.0.RELEASE (2017-10-02)
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
* DATAES-397 - Add explicit automatic module name for Java 9.
|
* DATAES-397 - Add explicit automatic module name for Java 9.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Spring Data Elasticsearch 3.0 GA
|
Spring Data Elasticsearch 3.0.11
|
||||||
Copyright (c) [2013-2016] Pivotal Software, Inc.
|
Copyright (c) [2013-2016] Pivotal Software, Inc.
|
||||||
|
|
||||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||||
|
|||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.elasticsearch.client;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link ClusterNodes}.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class ClusterNodesUnitTests {
|
||||||
|
|
||||||
|
@Test // DATAES-470
|
||||||
|
public void parsesSingleClusterNode() {
|
||||||
|
|
||||||
|
ClusterNodes nodes = ClusterNodes.DEFAULT;
|
||||||
|
|
||||||
|
assertThat(nodes).hasSize(1) //
|
||||||
|
.first().satisfies(it -> {
|
||||||
|
assertThat(it.getAddress()).isEqualTo("127.0.0.1");
|
||||||
|
assertThat(it.getPort()).isEqualTo(9300);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-470
|
||||||
|
public void parsesMultiClusterNode() {
|
||||||
|
|
||||||
|
ClusterNodes nodes = ClusterNodes.of("127.0.0.1:1234,10.1.0.1:5678");
|
||||||
|
|
||||||
|
assertThat(nodes.stream()).hasSize(2); //
|
||||||
|
assertThat(nodes.stream()).element(0).satisfies(it -> {
|
||||||
|
assertThat(it.getAddress()).isEqualTo("127.0.0.1");
|
||||||
|
assertThat(it.getPort()).isEqualTo(1234);
|
||||||
|
});
|
||||||
|
assertThat(nodes.stream()).element(1).satisfies(it -> {
|
||||||
|
assertThat(it.getAddress()).isEqualTo("10.1.0.1");
|
||||||
|
assertThat(it.getPort()).isEqualTo(5678);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-470
|
||||||
|
public void rejectsEmptyHostName() {
|
||||||
|
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class) //
|
||||||
|
.isThrownBy(() -> ClusterNodes.of(":8080")) //
|
||||||
|
.withMessageContaining("host");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-470
|
||||||
|
public void rejectsEmptyPort() {
|
||||||
|
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class) //
|
||||||
|
.isThrownBy(() -> ClusterNodes.of("localhost:")) //
|
||||||
|
.withMessageContaining("port");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-470
|
||||||
|
public void rejectsMissingPort() {
|
||||||
|
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class) //
|
||||||
|
.isThrownBy(() -> ClusterNodes.of("localhost")) //
|
||||||
|
.withMessageContaining("host:port");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-470
|
||||||
|
public void rejectsUnresolvableHost() {
|
||||||
|
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class) //
|
||||||
|
.isThrownBy(() -> ClusterNodes.of("mylocalhost:80"));
|
||||||
|
}
|
||||||
|
}
|
||||||
+68
-2
@@ -16,14 +16,15 @@
|
|||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.fasterxml.jackson.databind.util.ArrayIterator;
|
import com.fasterxml.jackson.databind.util.ArrayIterator;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.elasticsearch.action.get.GetResponse;
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
|
import org.elasticsearch.action.get.MultiGetItemResponse;
|
||||||
|
import org.elasticsearch.action.get.MultiGetResponse;
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.SearchHitField;
|
import org.elasticsearch.search.SearchHitField;
|
||||||
@@ -41,6 +42,7 @@ import org.springframework.data.elasticsearch.annotations.Document;
|
|||||||
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
import org.springframework.data.elasticsearch.entities.Car;
|
import org.springframework.data.elasticsearch.entities.Car;
|
||||||
|
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
@@ -50,6 +52,7 @@ import static org.mockito.Mockito.*;
|
|||||||
/**
|
/**
|
||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Chris White
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
public class DefaultResultMapperTests {
|
public class DefaultResultMapperTests {
|
||||||
@@ -153,6 +156,69 @@ public class DefaultResultMapperTests {
|
|||||||
assertThat(result.getId(), is("identifier"));
|
assertThat(result.getId(), is("identifier"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-198
|
||||||
|
public void setsVersionFromGetResponse() {
|
||||||
|
GetResponse response = mock(GetResponse.class);
|
||||||
|
when(response.getSourceAsString()).thenReturn("{}");
|
||||||
|
when(response.getVersion()).thenReturn(1234L);
|
||||||
|
|
||||||
|
SampleEntity result = resultMapper.mapResult(response, SampleEntity.class);
|
||||||
|
|
||||||
|
assertThat(result, is(notNullValue()));
|
||||||
|
assertThat(result.getVersion(), is(1234L));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-198
|
||||||
|
public void setsVersionFromMultiGetResponse() {
|
||||||
|
GetResponse response1 = mock(GetResponse.class);
|
||||||
|
when(response1.getSourceAsString()).thenReturn("{}");
|
||||||
|
when(response1.isExists()).thenReturn(true);
|
||||||
|
when(response1.getVersion()).thenReturn(1234L);
|
||||||
|
|
||||||
|
GetResponse response2 = mock(GetResponse.class);
|
||||||
|
when(response2.getSourceAsString()).thenReturn("{}");
|
||||||
|
when(response2.isExists()).thenReturn(true);
|
||||||
|
when(response2.getVersion()).thenReturn(5678L);
|
||||||
|
|
||||||
|
MultiGetResponse multiResponse = mock(MultiGetResponse.class);
|
||||||
|
when(multiResponse.getResponses()).thenReturn(new MultiGetItemResponse[] {
|
||||||
|
new MultiGetItemResponse(response1, null), new MultiGetItemResponse(response2, null) });
|
||||||
|
|
||||||
|
LinkedList<SampleEntity> results = resultMapper.mapResults(multiResponse, SampleEntity.class);
|
||||||
|
|
||||||
|
assertThat(results, is(notNullValue()));
|
||||||
|
assertThat(results, hasSize(2));
|
||||||
|
|
||||||
|
assertThat(results.get(0).getVersion(), is(1234L));
|
||||||
|
assertThat(results.get(1).getVersion(), is(5678L));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-198
|
||||||
|
public void setsVersionFromSearchResponse() {
|
||||||
|
SearchHit hit1 = mock(SearchHit.class);
|
||||||
|
when(hit1.getSourceAsString()).thenReturn("{}");
|
||||||
|
when(hit1.getVersion()).thenReturn(1234L);
|
||||||
|
|
||||||
|
SearchHit hit2 = mock(SearchHit.class);
|
||||||
|
when(hit2.getSourceAsString()).thenReturn("{}");
|
||||||
|
when(hit2.getVersion()).thenReturn(5678L);
|
||||||
|
|
||||||
|
SearchHits searchHits = mock(SearchHits.class);
|
||||||
|
when(searchHits.getTotalHits()).thenReturn(2L);
|
||||||
|
when(searchHits.iterator()).thenReturn(Arrays.asList(hit1, hit2).iterator());
|
||||||
|
|
||||||
|
SearchResponse searchResponse = mock(SearchResponse.class);
|
||||||
|
when(searchResponse.getHits()).thenReturn(searchHits);
|
||||||
|
|
||||||
|
AggregatedPage<SampleEntity> results = resultMapper.mapResults(searchResponse, SampleEntity.class,
|
||||||
|
mock(Pageable.class));
|
||||||
|
|
||||||
|
assertThat(results, is(notNullValue()));
|
||||||
|
|
||||||
|
assertThat(results.getContent().get(0).getVersion(), is(1234L));
|
||||||
|
assertThat(results.getContent().get(1).getVersion(), is(5678L));
|
||||||
|
}
|
||||||
|
|
||||||
private Aggregation createCarAggregation() {
|
private Aggregation createCarAggregation() {
|
||||||
Aggregation aggregation = mock(Terms.class);
|
Aggregation aggregation = mock(Terms.class);
|
||||||
when(aggregation.getName()).thenReturn("Diesel");
|
when(aggregation.getName()).thenReturn("Diesel");
|
||||||
|
|||||||
+184
-2
@@ -33,6 +33,7 @@ import org.elasticsearch.script.Script;
|
|||||||
import org.elasticsearch.script.ScriptType;
|
import org.elasticsearch.script.ScriptType;
|
||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||||
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
|
||||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||||
import org.elasticsearch.search.sort.SortOrder;
|
import org.elasticsearch.search.sort.SortOrder;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
@@ -70,6 +71,8 @@ import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
|
|||||||
* @author Abdul Mohammed
|
* @author Abdul Mohammed
|
||||||
* @author Kevin Leturc
|
* @author Kevin Leturc
|
||||||
* @author Mason Chan
|
* @author Mason Chan
|
||||||
|
* @author Chris White
|
||||||
|
* @author Sascha Woo
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||||
@@ -461,6 +464,129 @@ public class ElasticsearchTemplateTests {
|
|||||||
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
|
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-312
|
||||||
|
public void shouldSortResultsGivenNullFirstSortCriteria() {
|
||||||
|
// given
|
||||||
|
List<IndexQuery> indexQueries;
|
||||||
|
|
||||||
|
// first document
|
||||||
|
String documentId = randomNumeric(5);
|
||||||
|
SampleEntity sampleEntity1 = SampleEntity.builder()
|
||||||
|
.id(documentId)
|
||||||
|
.message("abc")
|
||||||
|
.rate(15)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// second document
|
||||||
|
String documentId2 = randomNumeric(5);
|
||||||
|
SampleEntity sampleEntity2 = SampleEntity.builder()
|
||||||
|
.id(documentId2)
|
||||||
|
.message("xyz")
|
||||||
|
.rate(5)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// third document
|
||||||
|
String documentId3 = randomNumeric(5);
|
||||||
|
SampleEntity sampleEntity3 = SampleEntity.builder()
|
||||||
|
.id(documentId3)
|
||||||
|
.rate(10)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
|
||||||
|
|
||||||
|
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||||
|
elasticsearchTemplate.refresh(SampleEntity.class);
|
||||||
|
|
||||||
|
SearchQuery searchQuery = new NativeSearchQueryBuilder()
|
||||||
|
.withQuery(matchAllQuery())
|
||||||
|
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsFirst())))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
|
||||||
|
assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity3.getRate()));
|
||||||
|
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-312
|
||||||
|
public void shouldSortResultsGivenNullLastSortCriteria() {
|
||||||
|
// given
|
||||||
|
List<IndexQuery> indexQueries;
|
||||||
|
|
||||||
|
// first document
|
||||||
|
String documentId = randomNumeric(5);
|
||||||
|
SampleEntity sampleEntity1 = SampleEntity.builder()
|
||||||
|
.id(documentId)
|
||||||
|
.message("abc")
|
||||||
|
.rate(15)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// second document
|
||||||
|
String documentId2 = randomNumeric(5);
|
||||||
|
SampleEntity sampleEntity2 = SampleEntity.builder()
|
||||||
|
.id(documentId2)
|
||||||
|
.message("xyz")
|
||||||
|
.rate(5)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// third document
|
||||||
|
String documentId3 = randomNumeric(5);
|
||||||
|
SampleEntity sampleEntity3 = SampleEntity.builder()
|
||||||
|
.id(documentId3)
|
||||||
|
.rate(10)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
|
||||||
|
|
||||||
|
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||||
|
elasticsearchTemplate.refresh(SampleEntity.class);
|
||||||
|
|
||||||
|
SearchQuery searchQuery = new NativeSearchQueryBuilder()
|
||||||
|
.withQuery(matchAllQuery())
|
||||||
|
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsLast())))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
|
||||||
|
assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity1.getRate()));
|
||||||
|
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity2.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-467
|
||||||
|
public void shouldSortResultsByScore() {
|
||||||
|
// given
|
||||||
|
List<SampleEntity> entities = Arrays.asList( //
|
||||||
|
SampleEntity.builder().id("1").message("abc").build(), //
|
||||||
|
SampleEntity.builder().id("2").message("def").build(), //
|
||||||
|
SampleEntity.builder().id("3").message("ghi").build());
|
||||||
|
|
||||||
|
elasticsearchTemplate.bulkIndex(getIndexQueries(entities));
|
||||||
|
elasticsearchTemplate.refresh(SampleEntity.class);
|
||||||
|
|
||||||
|
SearchQuery searchQuery = new NativeSearchQueryBuilder()
|
||||||
|
.withQuery(matchAllQuery())
|
||||||
|
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("_score"))))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldExecuteStringQuery() {
|
public void shouldExecuteStringQuery() {
|
||||||
// given
|
// given
|
||||||
@@ -1206,6 +1332,58 @@ public class ElasticsearchTemplateTests {
|
|||||||
assertThat(sampleEntities.getContent().get(0).getHighlightedMessage(), is(highlightedMessage));
|
assertThat(sampleEntities.getContent().get(0).getHighlightedMessage(), is(highlightedMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-412
|
||||||
|
public void shouldReturnMultipleHighlightFields() {
|
||||||
|
|
||||||
|
// given
|
||||||
|
String documentId = randomNumeric(5);
|
||||||
|
String actualType = "some test type";
|
||||||
|
String actualMessage = "some test message";
|
||||||
|
String highlightedType = "some <em>test</em> type";
|
||||||
|
String highlightedMessage = "some <em>test</em> message";
|
||||||
|
|
||||||
|
SampleEntity sampleEntity = SampleEntity.builder()
|
||||||
|
.id(documentId)
|
||||||
|
.type(actualType)
|
||||||
|
.message(actualMessage)
|
||||||
|
.version(System.currentTimeMillis())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||||
|
|
||||||
|
elasticsearchTemplate.index(indexQuery);
|
||||||
|
elasticsearchTemplate.refresh(SampleEntity.class);
|
||||||
|
|
||||||
|
SearchQuery searchQuery = new NativeSearchQueryBuilder()
|
||||||
|
.withQuery(
|
||||||
|
boolQuery()
|
||||||
|
.must(termQuery("type", "test"))
|
||||||
|
.must(termQuery("message", "test")))
|
||||||
|
.withHighlightFields(
|
||||||
|
new HighlightBuilder.Field("type"),
|
||||||
|
new HighlightBuilder.Field("message"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapper() {
|
||||||
|
@Override
|
||||||
|
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||||
|
for (SearchHit searchHit : response.getHits()) {
|
||||||
|
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
|
||||||
|
HighlightField highlightFieldType = highlightFields.get("type");
|
||||||
|
HighlightField highlightFieldMessage = highlightFields.get("message");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertNotNull(highlightFieldType);
|
||||||
|
assertNotNull(highlightFieldMessage);
|
||||||
|
assertThat(highlightFieldType.fragments()[0].toString(), is(highlightedType));
|
||||||
|
assertThat(highlightFieldMessage.fragments()[0].toString(), is(highlightedMessage));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldDeleteDocumentBySpecifiedTypeUsingDeleteQuery() {
|
public void shouldDeleteDocumentBySpecifiedTypeUsingDeleteQuery() {
|
||||||
// given
|
// given
|
||||||
@@ -1987,13 +2165,17 @@ public class ElasticsearchTemplateTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IndexQuery getIndexQuery(SampleEntity sampleEntity) {
|
private IndexQuery getIndexQuery(SampleEntity sampleEntity) {
|
||||||
return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build();
|
return new IndexQueryBuilder()
|
||||||
|
.withId(sampleEntity.getId())
|
||||||
|
.withObject(sampleEntity)
|
||||||
|
.withVersion(sampleEntity.getVersion())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IndexQuery> getIndexQueries(List<SampleEntity> sampleEntities) {
|
private List<IndexQuery> getIndexQueries(List<SampleEntity> sampleEntities) {
|
||||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||||
for (SampleEntity sampleEntity : sampleEntities) {
|
for (SampleEntity sampleEntity : sampleEntities) {
|
||||||
indexQueries.add(new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build());
|
indexQueries.add(getIndexQuery(sampleEntity));
|
||||||
}
|
}
|
||||||
return indexQueries;
|
return indexQueries;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.io.IOException;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -43,6 +44,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||||||
* @author Jakub Vavrik
|
* @author Jakub Vavrik
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
* @author Keivn Leturc
|
* @author Keivn Leturc
|
||||||
|
* @author Nordine Bittich
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||||
@@ -189,8 +191,28 @@ public class MappingBuilderTests {
|
|||||||
elasticsearchTemplate.createIndex(Book.class);
|
elasticsearchTemplate.createIndex(Book.class);
|
||||||
elasticsearchTemplate.putMapping(Book.class);
|
elasticsearchTemplate.putMapping(Book.class);
|
||||||
//when
|
//when
|
||||||
|
|
||||||
//then
|
//then
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-420
|
||||||
|
public void shouldUseBothAnalyzer() {
|
||||||
|
//given
|
||||||
|
elasticsearchTemplate.deleteIndex(Book.class);
|
||||||
|
elasticsearchTemplate.createIndex(Book.class);
|
||||||
|
elasticsearchTemplate.putMapping(Book.class);
|
||||||
|
|
||||||
|
//when
|
||||||
|
Map mapping = elasticsearchTemplate.getMapping(Book.class);
|
||||||
|
Map descriptionMapping = (Map) ((Map) mapping.get("properties")).get("description");
|
||||||
|
Map prefixDescription = (Map) ((Map) descriptionMapping.get("fields")).get("prefix");
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat(prefixDescription.size(), is(3));
|
||||||
|
assertThat(prefixDescription.get("type"), equalTo("text"));
|
||||||
|
assertThat(prefixDescription.get("analyzer"), equalTo("stop"));
|
||||||
|
assertThat(prefixDescription.get("search_analyzer"), equalTo("standard"));
|
||||||
|
assertThat(descriptionMapping.get("type"), equalTo("text"));
|
||||||
|
assertThat(descriptionMapping.get("analyzer"), equalTo("whitespace"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.aggregation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Remco Zigterman
|
||||||
|
*/
|
||||||
|
public class AggregatedPageImplTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructFacetedPageWithPageable() {
|
||||||
|
Page<String> page = new AggregatedPageImpl<>(Arrays.asList("Test", "Test 2"), PageRequest.of(0, 2), 10);
|
||||||
|
|
||||||
|
assertEquals(10, page.getTotalElements());
|
||||||
|
assertEquals(2, page.getNumberOfElements());
|
||||||
|
assertEquals(2, page.getSize());
|
||||||
|
assertEquals(5, page.getTotalPages());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
package org.springframework.data.elasticsearch.core.facet;
|
package org.springframework.data.elasticsearch.core.facet;
|
||||||
|
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.Integer;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.Integer;
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.text;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,14 +36,14 @@ public class ArticleEntity {
|
|||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
private String title;
|
private String title;
|
||||||
@Field(type = text, fielddata = true)
|
@Field(type = Text, fielddata = true)
|
||||||
private String subject;
|
private String subject;
|
||||||
|
|
||||||
@MultiField(
|
@MultiField(
|
||||||
mainField = @Field(type = text),
|
mainField = @Field(type = Text),
|
||||||
otherFields = {
|
otherFields = {
|
||||||
@InnerField(suffix = "untouched", type = text, store = true, fielddata = true, indexAnalyzer = "keyword"),
|
@InnerField(suffix = "untouched", type = Text, store = true, fielddata = true, analyzer = "keyword"),
|
||||||
@InnerField(suffix = "sort", type = text, store = true, indexAnalyzer = "keyword")
|
@InnerField(suffix = "sort", type = Text, store = true, analyzer = "keyword")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
private List<String> authors = new ArrayList<>();
|
private List<String> authors = new ArrayList<>();
|
||||||
|
|||||||
+2
-1
@@ -66,7 +66,8 @@ public class SimpleElasticsearchPersistentEntityTests {
|
|||||||
private static SimpleElasticsearchPersistentProperty createProperty(SimpleElasticsearchPersistentEntity<?> entity,
|
private static SimpleElasticsearchPersistentProperty createProperty(SimpleElasticsearchPersistentEntity<?> entity,
|
||||||
String field) {
|
String field) {
|
||||||
|
|
||||||
Property property = Property.of(ReflectionUtils.findField(entity.getTypeInformation().getType(), field));
|
TypeInformation<?> type = entity.getTypeInformation();
|
||||||
|
Property property = Property.of(type, ReflectionUtils.findField(entity.getType(), field));
|
||||||
return new SimpleElasticsearchPersistentProperty(property, entity, SimpleTypeHolder.DEFAULT);
|
return new SimpleElasticsearchPersistentProperty(property, entity, SimpleTypeHolder.DEFAULT);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,13 @@ import org.springframework.data.annotation.Id;
|
|||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.annotations.Field;
|
import org.springframework.data.elasticsearch.annotations.Field;
|
||||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||||
|
import org.springframework.data.elasticsearch.annotations.InnerField;
|
||||||
|
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Nordine Bittich
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@@ -49,4 +52,11 @@ public class Book {
|
|||||||
private Author author;
|
private Author author;
|
||||||
@Field(type = FieldType.Nested)
|
@Field(type = FieldType.Nested)
|
||||||
private Map<Integer, Collection<String>> buckets = new HashMap<>();
|
private Map<Integer, Collection<String>> buckets = new HashMap<>();
|
||||||
|
@MultiField(
|
||||||
|
mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
|
||||||
|
otherFields = {
|
||||||
|
@InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
private String description;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.springframework.core.style.ToStringCreator;
|
|||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.annotations.Field;
|
import org.springframework.data.elasticsearch.annotations.Field;
|
||||||
import org.springframework.data.elasticsearch.annotations.FieldIndex;
|
|
||||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||||
import org.springframework.data.elasticsearch.annotations.Parent;
|
import org.springframework.data.elasticsearch.annotations.Parent;
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ public class ParentEntity {
|
|||||||
|
|
||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
@Field(type = FieldType.text, store = true)
|
@Field(type = FieldType.Text, store = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
public ParentEntity() {
|
public ParentEntity() {
|
||||||
@@ -67,10 +66,10 @@ public class ParentEntity {
|
|||||||
|
|
||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
@Field(type = FieldType.text, store = true)
|
@Field(type = FieldType.Text, store = true)
|
||||||
@Parent(type = PARENT_TYPE)
|
@Parent(type = PARENT_TYPE)
|
||||||
private String parentId;
|
private String parentId;
|
||||||
@Field(type = FieldType.text, store = true)
|
@Field(type = FieldType.Text, store = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
public ChildEntity() {
|
public ChildEntity() {
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package org.springframework.data.elasticsearch.entities;
|
package org.springframework.data.elasticsearch.entities;
|
||||||
|
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.text;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ public class SampleDateMappingEntity {
|
|||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Field(type = text, index = false, store = true, analyzer = "standard")
|
@Field(type = Text, index = false, store = true, analyzer = "standard")
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
@Field(type = Date, format = DateFormat.custom, pattern = "dd.MM.yyyy hh:mm")
|
@Field(type = Date, format = DateFormat.custom, pattern = "dd.MM.yyyy hh:mm")
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import lombok.Builder;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.annotation.Version;
|
import org.springframework.data.annotation.Version;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
@@ -34,21 +35,23 @@ import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
|||||||
/**
|
/**
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Chris White
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@ToString
|
||||||
@Builder
|
@Builder
|
||||||
@Document(indexName = "test-index-sample", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1")
|
@Document(indexName = "test-index-sample", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1")
|
||||||
public class SampleEntity {
|
public class SampleEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
@Field(type = text, store = true, fielddata = true)
|
@Field(type = Text, store = true, fielddata = true)
|
||||||
private String type;
|
private String type;
|
||||||
@Field(type = text, store = true, fielddata = true)
|
@Field(type = Text, store = true, fielddata = true)
|
||||||
private String message;
|
private String message;
|
||||||
private int rate;
|
private int rate;
|
||||||
@ScriptedField
|
@ScriptedField
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ public class SampleEntityUUIDKeyed {
|
|||||||
@Id
|
@Id
|
||||||
private UUID id;
|
private UUID id;
|
||||||
private String type;
|
private String type;
|
||||||
@Field(type = FieldType.text, fielddata = true)
|
@Field(type = FieldType.Text, fielddata = true)
|
||||||
private String message;
|
private String message;
|
||||||
private int rate;
|
private int rate;
|
||||||
@ScriptedField
|
@ScriptedField
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.entities;
|
package org.springframework.data.elasticsearch.entities;
|
||||||
|
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.text;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
|
||||||
|
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.annotations.Field;
|
import org.springframework.data.elasticsearch.annotations.Field;
|
||||||
@@ -26,7 +26,7 @@ import org.springframework.data.elasticsearch.annotations.Field;
|
|||||||
@Document(indexName = "test-index-sample-inherited", type = "mapping", shards = 1, replicas = 0, refreshInterval = "-1")
|
@Document(indexName = "test-index-sample-inherited", type = "mapping", shards = 1, replicas = 0, refreshInterval = "-1")
|
||||||
public class SampleInheritedEntity extends AbstractInheritedEntity {
|
public class SampleInheritedEntity extends AbstractInheritedEntity {
|
||||||
|
|
||||||
@Field(type = text, index = false, store = true, analyzer = "standard")
|
@Field(type = Text, index = false, store = true, analyzer = "standard")
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
|
|||||||
+3
-3
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.entities;
|
package org.springframework.data.elasticsearch.entities;
|
||||||
|
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.text;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
|
||||||
|
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
@@ -31,7 +31,7 @@ public class SampleMappingEntity {
|
|||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Field(type = text, index = false, store = true, analyzer = "standard")
|
@Field(type = Text, index = false, store = true, analyzer = "standard")
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
private NestedEntity nested;
|
private NestedEntity nested;
|
||||||
@@ -54,7 +54,7 @@ public class SampleMappingEntity {
|
|||||||
|
|
||||||
static class NestedEntity {
|
static class NestedEntity {
|
||||||
|
|
||||||
@Field(type = text)
|
@Field(type = Text)
|
||||||
private String someField;
|
private String someField;
|
||||||
|
|
||||||
public String getSomeField() {
|
public String getSomeField() {
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.entities;
|
package org.springframework.data.elasticsearch.entities;
|
||||||
|
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.text;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
|
||||||
|
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.annotation.Transient;
|
import org.springframework.data.annotation.Transient;
|
||||||
@@ -31,7 +31,7 @@ public class SampleTransientEntity {
|
|||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Field(type = text, index = false, store = true, analyzer = "standard")
|
@Field(type = Text, index = false, store = true, analyzer = "standard")
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
|
|||||||
+14
@@ -47,6 +47,7 @@ import static org.springframework.data.domain.Sort.Direction.*;
|
|||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
|
* @author Michael Wirth
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration("classpath:/simple-repository-test.xml")
|
@ContextConfiguration("classpath:/simple-repository-test.xml")
|
||||||
@@ -274,6 +275,19 @@ public class SimpleElasticsearchRepositoryTests {
|
|||||||
assertEquals(exist, true);
|
assertEquals(exist, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-363
|
||||||
|
public void shouldReturnFalseGivenDocumentWithIdDoesNotExist() {
|
||||||
|
|
||||||
|
// given
|
||||||
|
String documentId = randomNumeric(5);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean exist = repository.existsById(documentId);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(exist, is(false));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnResultsForGivenSearchQuery() {
|
public void shouldReturnResultsForGivenSearchQuery() {
|
||||||
// given
|
// given
|
||||||
|
|||||||
+14
@@ -45,6 +45,7 @@ import static org.junit.Assert.*;
|
|||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
|
* @author Michael Wirth
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration("classpath:/simple-repository-test.xml")
|
@ContextConfiguration("classpath:/simple-repository-test.xml")
|
||||||
@@ -262,6 +263,19 @@ public class UUIDElasticsearchRepositoryTests {
|
|||||||
assertEquals(exist, true);
|
assertEquals(exist, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-363
|
||||||
|
public void shouldReturnFalseGivenDocumentWithIdDoesNotExist() {
|
||||||
|
|
||||||
|
// given
|
||||||
|
UUID documentId = UUID.randomUUID();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean exist = repository.existsById(documentId);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(exist, is(false));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldDeleteAll() {
|
public void shouldDeleteAll() {
|
||||||
// when
|
// when
|
||||||
|
|||||||
Reference in New Issue
Block a user