Upgrade to Elasticsearch 8.15.0.

Ortiginal Pull Request #2974
Closes #2963
This commit is contained in:
Peter-Josef Meisch 2024-08-30 21:31:07 +02:00 committed by GitHub
parent 6ad98bf500
commit 81eb167981
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 119 additions and 126 deletions

View File

@ -21,7 +21,7 @@
<springdata.commons>3.4.0-SNAPSHOT</springdata.commons>
<!-- version of the ElasticsearchClient -->
<elasticsearch-java>8.14.3</elasticsearch-java>
<elasticsearch-java>8.15.0</elasticsearch-java>
<blockhound-junit>1.0.9.RELEASE</blockhound-junit>
<hoverfly>0.19.0</hoverfly>

View File

@ -4,7 +4,7 @@
[[new-features.5-4-0]]
== New in Spring Data Elasticsearch 5.4
* Upgrade to Elasticsearch 8.14.3.
* Upgrade to Elasticsearch 8.15.0.
* Allow to customize the mapped type name for `@InnerField` and `@Field` annotations.
* Support for Elasticsearch SQL.

View File

@ -6,7 +6,7 @@ The following table shows the Elasticsearch and Spring versions that are used by
[cols="^,^,^,^",options="header"]
|===
| Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Framework
| 2024.1 (in development) | 5.3.x | 8.14.3 | 6.1.x
| 2024.1 (in development) | 5.3.x | 8.15.0 | 6.1.x
| 2024.0 | 5.3.1 | 8.13.4 | 6.1.x
| 2023.1 (Vaughan) | 5.2.x | 8.11.1 | 6.1.x
| 2023.0 (Ullmann) | 5.1.x | 8.7.1 | 6.0.x

View File

