Compare commits

...

20 Commits
main ... 4.3.2

Author SHA1 Message Date
Mark Paluch
187c9bbd5d
Release version 4.3.2 (2021.1.2).
See #2056
2022-02-18 10:41:01 +01:00
Mark Paluch
e1a5811406
Prepare 4.3.2 (2021.1.2).
See #2056
2022-02-18 10:40:40 +01:00
Greg L. Turnquist
b643669d36 Update CI properties.
See #2056
2022-02-14 14:39:49 -06:00
Peter-Josef Meisch
f66af53480
Fix exception on property conversion with criteria exists/empty/non-empty.
Original Pull Request #2081
Closes #2080

(cherry picked from commit 32fa7391c42a64710dc073bb38cbf4611d9ac5aa)
2022-02-09 23:25:34 +01:00
Mark Paluch
14099970bb
Polishing.
Extract Docker and Artifactory credentials into properties file.

See #2074
2022-02-04 15:18:50 +01:00
Greg L. Turnquist
0ab253422f
Externalize build properties.
See #2074.
2022-02-04 15:18:48 +01:00
Christoph Strobl
0d2a6b98e8
After release cleanups.
See #1987
2022-01-14 10:45:02 +01:00
Christoph Strobl
30602496bd
Prepare next development iteration.
See #1987
2022-01-14 10:44:59 +01:00
Christoph Strobl
95762b4fde
Release version 4.3.1 (2021.1.1).
See #1987
2022-01-14 10:28:59 +01:00
Christoph Strobl
0771e90031
Prepare 4.3.1 (2021.1.1).
See #1987
2022-01-14 10:28:27 +01:00
Peter-Josef Meisch
6729330500
Update to log4j 2.17.0 2021-12-18 20:34:28 +01:00
Peter-Josef Meisch
8796292611
update log4j dependency version 2021-12-14 13:53:59 +01:00
Peter-Josef Meisch
f3f9ca4002
Fix FieldType mapping.
Original PullRequest #2026
Closes #2024

(cherry picked from commit f7a6a97c4e2fcde86fa182f599e548a75ce73865)
2021-12-13 21:52:28 +01:00
Peter-Josef Meisch
083a38ed57
Fix IndexOutOfBoundsException when try to map inner hits with no results returned.
Original Pull Request #1998
Closes #1997
Co-authored-by: Peter-Josef Meisch <pj.meisch@sothawo.com>

(cherry picked from commit 49324a369af627e390f981ed6b793f0f503526c7)
2021-12-05 09:02:06 +01:00
Sascha Woo
4f3aa52958
Fix IndexOutOfBoundsException when try to map inner hits with no results returned.
Original Pull Request #1998
Closes #1997
Co-authored-by: Peter-Josef Meisch <pj.meisch@sothawo.com>

(cherry picked from commit 49324a369af627e390f981ed6b793f0f503526c7)
2021-11-23 20:26:14 +01:00
Peter-Josef Meisch
3256a2bfe0
Fix RestStatusException cause.
Original Pull Request #1996
Closes #1995

(cherry picked from commit 45b4c99e951e4519c3fe1e2d4a51c8bd16ab33b0)
2021-11-16 07:38:01 +01:00
Peter-Josef Meisch
95401a5bd7
Exclude commons-logging dependency from Elasticsearch dependencies.
Original Pull Request #1993
Closes #1989
2021-11-13 14:56:57 +01:00
Mark Paluch
12cd64cfc8
Update build trigger to use branch build.
See #1965
2021-11-12 14:31:54 +01:00
Jens Schauder
7e557317d1
After release cleanups.
See #1965
2021-11-12 11:00:07 +01:00
Jens Schauder
c9846ab8ad
Prepare next development iteration.
See #1965
2021-11-12 11:00:05 +01:00
23 changed files with 672 additions and 232 deletions

50
Jenkinsfile vendored
View File

