Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -52,17 +52,12 @@ the appropriate dependency version.
|
||||
</repository>
|
||||
```
|
||||
|
||||
| spring data elasticsearch | elasticsearch |
|
||||
|:-----------------------------------:|:-------------:|
|
||||
| 3.0.0.RC2 | 5.5.0 |
|
||||
| 3.0.0.M4 | 5.4.0 |
|
||||
| 2.0.4.RELEASE | 2.4.0 |
|
||||
| 2.0.0.RELEASE | 2.2.0 |
|
||||
| 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 |
|
||||
| spring data elasticsearch | elasticsearch |
|
||||
|:-------------------------:|:-------------:|
|
||||
| 3.0.x | 5.5.0 |
|
||||
| 2.1.x | 2.4.0 |
|
||||
| 2.0.x | 2.2.0 |
|
||||
| 1.3.x | 1.5.2 |
|
||||
|
||||
|
||||
### ElasticsearchRepository
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>3.0.6.RELEASE</version>
|
||||
<version>3.0.8.RELEASE</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.0.6.RELEASE</version>
|
||||
<version>2.0.8.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -21,7 +21,7 @@
|
||||
<commonslang>2.6</commonslang>
|
||||
<elasticsearch>5.5.0</elasticsearch>
|
||||
<log4j>2.8.2</log4j>
|
||||
<springdata.commons>2.0.6.RELEASE</springdata.commons>
|
||||
<springdata.commons>2.0.8.RELEASE</springdata.commons>
|
||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||
</properties>
|
||||
|
||||
@@ -81,9 +81,19 @@
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.elasticsearch.plugin</groupId>
|
||||
<artifactId>transport-netty3-client</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch.plugin</groupId>
|
||||
<artifactId>transport-netty4-client</artifactId>
|
||||
<version>${elasticsearch}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
@@ -162,14 +172,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- required by elasticsearch -->
|
||||
<groupId>org.elasticsearch.plugin</groupId>
|
||||
<artifactId>transport-netty4-client</artifactId>
|
||||
<version>${elasticsearch}</version>
|
||||
<!--<scope>test</scope>-->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
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;
|
||||
|
||||
DateFormat format() default DateFormat.none;
|
||||
|
||||
String pattern() default "";
|
||||
|
||||
boolean store() default false;
|
||||
|
||||
boolean fielddata() default false;
|
||||
|
||||
String searchAnalyzer() default "";
|
||||
|
||||
String indexAnalyzer() default "";
|
||||
String analyzer() default "";
|
||||
}
|
||||
|
||||
+112
-1
@@ -17,12 +17,29 @@ 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.concurrent.TimeUnit;
|
||||
|
||||
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.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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,6 +47,7 @@ import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* TransportClientFactoryBean
|
||||
@@ -88,7 +106,7 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
||||
|
||||
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)) {
|
||||
String hostName = substringBeforeLast(clusterNode, COLON);
|
||||
@@ -153,4 +171,97 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
||||
public void setProperties(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPa
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
@@ -49,6 +50,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||
* @author Petar Tahchiev
|
||||
* @author Young Gu
|
||||
* @author Oliver Gierke
|
||||
* @author Chris White
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DefaultResultMapper extends AbstractResultMapper {
|
||||
@@ -88,6 +90,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
result = mapEntity(hit.getFields().values(), clazz);
|
||||
}
|
||||
setPersistentEntityId(result, hit.getId(), clazz);
|
||||
setPersistentEntityVersion(result, hit.getVersion(), clazz);
|
||||
populateScriptFields(result, hit);
|
||||
results.add(result);
|
||||
}
|
||||
@@ -153,6 +156,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
T result = mapEntity(response.getSourceAsString(), clazz);
|
||||
if (result != null) {
|
||||
setPersistentEntityId(result, response.getId(), clazz);
|
||||
setPersistentEntityVersion(result, response.getVersion(), clazz);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -164,6 +168,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
if (!response.isFailed() && response.getResponse().isExists()) {
|
||||
T result = mapEntity(response.getResponse().getSourceAsString(), clazz);
|
||||
setPersistentEntityId(result, response.getResponse().getId(), clazz);
|
||||
setPersistentEntityVersion(result, response.getResponse().getVersion(), clazz);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-5
@@ -59,7 +59,9 @@ import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilders;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.slf4j.Logger;
|
||||
@@ -105,7 +107,10 @@ import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
* @author Young Gu
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Janssen
|
||||
* @author Chris White
|
||||
* @author Mark Paluch
|
||||
* @author Sascha Woo
|
||||
* @author Ted Liang
|
||||
*/
|
||||
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
|
||||
|
||||
@@ -730,7 +735,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
private SearchRequestBuilder prepareScroll(Query query, long scrollTimeInMillis) {
|
||||
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()){
|
||||
requestBuilder.setSize(query.getPageable().getPageSize());
|
||||
@@ -875,9 +883,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
if (searchQuery.getHighlightFields() != null) {
|
||||
HighlightBuilder highlightBuilder = new HighlightBuilder();
|
||||
for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) {
|
||||
searchRequest.highlighter(new HighlightBuilder().field(highlightField));
|
||||
highlightBuilder.field(highlightField);
|
||||
}
|
||||
searchRequest.highlighter(highlightBuilder);
|
||||
}
|
||||
|
||||
if (!isEmpty(searchQuery.getIndicesBoost())) {
|
||||
@@ -975,7 +985,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
int startRecord = 0;
|
||||
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) {
|
||||
SourceFilter sourceFilter = query.getSourceFilter();
|
||||
@@ -994,8 +1006,15 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
if (query.getSort() != null) {
|
||||
for (Sort.Order order : query.getSort()) {
|
||||
searchRequestBuilder.addSort(order.getProperty(),
|
||||
order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC : SortOrder.ASC);
|
||||
FieldSortBuilder sort = SortBuilders.fieldSort(order.getProperty())
|
||||
.order(order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC);
|
||||
if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) {
|
||||
sort.missing("_first");
|
||||
}
|
||||
else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) {
|
||||
sort.missing("_last");
|
||||
}
|
||||
searchRequestBuilder.addSort(sort);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.TermResult;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* Container for query result and facet results
|
||||
*
|
||||
@@ -48,6 +50,7 @@ import org.springframework.data.elasticsearch.core.facet.result.TermResult;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
* @author Philipp Kräutli
|
||||
* @author Remco Zigterman
|
||||
*/
|
||||
@Deprecated
|
||||
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) {
|
||||
super(content, Pageable.unpaged(), total);
|
||||
super(content, ofNullable(pageable).orElse(Pageable.unpaged()), total);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -50,6 +50,8 @@ import static org.springframework.util.StringUtils.*;
|
||||
* @author Dennis Maaß
|
||||
* @author Pavel Luhin
|
||||
* @author Mark Paluch
|
||||
* @author Sascha Woo
|
||||
* @author Nordine Bittich
|
||||
*/
|
||||
class MappingBuilder {
|
||||
|
||||
@@ -67,8 +69,7 @@ class MappingBuilder {
|
||||
public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
|
||||
public static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
|
||||
|
||||
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
|
||||
public static final String TYPE_VALUE_STRING = "text";
|
||||
public static final String TYPE_VALUE_KEYWORD = "keyword";
|
||||
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
|
||||
public static final String TYPE_VALUE_COMPLETION = "completion";
|
||||
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix";
|
||||
@@ -215,89 +216,107 @@ class MappingBuilder {
|
||||
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
||||
throws IOException {
|
||||
xContentBuilder.startObject(field.getName())
|
||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
||||
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED);
|
||||
.field(FIELD_TYPE, TYPE_VALUE_KEYWORD)
|
||||
.field(FIELD_INDEX, true);
|
||||
xContentBuilder.endObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply mapping for a single @Field annotation
|
||||
* Add mapping for @Field annotation
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
|
||||
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
|
||||
xContentBuilder.startObject(field.getName());
|
||||
if(!nestedOrObjectField) {
|
||||
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
|
||||
private static void addSingleFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation, boolean nestedOrObjectField) throws IOException {
|
||||
builder.startObject(field.getName());
|
||||
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()) {
|
||||
xContentBuilder.field(FIELD_DATA, fieldAnnotation.fielddata());
|
||||
builder.endObject();
|
||||
|
||||
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()) {
|
||||
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
|
||||
if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) {
|
||||
xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format()
|
||||
? fieldAnnotation.pattern() : fieldAnnotation.format());
|
||||
if (!nestedOrObjectField) {
|
||||
builder.field(FIELD_STORE, store);
|
||||
}
|
||||
if (fielddata) {
|
||||
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()) {
|
||||
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index());
|
||||
if (!index) {
|
||||
builder.field(FIELD_INDEX, index);
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
|
||||
if (isNotBlank(analyzer)) {
|
||||
builder.field(FIELD_INDEX_ANALYZER, analyzer);
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.analyzer())) {
|
||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
|
||||
if (isNotBlank(searchAnalyzer)) {
|
||||
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) {
|
||||
|
||||
+2
-1
@@ -55,6 +55,7 @@ import org.springframework.util.Assert;
|
||||
* @author Kevin Leturc
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Michael Wirth
|
||||
*/
|
||||
public abstract class AbstractElasticsearchRepository<T, ID extends Serializable>
|
||||
implements ElasticsearchRepository<T, ID> {
|
||||
@@ -188,7 +189,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
|
||||
@Override
|
||||
public boolean existsById(ID id) {
|
||||
return findById(id) != null;
|
||||
return findById(id).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,54 @@
|
||||
Spring Data Elasticsearch Changelog
|
||||
===================================
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data Elasticsearch 3.0.6
|
||||
Spring Data Elasticsearch 3.0.8
|
||||
Copyright (c) [2013-2016] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
|
||||
+68
-2
@@ -16,14 +16,15 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import com.fasterxml.jackson.databind.util.ArrayIterator;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
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.search.SearchHit;
|
||||
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.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.entities.Car;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
@@ -50,6 +52,7 @@ import static org.mockito.Mockito.*;
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Mohsin Husen
|
||||
* @author Chris White
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DefaultResultMapperTests {
|
||||
@@ -153,6 +156,69 @@ public class DefaultResultMapperTests {
|
||||
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() {
|
||||
Aggregation aggregation = mock(Terms.class);
|
||||
when(aggregation.getName()).thenReturn("Diesel");
|
||||
|
||||
+162
-3
@@ -33,6 +33,7 @@ import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
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.SortOrder;
|
||||
import org.hamcrest.Matchers;
|
||||
@@ -70,6 +71,8 @@ import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
|
||||
* @author Abdul Mohammed
|
||||
* @author Kevin Leturc
|
||||
* @author Mason Chan
|
||||
* @author Chris White
|
||||
* @author Sascha Woo
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||
@@ -461,6 +464,106 @@ public class ElasticsearchTemplateTests {
|
||||
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
|
||||
public void shouldExecuteStringQuery() {
|
||||
// given
|
||||
@@ -1206,6 +1309,58 @@ public class ElasticsearchTemplateTests {
|
||||
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
|
||||
public void shouldDeleteDocumentBySpecifiedTypeUsingDeleteQuery() {
|
||||
// given
|
||||
@@ -1987,13 +2142,17 @@ public class ElasticsearchTemplateTests {
|
||||
}
|
||||
|
||||
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) {
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
for (SampleEntity sampleEntity : sampleEntities) {
|
||||
indexQueries.add(new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build());
|
||||
indexQueries.add(getIndexQuery(sampleEntity));
|
||||
}
|
||||
return indexQueries;
|
||||
}
|
||||
@@ -2011,4 +2170,4 @@ public class ElasticsearchTemplateTests {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.junit.Test;
|
||||
@@ -43,6 +44,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Jakub Vavrik
|
||||
* @author Mohsin Husen
|
||||
* @author Keivn Leturc
|
||||
* @author Nordine Bittich
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||
@@ -189,8 +191,28 @@ public class MappingBuilderTests {
|
||||
elasticsearchTemplate.createIndex(Book.class);
|
||||
elasticsearchTemplate.putMapping(Book.class);
|
||||
//when
|
||||
|
||||
//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;
|
||||
|
||||
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.List;
|
||||
@@ -36,14 +36,14 @@ public class ArticleEntity {
|
||||
@Id
|
||||
private String id;
|
||||
private String title;
|
||||
@Field(type = text, fielddata = true)
|
||||
@Field(type = Text, fielddata = true)
|
||||
private String subject;
|
||||
|
||||
@MultiField(
|
||||
mainField = @Field(type = text),
|
||||
mainField = @Field(type = Text),
|
||||
otherFields = {
|
||||
@InnerField(suffix = "untouched", type = text, store = true, fielddata = true, indexAnalyzer = "keyword"),
|
||||
@InnerField(suffix = "sort", type = text, store = true, indexAnalyzer = "keyword")
|
||||
@InnerField(suffix = "untouched", type = Text, store = true, fielddata = true, analyzer = "keyword"),
|
||||
@InnerField(suffix = "sort", type = Text, store = true, analyzer = "keyword")
|
||||
}
|
||||
)
|
||||
private List<String> authors = new ArrayList<>();
|
||||
|
||||
@@ -29,10 +29,13 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.InnerField;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Nordine Bittich
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@@ -49,4 +52,11 @@ public class Book {
|
||||
private Author author;
|
||||
@Field(type = FieldType.Nested)
|
||||
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.elasticsearch.annotations.Document;
|
||||
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.Parent;
|
||||
|
||||
@@ -38,7 +37,7 @@ public class ParentEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
@Field(type = FieldType.text, store = true)
|
||||
@Field(type = FieldType.Text, store = true)
|
||||
private String name;
|
||||
|
||||
public ParentEntity() {
|
||||
@@ -67,10 +66,10 @@ public class ParentEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
@Field(type = FieldType.text, store = true)
|
||||
@Field(type = FieldType.Text, store = true)
|
||||
@Parent(type = PARENT_TYPE)
|
||||
private String parentId;
|
||||
@Field(type = FieldType.text, store = true)
|
||||
@Field(type = FieldType.Text, store = true)
|
||||
private String name;
|
||||
|
||||
public ChildEntity() {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package org.springframework.data.elasticsearch.entities;
|
||||
|
||||
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;
|
||||
|
||||
@@ -19,7 +19,7 @@ public class SampleDateMappingEntity {
|
||||
@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;
|
||||
|
||||
@Field(type = Date, format = DateFormat.custom, pattern = "dd.MM.yyyy hh:mm")
|
||||
|
||||
@@ -23,6 +23,7 @@ import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
@@ -34,21 +35,23 @@ import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Chris White
|
||||
*/
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
@Builder
|
||||
@Document(indexName = "test-index-sample", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1")
|
||||
public class SampleEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
@Field(type = text, store = true, fielddata = true)
|
||||
@Field(type = Text, store = true, fielddata = true)
|
||||
private String type;
|
||||
@Field(type = text, store = true, fielddata = true)
|
||||
@Field(type = Text, store = true, fielddata = true)
|
||||
private String message;
|
||||
private int rate;
|
||||
@ScriptedField
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class SampleEntityUUIDKeyed {
|
||||
@Id
|
||||
private UUID id;
|
||||
private String type;
|
||||
@Field(type = FieldType.text, fielddata = true)
|
||||
@Field(type = FieldType.Text, fielddata = true)
|
||||
private String message;
|
||||
private int rate;
|
||||
@ScriptedField
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
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.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")
|
||||
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;
|
||||
|
||||
public String getMessage() {
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
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.elasticsearch.annotations.Document;
|
||||
@@ -31,7 +31,7 @@ public class SampleMappingEntity {
|
||||
@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 NestedEntity nested;
|
||||
@@ -54,7 +54,7 @@ public class SampleMappingEntity {
|
||||
|
||||
static class NestedEntity {
|
||||
|
||||
@Field(type = text)
|
||||
@Field(type = Text)
|
||||
private String someField;
|
||||
|
||||
public String getSomeField() {
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
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.Transient;
|
||||
@@ -31,7 +31,7 @@ public class SampleTransientEntity {
|
||||
@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;
|
||||
|
||||
@Transient
|
||||
|
||||
+14
@@ -47,6 +47,7 @@ import static org.springframework.data.domain.Sort.Direction.*;
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Michael Wirth
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:/simple-repository-test.xml")
|
||||
@@ -274,6 +275,19 @@ public class SimpleElasticsearchRepositoryTests {
|
||||
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
|
||||
public void shouldReturnResultsForGivenSearchQuery() {
|
||||
// given
|
||||
|
||||
+14
@@ -45,6 +45,7 @@ import static org.junit.Assert.*;
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Michael Wirth
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:/simple-repository-test.xml")
|
||||
@@ -262,6 +263,19 @@ public class UUIDElasticsearchRepositoryTests {
|
||||
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
|
||||
public void shouldDeleteAll() {
|
||||
// when
|
||||
|
||||
Reference in New Issue
Block a user