@ -127,7 +127,7 @@ class CriteriaQueryProcessor extends AbstractQueryProcessor {
mustQueries.add(Query.of(qb -> qb.matchAll(m -> m)));
}
return new Query.Builder().bool(boolQueryBuilder -> {
return new Query.Builder().bool(boolQueryBuilder -> {
if (!shouldQueries.isEmpty()) {
boolQueryBuilder.should(shouldQueries);
@ -249,49 +249,54 @@ class CriteriaQueryProcessor extends AbstractQueryProcessor {
queryBuilder.queryString(queryStringQuery(fieldName, Objects.requireNonNull(value).toString(), boost));
break;
case LESS:
queryBuilder //
.range(rb -> rb //
.field(fieldName) //
.lt(JsonData.of(value)) //
.boost(boost)); //
queryBuilder
.range(rb -> rb
.untyped(ut -> ut
.field(fieldName)
.lt(JsonData.of(value))
.boost(boost)));
break;
case LESS_EQUAL:
queryBuilder //
.range(rb -> rb //
.field(fieldName) //
.lte(JsonData.of(value)) //
.boost(boost)); //
queryBuilder
.range(rb -> rb
.untyped(ut -> ut
.field(fieldName)
.lte(JsonData.of(value))
.boost(boost)));
break;
case GREATER:
queryBuilder //
.range(rb -> rb //
.field(fieldName) //
.gt(JsonData.of(value)) //
.boost(boost)); //
queryBuilder
.range(rb -> rb
.untyped(ut -> ut
.field(fieldName)
.gt(JsonData.of(value))
.boost(boost)));
break;
case GREATER_EQUAL:
queryBuilder //
.range(rb -> rb //
.field(fieldName) //
.gte(JsonData.of(value)) //
.boost(boost)); //
queryBuilder
.range(rb -> rb
.untyped(ut -> ut
.field(fieldName)
.gte(JsonData.of(value))
.boost(boost)));
break;
case BETWEEN:
Object[] ranges = (Object[]) value;
Assert.notNull(value, "value for a between condition must not be null");
queryBuilder //
.range(rb -> {
rb.field(fieldName);
if (ranges[0] != null) {
rb.gte(JsonData.of(ranges[0]));
}
queryBuilder
.range(rb -> rb
.untyped(ut -> {
ut.field(fieldName);
if (ranges[0] != null) {
ut.gte(JsonData.of(ranges[0]));
}
if (ranges[1] != null) {
rb.lte(JsonData.of(ranges[1]));
}
rb.boost(boost); //
return rb;
}); //
if (ranges[1] != null) {
ut.lte(JsonData.of(ranges[1]));
}
ut.boost(boost); //
return ut;
}));
break;
case FUZZY:

View File

@ -126,7 +126,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
// java.lang.Class<TDocument>)
// noinspection unchecked
JsonEndpoint<GetRequest, GetResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<GetRequest, GetResponse<T>, ErrorResponse>) GetRequest._ENDPOINT;
endpoint = new EndpointWithResponseMapperAttr<>(endpoint, "co.elastic.clients:Deserializer:_global.get.TDocument",
endpoint = new EndpointWithResponseMapperAttr<>(endpoint, "co.elastic.clients:Deserializer:_global.get.Response.TDocument",
getDeserializer(tClass));
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
@ -145,7 +145,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
// noinspection unchecked
JsonEndpoint<UpdateRequest<?, ?>, UpdateResponse<T>, ErrorResponse> endpoint = new EndpointWithResponseMapperAttr(
UpdateRequest._ENDPOINT, "co.elastic.clients:Deserializer:_global.update.TDocument",
UpdateRequest._ENDPOINT, "co.elastic.clients:Deserializer:_global.update.Response.TDocument",
this.getDeserializer(clazz));
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, this.transportOptions));
}
@ -171,7 +171,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
// noinspection unchecked
JsonEndpoint<MgetRequest, MgetResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<MgetRequest, MgetResponse<T>, ErrorResponse>) MgetRequest._ENDPOINT;
endpoint = new EndpointWithResponseMapperAttr<>(endpoint, "co.elastic.clients:Deserializer:_global.mget.TDocument",
endpoint = new EndpointWithResponseMapperAttr<>(endpoint, "co.elastic.clients:Deserializer:_global.mget.Response.TDocument",
this.getDeserializer(clazz));
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
@ -282,7 +282,7 @@ public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTranspor
// noinspection unchecked
JsonEndpoint<ScrollRequest, ScrollResponse<T>, ErrorResponse> endpoint = (JsonEndpoint<ScrollRequest, ScrollResponse<T>, ErrorResponse>) ScrollRequest._ENDPOINT;
endpoint = new EndpointWithResponseMapperAttr<>(endpoint,
"co.elastic.clients:Deserializer:_global.scroll.TDocument", getDeserializer(tDocumentClass));
"co.elastic.clients:Deserializer:_global.scroll.Response.TDocument", getDeserializer(tDocumentClass));
return Mono.fromFuture(transport.performRequestAsync(request, endpoint, transportOptions));
}

View File

@ -20,7 +20,6 @@ import static org.springframework.util.CollectionUtils.*;
import co.elastic.clients.elasticsearch._types.Conflicts;
import co.elastic.clients.elasticsearch._types.ExpandWildcard;
import co.elastic.clients.elasticsearch._types.InlineScript;
import co.elastic.clients.elasticsearch._types.NestedSortValue;
import co.elastic.clients.elasticsearch._types.OpType;
import co.elastic.clients.elasticsearch._types.SortOptions;
@ -744,16 +743,12 @@ class RequestConverter extends AbstractQueryProcessor {
scriptData.params().forEach((key, value) -> params.put(key, JsonData.of(value, jsonpMapper)));
}
return co.elastic.clients.elasticsearch._types.Script.of(sb -> {
sb.lang(scriptData.language())
.params(params);
if (scriptData.type() == ScriptType.INLINE) {
sb.inline(is -> is //
.lang(scriptData.language()) //
.source(scriptData.script()) //
.params(params)); //
sb.source(scriptData.script());
} else if (scriptData.type() == ScriptType.STORED) {
sb.stored(ss -> ss //
.id(scriptData.script()) //
.params(params) //
);
sb.id(scriptData.script());
}
return sb;
});
@ -925,7 +920,9 @@ class RequestConverter extends AbstractQueryProcessor {
ReindexRequest.Script script = reindexRequest.getScript();
if (script != null) {
builder.script(s -> s.inline(InlineScript.of(i -> i.lang(script.getLang()).source(script.getSource()))));
builder.script(sb -> sb
.lang(script.getLang())
.source(script.getSource()));
}
builder.timeout(time(reindexRequest.getTimeout())) //
@ -1078,21 +1075,15 @@ class RequestConverter extends AbstractQueryProcessor {
}
uqb.script(sb -> {
sb.lang(query.getLang()).params(params);
if (query.getScriptType() == ScriptType.INLINE) {
sb.inline(is -> is //
.lang(query.getLang()) //
.source(query.getScript()) //
.params(params)); //
sb.source(query.getScript()); //
} else if (query.getScriptType() == ScriptType.STORED) {
sb.stored(ss -> ss //
.id(query.getScript()) //
.params(params) //
);
sb.id(query.getScript());
}
return sb;
}
);
});
}
uqb //
@ -1347,17 +1338,16 @@ class RequestConverter extends AbstractQueryProcessor {
String script = runtimeField.getScript();
if (script != null) {
rfb
.script(s -> s
.inline(is -> {
is.source(script);
rfb.script(s -> {
s.source(script);
if (runtimeField.getParams() != null) {
is.params(TypeUtils.paramsMap(runtimeField.getParams()));
}
return is;
}));
if (runtimeField.getParams() != null) {
s.params(TypeUtils.paramsMap(runtimeField.getParams()));
}
return s;
});
}
return rfb;
});
runtimeMappings.put(runtimeField.getName(), esRuntimeField);
@ -1548,16 +1538,14 @@ class RequestConverter extends AbstractQueryProcessor {
rfb.type(RuntimeFieldType._DESERIALIZER.parse(runtimeField.getType()));
String script = runtimeField.getScript();
if (script != null) {
rfb
.script(s -> s
.inline(is -> {
is.source(script);
rfb.script(s -> {
s.source(script);
if (runtimeField.getParams() != null) {
is.params(TypeUtils.paramsMap(runtimeField.getParams()));
}
return is;
}));
if (runtimeField.getParams() != null) {
s.params(TypeUtils.paramsMap(runtimeField.getParams()));
}
return s;
});
}
return rfb;

View File

@ -34,12 +34,12 @@ public class IndexCoordinates {
private final String[] indexNames;
public static IndexCoordinates of(String... indexNames) {
Assert.notNull(indexNames, "indexNames must not be null");
return new IndexCoordinates(indexNames);
}
private IndexCoordinates(String... indexNames) {
Assert.notEmpty(indexNames, "indexNames may not be null or empty");
Assert.noNullElements(indexNames, "indexNames may not contain null elements");
this.indexNames = indexNames;
}

View File

@ -190,44 +190,42 @@ public class ElasticsearchELCIntegrationTests extends ElasticsearchIntegrationTe
@Override
protected Query getQueryWithRescorer() {
return NativeQuery.builder() //
.withQuery(q -> q //
.bool(b -> b //
.filter(f -> f.exists(e -> e.field("rate"))) //
.should(s -> s.term(t -> t.field("message").value("message"))) //
)) //
.withRescorerQuery( //
new RescorerQuery(NativeQuery.builder() //
.withQuery(q -> q //
.functionScore(fs -> fs //
.functions(f1 -> f1 //
.filter(matchAllQueryAsQuery()) //
.weight(1.0) //
.gauss(d -> d //
.field("rate") //
.placement(dp -> dp //
.origin(JsonData.of(0)) //
.scale(JsonData.of(10)) //
.decay(0.5)) //
)) //
.functions(f2 -> f2 //
.filter(matchAllQueryAsQuery()).weight(100.0) //
.gauss(d -> d //
.field("rate") //
.placement(dp -> dp //
.origin(JsonData.of(0)) //
.scale(JsonData.of(10)) //
.decay(0.5)) //
return NativeQuery.builder()
.withQuery(q -> q
.bool(b -> b
.filter(f -> f.exists(e -> e.field("rate")))
.should(s -> s.term(t -> t.field("message").value("message")))))
.withRescorerQuery(
new RescorerQuery(NativeQuery.builder()
.withQuery(q -> q
.functionScore(fs -> fs
.functions(f1 -> f1
.filter(matchAllQueryAsQuery())
.weight(1.0)
.gauss(d -> d
.untyped(ut -> ut
.field("rate")
.placement(dp -> dp
.origin(JsonData.of(0))
.scale(JsonData.of(10))
.decay(0.5)))))
.functions(f2 -> f2
.filter(matchAllQueryAsQuery()).weight(100.0)
.gauss(d -> d
.untyped(ut -> ut
.field("rate")
.placement(dp -> dp
.origin(JsonData.of(0))
.scale(JsonData.of(10))
.decay(0.5)))
)) //
.scoreMode(FunctionScoreMode.Sum) //
.maxBoost(80.0) //
.boostMode(FunctionBoostMode.Replace)) //
) //
.build() //
) //
.withScoreMode(RescorerQuery.ScoreMode.Max) //
.withWindowSize(100)) //
))
.scoreMode(FunctionScoreMode.Sum)
.maxBoost(80.0)
.boostMode(FunctionBoostMode.Replace)))
.build())
.withScoreMode(RescorerQuery.ScoreMode.Max)
.withWindowSize(100))
.build();
}
}

View File

@ -23,11 +23,12 @@ import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
/**
* @author Peter-Josef Meisch
*/
@SuppressWarnings("DataFlowIssue")
class IndexCoordinatesUnitTests {
@Test
void cannotBeInitializedWithNullIndexName() {
assertThatThrownBy(() -> IndexCoordinates.of(null)).isInstanceOf(IllegalArgumentException.class);
assertThatThrownBy(() -> IndexCoordinates.of((String) null)).isInstanceOf(IllegalArgumentException.class);
}
@Test

View File

@ -54,12 +54,13 @@ public class LogEntityELCIntegrationTests extends LogEntityIntegrationTests {
@Override
Query rangeQueryForIp(String from, String to) {
return NativeQuery.builder() //
.withQuery(qb -> qb //
.range(rqb -> rqb //
.field("ip") //
.gte(JsonData.of(from))//
.lte(JsonData.of(to))//
)).build();
return NativeQuery.builder()
.withQuery(qb -> qb
.range(rqb -> rqb
.untyped(ut -> ut
.field("ip")
.gte(JsonData.of(from))
.lte(JsonData.of(to)))))
.build();
}
}

View File

@ -15,7 +15,7 @@
#
#
sde.testcontainers.image-name=docker.elastic.co/elasticsearch/elasticsearch
sde.testcontainers.image-version=8.14.3
sde.testcontainers.image-version=8.15.0
#
#
# needed as we do a DELETE /* at the end of the tests, will be required from 8.0 on, produces a warning since 7.13