@ -1,9 +1,15 @@
def p = [:]
node {
checkout scm
p = readProperties interpolate: true, file: 'ci/pipeline.properties'
}
pipeline {
agent none
triggers {
pollSCM 'H/10 * * * *'
upstream(upstreamProjects: "spring-data-commons/main", threshold: hudson.model.Result.SUCCESS)
upstream(upstreamProjects: "spring-data-commons/2.6.x", threshold: hudson.model.Result.SUCCESS)
}
options {
@ -12,7 +18,7 @@ pipeline {
}
stages {
stage("test: baseline (jdk8)") {
stage("test: baseline (main)") {
when {
anyOf {
branch 'main'
@ -25,14 +31,14 @@ pipeline {
options { timeout(time: 30, unit: 'MINUTES') }
environment {
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
DOCKER_HUB = credentials("${p['docker.credentials']}")
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
}
steps {
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk8:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.docker']) {
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
sh 'PROFILE=none ci/verify.sh'
sh "ci/clean.sh"
@ -50,21 +56,21 @@ pipeline {
}
}
parallel {
stage("test: baseline (jdk11)") {
stage("test: baseline (next)") {
agent {
label 'data'
}
options { timeout(time: 30, unit: 'MINUTES') }
environment {
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
DOCKER_HUB = credentials("${p['docker.credentials']}")
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
}
steps {
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk11:latest').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
docker.image(p['docker.java.next.image']).inside(p['docker.java.inside.docker']) {
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
sh 'PROFILE=java11 ci/verify.sh'
sh "ci/clean.sh"
@ -74,21 +80,21 @@ pipeline {
}
}
stage("test: baseline (jdk17)") {
stage("test: baseline (LTS)") {
agent {
label 'data'
}
options { timeout(time: 30, unit: 'MINUTES') }
environment {
DOCKER_HUB = credentials('hub.docker.com-springbuildmaster')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
DOCKER_HUB = credentials("${p['docker.credentials']}")
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
}
steps {
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('openjdk:17-bullseye').inside('-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home') {
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
docker.image(p['docker.java.lts.image']).inside(p['docker.java.inside.docker']) {
sh "docker login --username ${DOCKER_HUB_USR} --password ${DOCKER_HUB_PSW}"
sh 'PROFILE=java11 ci/verify.sh'
sh "ci/clean.sh"
@ -113,13 +119,13 @@ pipeline {
options { timeout(time: 20, unit: 'MINUTES') }
environment {
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
}
steps {
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,artifactory -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
'-Dartifactory.server=https://repo.spring.io ' +
"-Dartifactory.username=${ARTIFACTORY_USR} " +
@ -143,13 +149,13 @@ pipeline {
options { timeout(time: 20, unit: 'MINUTES') }
environment {
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
ARTIFACTORY = credentials("${p['artifactory.credentials']}")
}
steps {
script {
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') {
docker.withRegistry(p['docker.registry'], p['docker.credentials']) {
docker.image(p['docker.java.main.image']).inside(p['docker.java.inside.basic']) {
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,distribute -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-elasticsearch-non-root ' +
'-Dartifactory.server=https://repo.spring.io ' +
"-Dartifactory.username=${ARTIFACTORY_USR} " +

29
ci/pipeline.properties Normal file
View File

@ -0,0 +1,29 @@
# Java versions
java.main.tag=8u312-b07-jdk
java.next.tag=11.0.13_8-jdk
java.lts.tag=17.0.1_12-jdk
# Docker container images - standard
docker.java.main.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.main.tag}
docker.java.next.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.next.tag}
docker.java.lts.image=harbor-repo.vmware.com/dockerhub-proxy-cache/library/eclipse-temurin:${java.lts.tag}
# Supported versions of MongoDB
docker.mongodb.4.0.version=4.0.23
docker.mongodb.4.4.version=4.4.4
docker.mongodb.5.0.version=5.0.3
# Supported versions of Redis
docker.redis.6.version=6.2.4
# Supported versions of Cassandra
docker.cassandra.3.version=3.11.10
# Docker environment settings
docker.java.inside.basic=-v $HOME:/tmp/jenkins-home
docker.java.inside.docker=-u root -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v $HOME:/tmp/jenkins-home
# Credentials
docker.registry=
docker.credentials=hub.docker.com-springbuildmaster
artifactory.credentials=02bd1690-b54f-4c9f-819d-a77cb7a9822c

24
pom.xml
View File

@ -5,12 +5,12 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.3.0</version>
<version>4.3.2</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.6.0</version>
<version>2.6.2</version>
</parent>
<name>Spring Data Elasticsearch</name>
@ -19,9 +19,9 @@
<properties>
<elasticsearch>7.15.2</elasticsearch>
<log4j>2.14.1</log4j>
<log4j>2.17.0</log4j>
<netty>4.1.65.Final</netty>
<springdata.commons>2.6.0</springdata.commons>
<springdata.commons>2.6.2</springdata.commons>
<testcontainers>1.15.3</testcontainers>
<blockhound-junit>1.0.6.RELEASE</blockhound-junit>
<java-module-name>spring.data.elasticsearch</java-module-name>
@ -145,6 +145,12 @@
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -152,6 +158,12 @@
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -461,7 +473,9 @@
</module>
</checkstyleRules>
<includes>**/*</includes>
<excludes>.git/**/*,target/**/*,**/target/**/*,.idea/**/*,**/spring.schemas,**/*.svg,mvnw,mvnw.cmd,**/*.policy</excludes>
<excludes>
.git/**/*,target/**/*,**/target/**/*,.idea/**/*,**/spring.schemas,**/*.svg,mvnw,mvnw.cmd,**/*.policy
</excludes>
<sourceDirectories>./</sourceDirectories>
</configuration>
</plugin>

View File

@ -46,6 +46,16 @@ public @interface CompletionContext {
* @since 4.3
*/
enum ContextMappingType {
CATEGORY, GEO
CATEGORY("category"), GEO("geo");
private final String mappedName;
ContextMappingType(String mappedName) {
this.mappedName = mappedName;
}
public String getMappedName() {
return mappedName;
}
}
}

View File

@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.annotations;
/**
* Values for the {@code dynamic} mapping parameter.
*
*
* @author Sascha Woo
* @since 4.3
*/
@ -25,26 +25,36 @@ public enum Dynamic {
/**
* New fields are added to the mapping.
*/
TRUE,
TRUE("true"),
/**
* New fields are added to the mapping as
* <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime.html">runtime fields</a>. These
* fields are not indexed, and are loaded from {@code _source} at query time.
*/
RUNTIME,
RUNTIME("runtime"),
/**
* New fields are ignored. These fields will not be indexed or searchable, but will still appear in the
* {@code _source} field of returned hits. These fields will not be added to the mapping, and new fields must be added
* explicitly.
*/
FALSE,
FALSE("false"),
/**
* If new fields are detected, an exception is thrown and the document is rejected. New fields must be explicitly
* added to the mapping.
*/
STRICT,
STRICT("strict"),
/**
* Inherit the dynamic setting from their parent object or from the mapping type.
*/
INHERIT
INHERIT("nherit");
private final String mappedName;
Dynamic(String mappedName) {
this.mappedName = mappedName;
}
public String getMappedName() {
return mappedName;
}
}

View File

@ -17,13 +17,23 @@ package org.springframework.data.elasticsearch.annotations;
/**
* values for the {@link DynamicMapping annotation}
*
*
* @author Peter-Josef Meisch
* @author Sascha Woo
* @since 4.0
* @deprecated since 4.3, use {@link Document#dynamic()} or {@link Field#dynamic()} instead.
* @deprecated since 4.3, use {@link Document#dynamic()} or {@link Field#dynamic()} instead.
*/
@Deprecated
public enum DynamicMappingValue {
True, False, Strict
True("true"), False("false"), Strict("strict");
private final String mappedName;
DynamicMappingValue(String mappedName) {
this.mappedName = mappedName;
}
public String getMappedName() {
return mappedName;
}
}

View File

@ -26,40 +26,51 @@ package org.springframework.data.elasticsearch.annotations;
* @author Morgan Lutz
*/
public enum FieldType {
Auto, //
Text, //
Keyword, //
Long, //
Integer, //
Short, //
Byte, //
Double, //
Float, //
Half_Float, //
Scaled_Float, //
Date, //
Date_Nanos, //
Boolean, //
Binary, //
Integer_Range, //
Float_Range, //
Long_Range, //
Double_Range, //
Date_Range, //
Ip_Range, //
Object, //
Nested, //
Ip, //
TokenCount, //
Percolator, //
Flattened, //
Search_As_You_Type, //
Auto("auto"), //
Text("text"), //
Keyword("keyword"), //
Long("long"), //
Integer("integer"), //
Short("short"), //
Byte("byte"), //
Double("double"), //
Float("float"), //
Half_Float("half_float"), //
Scaled_Float("scaled_float"), //
Date("date"), //
Date_Nanos("date_nanos"), //
Boolean("boolean"), //
Binary("binary"), //
Integer_Range("integer_range"), //
Float_Range("float_range"), //
Long_Range("long_range"), //
Double_Range("double_range"), //
Date_Range("date_range"), //
Ip_Range("ip_range"), //
Object("object"), //
Nested("nested"), //
Ip("ip"), //
TokenCount("token_count"), //
Percolator("percolator"), //
Flattened("flattened"), //
Search_As_You_Type("search_as_you_type"), //
/** @since 4.1 */
Rank_Feature, //
Rank_Feature("rank_feature"), //
/** @since 4.1 */
Rank_Features, //
Rank_Features("rank_features"), //
/** since 4.2 */
Wildcard, //
Wildcard("wildcard"), //
/** @since 4.2 */
Dense_Vector //
Dense_Vector("dense_vector") //
;
private final String mappedName;
FieldType(String mappedName) {
this.mappedName = mappedName;
}
public String getMappedName() {
return mappedName;
}
}

View File

@ -64,9 +64,9 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
}
if (elasticsearchException instanceof ElasticsearchStatusException) {
ElasticsearchStatusException restStatusException = (ElasticsearchStatusException) elasticsearchException;
return new RestStatusException(restStatusException.status().getStatus(), restStatusException.getMessage(),
restStatusException.getCause());
ElasticsearchStatusException elasticsearchStatusException = (ElasticsearchStatusException) elasticsearchException;
return new RestStatusException(elasticsearchStatusException.status().getStatus(),
elasticsearchStatusException.getMessage(), elasticsearchStatusException);
}
return new UncategorizedElasticsearchException(ex.getMessage(), ex);

View File

@ -24,6 +24,7 @@ import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
@ -45,6 +46,7 @@ import org.springframework.util.Assert;
* @author Mark Paluch
* @author Roman Puchkovskiy
* @author Matt Gilene
* @author Sascha Woo
* @since 4.0
*/
class SearchHitMapping<T> {
@ -194,7 +196,7 @@ class SearchHitMapping<T> {
*/
private SearchHits<?> mapInnerDocuments(SearchHits<SearchDocument> searchHits, Class<T> type) {
if (searchHits.getTotalHits() == 0) {
if (searchHits.isEmpty()) {
return searchHits;
}
@ -239,7 +241,7 @@ class SearchHitMapping<T> {
searchHits.getSuggest());
}
} catch (Exception e) {
LOGGER.warn("Could not map inner_hits", e);
throw new UncategorizedElasticsearchException("Unable to convert inner hits.", e);
}
return searchHits;

View File

@ -76,7 +76,10 @@ public abstract class AbstractRangePropertyValueConverter<T> extends AbstractPro
public Object write(Object value) {
Assert.notNull(value, "value must not be null.");
Assert.isInstanceOf(Range.class, value, "value must be instance of Range.");
if (!Range.class.isAssignableFrom(value.getClass())) {
return value.toString();
}
try {
Range<T> range = (Range<T>) value;

View File

@ -58,6 +58,10 @@ public class DatePropertyValueConverter extends AbstractPropertyValueConverter {
@Override
public Object write(Object value) {
if (!Date.class.isAssignableFrom(value.getClass())) {
return value.toString();
}
try {
return dateConverters.get(0).format((Date) value);
} catch (Exception e) {

View File

@ -1256,14 +1256,19 @@ public class MappingElasticsearchConverter
PropertyValueConverter propertyValueConverter = Objects
.requireNonNull(persistentProperty.getPropertyValueConverter());
criteria.getQueryCriteriaEntries().forEach(criteriaEntry -> {
Object value = criteriaEntry.getValue();
if (value.getClass().isArray()) {
Object[] objects = (Object[]) value;
for (int i = 0; i < objects.length; i++) {
objects[i] = propertyValueConverter.write(objects[i]);
if (criteriaEntry.getKey().hasValue()) {
Object value = criteriaEntry.getValue();
if (value.getClass().isArray()) {
Object[] objects = (Object[]) value;
for (int i = 0; i < objects.length; i++) {
objects[i] = propertyValueConverter.write(objects[i]);
}
} else {
criteriaEntry.setValue(propertyValueConverter.write(value));
}
} else {
criteriaEntry.setValue(propertyValueConverter.write(value));
}
});
}

View File

@ -61,6 +61,10 @@ public class TemporalPropertyValueConverter extends AbstractPropertyValueConvert
@Override
public Object write(Object value) {
if (!TemporalAccessor.class.isAssignableFrom(value.getClass())) {
return value.toString();
}
try {
return dateConverters.get(0).format((TemporalAccessor) value);
} catch (Exception e) {

View File

@ -230,8 +230,7 @@ public class MappingBuilder {
boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField);
if (writeNestedProperties) {
String type = nestedOrObjectField ? fieldType.toString().toLowerCase()
: FieldType.Object.toString().toLowerCase();
String type = nestedOrObjectField ? fieldType.getMappedName() : FieldType.Object.getMappedName();
ObjectNode nestedObjectNode = objectMapper.createObjectNode();
nestedObjectNode.put(FIELD_PARAM_TYPE, type);
@ -247,9 +246,9 @@ public class MappingBuilder {
}
if (entity != null && entity.dynamic() != Dynamic.INHERIT) {
objectNode.put(TYPE_DYNAMIC, entity.dynamic().name().toLowerCase());
objectNode.put(TYPE_DYNAMIC, entity.dynamic().getMappedName());
} else if (dynamicMapping != null) {
objectNode.put(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
objectNode.put(TYPE_DYNAMIC, dynamicMapping.value().getMappedName());
}
ObjectNode propertiesNode = objectNode.putObject(FIELD_PROPERTIES);
@ -418,7 +417,7 @@ public class MappingBuilder {
ObjectNode contextNode = contextsNode.addObject();
contextNode.put(FIELD_CONTEXT_NAME, context.name());
contextNode.put(FIELD_CONTEXT_TYPE, context.type().name().toLowerCase());
contextNode.put(FIELD_CONTEXT_TYPE, context.type().getMappedName());
if (context.precision().length() > 0) {
contextNode.put(FIELD_CONTEXT_PRECISION, context.precision());
@ -450,7 +449,7 @@ public class MappingBuilder {
}
propertiesNode.set(property.getFieldName(), objectMapper.createObjectNode() //
.put(FIELD_PARAM_TYPE, field.type().name().toLowerCase()) //
.put(FIELD_PARAM_TYPE, field.type().getMappedName()) //
.put(MAPPING_ENABLED, false) //
);
@ -479,9 +478,9 @@ public class MappingBuilder {
if (nestedOrObjectField) {
if (annotation.dynamic() != Dynamic.INHERIT) {
fieldNode.put(TYPE_DYNAMIC, annotation.dynamic().name().toLowerCase());
fieldNode.put(TYPE_DYNAMIC, annotation.dynamic().getMappedName());
} else if (dynamicMapping != null) {
fieldNode.put(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
fieldNode.put(TYPE_DYNAMIC, dynamicMapping.value().getMappedName());
}
}
}
@ -530,9 +529,9 @@ public class MappingBuilder {
if (nestedOrObjectField) {
if (annotation.mainField().dynamic() != Dynamic.INHERIT) {
mainFieldNode.put(TYPE_DYNAMIC, annotation.mainField().dynamic().name().toLowerCase());
mainFieldNode.put(TYPE_DYNAMIC, annotation.mainField().dynamic().getMappedName());
} else if (dynamicMapping != null) {
mainFieldNode.put(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
mainFieldNode.put(TYPE_DYNAMIC, dynamicMapping.value().getMappedName());
}
}

View File

@ -237,7 +237,7 @@ public final class MappingParameters {
}
if (type != FieldType.Auto) {
objectNode.put(FIELD_PARAM_TYPE, type.toString().toLowerCase());
objectNode.put(FIELD_PARAM_TYPE, type.getMappedName());
if (type == FieldType.Date) {
List<String> formats = new ArrayList<>();

View File

@ -24,7 +24,8 @@ package org.springframework.data.elasticsearch.core.mapping;
public interface PropertyValueConverter {
/**
* Converts a property value to an elasticsearch value.
* Converts a property value to an elasticsearch value. If the converter cannot convert the value, it must return a
* String representation.
*
* @param value the value to convert, must not be {@literal null}
* @return The elasticsearch property value, must not be {@literal null}

View File

@ -954,7 +954,23 @@ public class Criteria {
/**
* @since 4.3
*/
NOT_EMPTY
NOT_EMPTY;
/**
* @return true if this key does not have an associated value
* @since 4.4
*/
public boolean hasNoValue() {
return this == OperationKey.EXISTS || this == OperationKey.EMPTY || this == OperationKey.NOT_EMPTY;
}
/**
* @return true if this key does have an associated value
* @since 4.4
*/
public boolean hasValue() {
return !hasNoValue();
}
}
/**
@ -967,9 +983,8 @@ public class Criteria {
protected CriteriaEntry(OperationKey key) {
boolean keyIsValid = key == OperationKey.EXISTS || key == OperationKey.EMPTY || key == OperationKey.NOT_EMPTY;
Assert.isTrue(keyIsValid,
"key must be OperationKey.EXISTS, OperationKey.EMPTY or OperationKey.EMPTY for this call");
Assert.isTrue(key.hasNoValue(),
"key must be OperationKey.EXISTS, OperationKey.EMPTY or OperationKey.NOT_EMPTY for this call");
this.key = key;
}

View File

@ -1,4 +1,4 @@
Spring Data Elasticsearch 4.3 GA (2021.1.0)
Spring Data Elasticsearch 4.3.2 (2021.1.2)
Copyright (c) [2013-2021] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@ -29,6 +29,8 @@ conditions of the subcomponent's license, as noted in the LICENSE file.

View File

@ -2783,6 +2783,33 @@ public abstract class ElasticsearchTemplateTests {
assertThat(searchHits.getSearchHit(1).getInnerHits("innerHits").getTotalHits()).isEqualTo(1);
}
@Test // #1997
@DisplayName("should return document with inner hits size zero")
void shouldReturnDocumentWithInnerHitsSizeZero() {
// given
SampleEntity sampleEntity = SampleEntity.builder().id(nextIdAsString()).message("message 1").rate(1)
.version(System.currentTimeMillis()).build();
List<IndexQuery> indexQueries = getIndexQueries(Arrays.asList(sampleEntity));
operations.bulkIndex(indexQueries, IndexCoordinates.of(indexNameProvider.indexName()));
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withCollapseBuilder(new CollapseBuilder("rate").setInnerHits(new InnerHitBuilder("innerHits").setSize(0)))
.build();
// when
SearchHits<SampleEntity> searchHits = operations.search(searchQuery, SampleEntity.class,
IndexCoordinates.of(indexNameProvider.indexName()));
// then
assertThat(searchHits).isNotNull();
assertThat(searchHits.getTotalHits()).isEqualTo(1);
assertThat(searchHits.getSearchHits()).hasSize(1);
assertThat(searchHits.getSearchHit(0).getContent().getMessage()).isEqualTo("message 1");
}
private IndexQuery getIndexQuery(SampleEntity sampleEntity) {
return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity)
.withVersion(sampleEntity.getVersion()).build();

View File

@ -66,6 +66,9 @@ import org.springframework.data.elasticsearch.core.geo.GeoJsonPolygon;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
@ -1496,6 +1499,16 @@ public class MappingElasticsearchConverterUnitTests {
assertThat(entity.getDontConvert()).isEqualTo("Monty Python's Flying Circus");
}
@Test // #2080
@DisplayName("should not try to call property converter on updating criteria exists")
void shouldNotTryToCallPropertyConverterOnUpdatingCriteriaExists() {
// don't care if the query makes no sense, we just add all criteria without values
Query query = new CriteriaQuery(Criteria.where("fieldWithClassBasedConverter").exists().empty().notEmpty());
mappingElasticsearchConverter.updateQuery(query, EntityWithCustomValueConverters.class);
}
private Map<String, Object> writeToMap(Object source) {
Document sink = Document.create();
@ -2429,6 +2442,7 @@ public class MappingElasticsearchConverterUnitTests {
return reverse(value);
}
}
// endregion
private static String reverse(Object o) {
@ -2436,5 +2450,4 @@ public class MappingElasticsearchConverterUnitTests {
return new StringBuilder().append(o.toString()).reverse().toString();
}
// endregion
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 2021 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core.convert;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.params.provider.Arguments.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchPersistentEntity;
import org.springframework.lang.Nullable;
/**
* @author Peter-Josef Meisch
*/
public class PropertyValueConvertersUnitTests {
@ParameterizedTest(name = "{0}") // #2018
@MethodSource("propertyValueConverters")
@DisplayName("should return original object on write if it cannot be converted")
void shouldReturnOriginalObjectOnWriteIfItCannotBeConverted(PropertyValueConverter converter) {
NoConverterForThisClass value = new NoConverterForThisClass();
Object written = converter.write(value);
assertThat(written).isEqualTo(value.toString());
}
static Stream<Arguments> propertyValueConverters() {
SimpleElasticsearchMappingContext context = new SimpleElasticsearchMappingContext();
SimpleElasticsearchPersistentEntity<?> persistentEntity = context
.getRequiredPersistentEntity(NoConverterForThisClass.class);
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("property");
List<PropertyValueConverter> converters = new ArrayList<>();
converters.add(new DatePropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
converters.add(new DateRangePropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
converters.add(new NumberRangePropertyValueConverter(persistentProperty));
converters.add(new TemporalPropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
converters.add(new TemporalRangePropertyValueConverter(persistentProperty,
Collections.singletonList(ElasticsearchDateConverter.of(DateFormat.basic_date))));
return converters.stream().map(propertyValueConverter -> arguments(
Named.of(propertyValueConverter.getClass().getSimpleName(), propertyValueConverter)));
}
static class NoConverterForThisClass {
@SuppressWarnings("unused")
@Nullable Long property;
}
}

View File

@ -38,10 +38,14 @@ import java.util.Objects;
import java.util.Set;
import org.assertj.core.data.Percentage;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.*;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
@ -57,6 +61,7 @@ import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Point;
@ -79,10 +84,25 @@ import org.springframework.test.context.ContextConfiguration;
* @author Morgan Lutz
*/
@SpringIntegrationTest
@ContextConfiguration(classes = { ElasticsearchRestTemplateConfiguration.class })
@ContextConfiguration(classes = { MappingBuilderIntegrationTests.Config.class })
public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
@Configuration
@Import({ ElasticsearchRestTemplateConfiguration.class })
static class Config {
@Bean
IndexNameProvider indexNameProvider() {
return new IndexNameProvider("mapping-builder");
}
}
@Autowired private ElasticsearchOperations operations;
@Autowired IndexNameProvider indexNameProvider;
@BeforeEach
public void before() {
indexNameProvider.increment();
}
@Test
@Order(java.lang.Integer.MAX_VALUE)
@ -132,8 +152,7 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
@Test // DATAES-76
public void shouldAddSampleInheritedEntityDocumentToIndex() {
// given
IndexCoordinates index = IndexCoordinates.of("test-index-sample-inherited-mapping-builder");
IndexOperations indexOps = operations.indexOps(index);
IndexOperations indexOps = operations.indexOps(SampleInheritedEntity.class);
// when
indexOps.create();
@ -142,11 +161,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
String message = "msg";
String id = "abc";
operations.index(new SampleInheritedEntityBuilder(id).createdDate(createdDate).message(message).buildIndex(),
index);
operations.indexOps(SampleInheritedEntity.class).refresh();
IndexCoordinates.of(indexNameProvider.indexName()));
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
SearchHits<SampleInheritedEntity> result = operations.search(searchQuery, SampleInheritedEntity.class, index);
SearchHits<SampleInheritedEntity> result = operations.search(searchQuery, SampleInheritedEntity.class);
// then
assertThat(result).hasSize(1);
@ -163,7 +181,7 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
IndexOperations indexOpsUser = operations.indexOps(User.class);
indexOpsUser.create();
indexOpsUser.putMapping(User.class);
indexNameProvider.increment();
IndexOperations indexOpsGroup = operations.indexOps(Group.class);
indexOpsGroup.create();
indexOpsGroup.putMapping(Group.class);
@ -336,11 +354,19 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
@Test // #2024
@DisplayName("should map all field type values")
void shouldMapAllFieldTypeValues() {
operations.indexOps(EntityWithAllTypes.class).createWithMapping();
}
// region entities
@Document(indexName = "ignore-above-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class IgnoreAboveEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Keyword, ignoreAbove = 10) private String message;
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Keyword, ignoreAbove = 10) private String message;
@Nullable
public String getId() {
@ -365,57 +391,76 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
@Document(indexName = "fieldname-index")
static class IdEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
}
@Document(indexName = "fieldname-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class TextEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
@Field(name = "text-property", type = FieldType.Text) //
@Nullable private String textProperty;
}
@Document(indexName = "fieldname-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class MappingEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
@Field("mapping-property") @Mapping(mappingPath = "/mappings/test-field-analyzed-mappings.json") //
@Field("mapping-property")
@Mapping(mappingPath = "/mappings/test-field-analyzed-mappings.json") //
@Nullable private byte[] mappingProperty;
}
@Document(indexName = "fieldname-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class GeoPointEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
@Nullable @Field("geopoint-property") private GeoPoint geoPoint;
@Nullable
@Field("geopoint-property") private GeoPoint geoPoint;
}
@Document(indexName = "fieldname-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class CircularEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
@Nullable @Field(name = "circular-property", type = FieldType.Object, ignoreFields = { "circular-property" }) //
@Nullable
@Field(name = "circular-property", type = FieldType.Object, ignoreFields = { "circular-property" }) //
private CircularEntity circularProperty;
}
@Document(indexName = "fieldname-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class CompletionEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
@Nullable @Field("completion-property") @CompletionField(maxInputLength = 100) //
@Nullable
@Field("completion-property")
@CompletionField(maxInputLength = 100) //
private Completion suggest;
}
@Document(indexName = "fieldname-index")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class MultiFieldEntity {
@Nullable @Id @Field("id-property") private String id;
@Nullable
@Id
@Field("id-property") private String id;
@Nullable //
@MultiField(mainField = @Field(name = "main-field", type = FieldType.Text, analyzer = "whitespace"),
@ -425,13 +470,17 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-book-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class Book {
@Nullable @Id private String id;
@Nullable
@Id private String id;
@Nullable private String name;
@Nullable @Field(type = FieldType.Object) private Author author;
@Nullable @Field(type = FieldType.Nested) private Map<Integer, Collection<String>> buckets = new HashMap<>();
@Nullable @MultiField(mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
@Nullable
@Field(type = FieldType.Object) private Author author;
@Nullable
@Field(type = FieldType.Nested) private Map<Integer, Collection<String>> buckets = new HashMap<>();
@Nullable
@MultiField(mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
otherFields = { @InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop",
searchAnalyzer = "standard") }) private String description;
@ -481,11 +530,12 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-simple-recursive-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class SimpleRecursiveEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Object,
ignoreFields = { "circularObject" }) private SimpleRecursiveEntity circularObject;
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Object, ignoreFields = { "circularObject" }) private SimpleRecursiveEntity circularObject;
@Nullable
public String getId() {
@ -506,12 +556,16 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-copy-to-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class CopyToEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Keyword, copyTo = "name") private String firstName;
@Nullable @Field(type = FieldType.Keyword, copyTo = "name") private String lastName;
@Nullable @Field(type = FieldType.Keyword) private String name;
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Keyword, copyTo = "name") private String firstName;
@Nullable
@Field(type = FieldType.Keyword, copyTo = "name") private String lastName;
@Nullable
@Field(type = FieldType.Keyword) private String name;
@Nullable
public String getId() {
@ -550,12 +604,15 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-normalizer-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
@Setting(settingPath = "/settings/test-normalizer.json")
static class NormalizerEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Keyword, normalizer = "lower_case_normalizer") private String name;
@Nullable @MultiField(mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(suffix = "lower_case",
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Keyword, normalizer = "lower_case_normalizer") private String name;
@Nullable
@MultiField(mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(suffix = "lower_case",
type = FieldType.Keyword, normalizer = "lower_case_normalizer") }) private String description;
@Nullable
@ -610,10 +667,11 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-sample-inherited-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class SampleInheritedEntity extends AbstractInheritedEntity {
@Nullable @Field(type = Text, index = false, store = true, analyzer = "standard") private String message;
@Nullable
@Field(type = Text, index = false, store = true, analyzer = "standard") private String message;
@Nullable
public String getMessage() {
@ -656,11 +714,13 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-stock-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class StockPrice {
@Nullable @Id private String id;
@Nullable
@Id private String id;
@Nullable private String symbol;
@Nullable @Field(type = FieldType.Double) private BigDecimal price;
@Nullable
@Field(type = FieldType.Double) private BigDecimal price;
@Nullable
public String getId() {
@ -691,8 +751,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
static class AbstractInheritedEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Date, format = DateFormat.date_time, index = false) private Date createdDate;
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Date, format = DateFormat.date_time, index = false) private Date createdDate;
@Nullable
public String getId() {
@ -713,21 +775,27 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-geo-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class GeoEntity {
@Nullable @Id private String id;
@Nullable
@Id private String id;
// geo shape - Spring Data
@Nullable private Box box;
@Nullable private Circle circle;
@Nullable private Polygon polygon;
// geo point - Custom implementation + Spring Data
@Nullable @GeoPointField private Point pointA;
@Nullable
@GeoPointField private Point pointA;
@Nullable private GeoPoint pointB;
@Nullable @GeoPointField private String pointC;
@Nullable @GeoPointField private double[] pointD;
@Nullable
@GeoPointField private String pointC;
@Nullable
@GeoPointField private double[] pointD;
// geo shape, until e have the classes for this, us a strng
@Nullable @GeoShapeField private String shape1;
@Nullable @GeoShapeField(coerce = true, ignoreMalformed = true, ignoreZValue = false,
@Nullable
@GeoShapeField private String shape1;
@Nullable
@GeoShapeField(coerce = true, ignoreMalformed = true, ignoreZValue = false,
orientation = GeoShapeField.Orientation.clockwise) private String shape2;
@Nullable
@ -821,17 +889,21 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-user-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class User {
@Nullable @Id private String id;
@Nullable
@Id private String id;
@Field(type = FieldType.Nested, ignoreFields = { "users" }) private Set<Group> groups = new HashSet<>();
}
@Document(indexName = "test-index-group-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class Group {
@Nullable @Id String id;
@Nullable
@Id String id;
@Field(type = FieldType.Nested, ignoreFields = { "groups" }) private Set<User> users = new HashSet<>();
}
@ -848,11 +920,14 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "completion")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class CompletionDocument {
@Nullable @Id private String id;
@Nullable @CompletionField(contexts = { @CompletionContext(name = "location",
type = CompletionContext.ContextMappingType.GEO, path = "proppath") }) private Completion suggest;
@Nullable
@Id private String id;
@Nullable
@CompletionField(contexts = { @CompletionContext(name = "location", type = CompletionContext.ContextMappingType.GEO,
path = "proppath") }) private Completion suggest;
@Nullable
public String getId() {
@ -873,9 +948,10 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "test-index-entity-with-seq-no-primary-term-mapping-builder")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class EntityWithSeqNoPrimaryTerm {
@Nullable @Field(type = Object) private SeqNoPrimaryTerm seqNoPrimaryTerm;
@Nullable
@Field(type = Object) private SeqNoPrimaryTerm seqNoPrimaryTerm;
@Nullable
public SeqNoPrimaryTerm getSeqNoPrimaryTerm() {
@ -888,10 +964,14 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
static class RankFeatureEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Rank_Feature) private Integer pageRank;
@Nullable @Field(type = FieldType.Rank_Feature, positiveScoreImpact = false) private Integer urlLength;
@Nullable @Field(type = FieldType.Rank_Features) private Map<String, Integer> topics;
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Rank_Feature) private Integer pageRank;
@Nullable
@Field(type = FieldType.Rank_Feature, positiveScoreImpact = false) private Integer urlLength;
@Nullable
@Field(type = FieldType.Rank_Features) private Map<String, Integer> topics;
@Nullable
public String getId() {
@ -930,18 +1010,25 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "termvectors-test")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class TermVectorFieldEntity {
@Nullable @Id private String id;
@Nullable @Field(type = FieldType.Text, termVector = TermVector.no) private String no;
@Nullable @Field(type = FieldType.Text, termVector = TermVector.yes) private String yes;
@Nullable @Field(type = FieldType.Text, termVector = TermVector.with_positions) private String with_positions;
@Nullable @Field(type = FieldType.Text, termVector = TermVector.with_offsets) private String with_offsets;
@Nullable @Field(type = FieldType.Text,
termVector = TermVector.with_positions_offsets) private String with_positions_offsets;
@Nullable @Field(type = FieldType.Text,
@Nullable
@Id private String id;
@Nullable
@Field(type = FieldType.Text, termVector = TermVector.no) private String no;
@Nullable
@Field(type = FieldType.Text, termVector = TermVector.yes) private String yes;
@Nullable
@Field(type = FieldType.Text, termVector = TermVector.with_positions) private String with_positions;
@Nullable
@Field(type = FieldType.Text, termVector = TermVector.with_offsets) private String with_offsets;
@Nullable
@Field(type = FieldType.Text, termVector = TermVector.with_positions_offsets) private String with_positions_offsets;
@Nullable
@Field(type = FieldType.Text,
termVector = TermVector.with_positions_payloads) private String with_positions_payloads;
@Nullable @Field(type = FieldType.Text,
@Nullable
@Field(type = FieldType.Text,
termVector = TermVector.with_positions_offsets_payloads) private String with_positions_offsets_payloads;
@Nullable
@ -1017,10 +1104,12 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "wildcard-test")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class WildcardEntity {
@Nullable @Field(type = Wildcard) private String wildcardWithoutParams;
@Nullable @Field(type = Wildcard, nullValue = "WILD", ignoreAbove = 42) private String wildcardWithParams;
@Nullable
@Field(type = Wildcard) private String wildcardWithoutParams;
@Nullable
@Field(type = Wildcard, nullValue = "WILD", ignoreAbove = 42) private String wildcardWithParams;
@Nullable
public String getWildcardWithoutParams() {
@ -1041,11 +1130,13 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "disabled-entity-mapping")
@Document(indexName = "#{@indexNameProvider.indexName()}")
@Mapping(enabled = false)
static class DisabledMappingEntity {
@Nullable @Id private String id;
@Nullable @Field(type = Text) private String text;
@Nullable
@Id private String id;
@Nullable
@Field(type = Text) private String text;
@Nullable
public String getId() {
@ -1068,9 +1159,13 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
@Document(indexName = "disabled-property-mapping")
static class DisabledMappingProperty {
@Nullable @Id private String id;
@Nullable @Field(type = Text) private String text;
@Nullable @Mapping(enabled = false) @Field(type = Object) private Object object;
@Nullable
@Id private String id;
@Nullable
@Field(type = Text) private String text;
@Nullable
@Mapping(enabled = false)
@Field(type = Object) private Object object;
@Nullable
public String getId() {
@ -1100,10 +1195,12 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "densevector-test")
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class DenseVectorEntity {
@Nullable @Id private String id;
@Nullable @Field(type = Dense_Vector, dims = 3) private float[] dense_vector;
@Nullable
@Id private String id;
@Nullable
@Field(type = Dense_Vector, dims = 3) private float[] dense_vector;
@Nullable
public String getId() {
@ -1124,15 +1221,19 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "dynamic-mapping-annotation")
@Document(indexName = "#{@indexNameProvider.indexName()}")
@DynamicMapping(DynamicMappingValue.False)
static class DynamicMappingAnnotationEntity {
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
type = FieldType.Object) private Map<String, Object> objectMap;
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
type = FieldType.Nested) private List<Map<String, Object>> nestedObjectMap;
@Nullable
@DynamicMapping(DynamicMappingValue.Strict)
@Field(type = FieldType.Object) private Author author;
@Nullable
@DynamicMapping(DynamicMappingValue.False)
@Field(type = FieldType.Object) private Map<String, Object> objectMap;
@Nullable
@DynamicMapping(DynamicMappingValue.False)
@Field(type = FieldType.Nested) private List<Map<String, Object>> nestedObjectMap;
@Nullable
public Author getAuthor() {
@ -1144,57 +1245,140 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
}
}
@Document(indexName = "dynamic-mapping", dynamic = Dynamic.FALSE)
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class DynamicMappingEntity {
@Nullable @Field(type = FieldType.Object) //
@Nullable
@Field(type = FieldType.Object) //
private Map<String, Object> objectInherit;
@Nullable @Field(type = FieldType.Object, dynamic = Dynamic.FALSE) //
@Nullable
@Field(type = FieldType.Object, dynamic = Dynamic.FALSE) //
private Map<String, Object> objectFalse;
@Nullable @Field(type = FieldType.Object, dynamic = Dynamic.TRUE) //
@Nullable
@Field(type = FieldType.Object, dynamic = Dynamic.TRUE) //
private Map<String, Object> objectTrue;
@Nullable @Field(type = FieldType.Object, dynamic = Dynamic.STRICT) //
@Nullable
@Field(type = FieldType.Object, dynamic = Dynamic.STRICT) //
private Map<String, Object> objectStrict;
@Nullable @Field(type = FieldType.Object, dynamic = Dynamic.RUNTIME) //
@Nullable
@Field(type = FieldType.Object, dynamic = Dynamic.RUNTIME) //
private Map<String, Object> objectRuntime;
@Nullable @Field(type = FieldType.Nested) //
@Nullable
@Field(type = FieldType.Nested) //
private List<Map<String, Object>> nestedObjectInherit;
@Nullable @Field(type = FieldType.Nested, dynamic = Dynamic.FALSE) //
@Nullable
@Field(type = FieldType.Nested, dynamic = Dynamic.FALSE) //
private List<Map<String, Object>> nestedObjectFalse;
@Nullable @Field(type = FieldType.Nested, dynamic = Dynamic.TRUE) //
@Nullable
@Field(type = FieldType.Nested, dynamic = Dynamic.TRUE) //
private List<Map<String, Object>> nestedObjectTrue;
@Nullable @Field(type = FieldType.Nested, dynamic = Dynamic.STRICT) //
@Nullable
@Field(type = FieldType.Nested, dynamic = Dynamic.STRICT) //
private List<Map<String, Object>> nestedObjectStrict;
@Nullable @Field(type = FieldType.Nested, dynamic = Dynamic.RUNTIME) //
@Nullable
@Field(type = FieldType.Nested, dynamic = Dynamic.RUNTIME) //
private List<Map<String, Object>> nestedObjectRuntime;
}
@Document(indexName = "dynamic-detection-mapping-true")
@Document(indexName = "#{@indexNameProvider.indexName()}")
@Mapping(dateDetection = Mapping.Detection.TRUE, numericDetection = Mapping.Detection.TRUE,
dynamicDateFormats = { "MM/dd/yyyy" })
private static class DynamicDetectionMapping {
@Id @Nullable private String id;
@Id
@Nullable private String id;
}
@Document(indexName = "runtime-fields")
@Document(indexName = "#{@indexNameProvider.indexName()}")
@Mapping(runtimeFieldsPath = "/mappings/runtime-fields.json")
private static class RuntimeFieldEntity {
@Id @Nullable private String id;
@Field(type = Date, format = DateFormat.epoch_millis, name = "@timestamp") @Nullable private Instant timestamp;
@Id
@Nullable private String id;
@Field(type = Date, format = DateFormat.epoch_millis, name = "@timestamp")
@Nullable private Instant timestamp;
}
@Document(indexName = "fields-excluded-from-source")
@Document(indexName = "#{@indexNameProvider.indexName()}")
private static class ExcludedFieldEntity {
@Id @Nullable private String id;
@Nullable @Field(name = "excluded-date", type = Date, format = DateFormat.date,
@Id
@Nullable private String id;
@Nullable
@Field(name = "excluded-date", type = Date, format = DateFormat.date,
excludeFromSource = true) private LocalDate excludedDate;
@Nullable @Field(type = Nested) private NestedExcludedFieldEntity nestedEntity;
@Nullable
@Field(type = Nested) private NestedExcludedFieldEntity nestedEntity;
}
private static class NestedExcludedFieldEntity {
@Nullable @Field(name = "excluded-text", type = Text, excludeFromSource = true) private String excludedText;
@Nullable
@Field(name = "excluded-text", type = Text, excludeFromSource = true) private String excludedText;
}
@Document(indexName = "#{@indexNameProvider.indexName()}")
private static class EntityWithAllTypes {
@Nullable
@Field(type = FieldType.Auto) String autoField;
@Nullable
@Field(type = FieldType.Text) String textField;
@Nullable
@Field(type = FieldType.Keyword) String keywordField;
@Nullable
@Field(type = FieldType.Long) String longField;
@Nullable
@Field(type = FieldType.Integer) String integerField;
@Nullable
@Field(type = FieldType.Short) String shortField;
@Nullable
@Field(type = FieldType.Byte) String byteField;
@Nullable
@Field(type = FieldType.Double) String doubleField;
@Nullable
@Field(type = FieldType.Float) String floatField;
@Nullable
@Field(type = FieldType.Half_Float) String halfFloatField;
@Nullable
@Field(type = FieldType.Scaled_Float) String scaledFloatField;
@Nullable
@Field(type = FieldType.Date) String dateField;
@Nullable
@Field(type = FieldType.Date_Nanos) String dateNanosField;
@Nullable
@Field(type = FieldType.Boolean) String booleanField;
@Nullable
@Field(type = FieldType.Binary) String binaryField;
@Nullable
@Field(type = FieldType.Integer_Range) String integerRangeField;
@Nullable
@Field(type = FieldType.Float_Range) String floatRangeField;
@Nullable
@Field(type = FieldType.Long_Range) String longRangeField;
@Nullable
@Field(type = FieldType.Double_Range) String doubleRangeField;
@Nullable
@Field(type = FieldType.Date_Range) String dateRangeField;
@Nullable
@Field(type = FieldType.Ip_Range) String ipRangeField;
@Nullable
@Field(type = FieldType.Object) String objectField;
@Nullable
@Field(type = FieldType.Nested) String nestedField;
@Nullable
@Field(type = FieldType.Ip) String ipField;
@Nullable
@Field(type = FieldType.TokenCount, analyzer = "standard") String tokenCountField;
@Nullable
@Field(type = FieldType.Percolator) String percolatorField;
@Nullable
@Field(type = FieldType.Flattened) String flattenedField;
@Nullable
@Field(type = FieldType.Search_As_You_Type) String searchAsYouTypeField;
@Nullable
@Field(type = FieldType.Rank_Feature) String rankFeatureField;
@Nullable
@Field(type = FieldType.Rank_Features) String rankFeaturesField;
@Nullable
@Field(type = FieldType.Wildcard) String wildcardField;
@Nullable
@Field(type = FieldType.Dense_Vector, dims = 1) String denseVectorField;
}
// endregion
}

View File

@ -265,23 +265,30 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
// region entities
static class FieldNameProperty {
@Nullable @Field(name = "by-name") String fieldProperty;
@Nullable
@Field(name = "by-name") String fieldProperty;
}
static class FieldValueProperty {
@Nullable @Field(value = "by-value") String fieldProperty;
@Nullable
@Field(value = "by-value") String fieldProperty;
}
static class MultiFieldProperty {
@Nullable @MultiField(mainField = @Field("mainfield"),
@Nullable
@MultiField(mainField = @Field("mainfield"),
otherFields = { @InnerField(suffix = "suff", type = FieldType.Keyword) }) String mainfieldProperty;
}
static class DatesProperty {
@Nullable @Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") LocalDate localDate;
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time) LocalDateTime localDateTime;
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time) Date legacyDate;
@Nullable @Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") List<LocalDate> localDateList;
@Nullable
@Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") LocalDate localDate;
@Nullable
@Field(type = FieldType.Date, format = DateFormat.basic_date_time) LocalDateTime localDateTime;
@Nullable
@Field(type = FieldType.Date, format = DateFormat.basic_date_time) Date legacyDate;
@Nullable
@Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") List<LocalDate> localDateList;
}
static class SeqNoPrimaryTermProperty {
@ -344,8 +351,10 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
private static class EntityWithCustomValueConverters {
@Id private String id;
@Nullable @ValueConverter(ClassBasedValueConverter.class) private String fieldWithClassBasedConverter;
@Nullable @ValueConverter(EnumBasedValueConverter.class) private String fieldWithEnumBasedConverter;
@Nullable
@ValueConverter(ClassBasedValueConverter.class) private String fieldWithClassBasedConverter;
@Nullable
@ValueConverter(EnumBasedValueConverter.class) private String fieldWithEnumBasedConverter;
}
private static class ClassBasedValueConverter implements PropertyValueConverter {