1
0
mirror of synced 2026-05-24 05:03:17 +00:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Mark Paluch a065ba6a76 Release version 5.0.10 (2022.0.10).
See #2673
2023-09-15 10:17:46 +02:00
Mark Paluch 631e5fe496 Prepare 5.0.10 (2022.0.10).
See #2673
2023-09-15 10:17:32 +02:00
Peter-Josef Meisch b1e6e51e16 Fix refresh policy in UpdateQuery.
Original Pull Request #2696
Closes #2692

(cherry picked from commit 2d0aee08ce)
(cherry picked from commit 572cc7ffea)
2023-09-13 21:55:31 +02:00
Peter-Josef Meisch d5df3bfd20 Upgrade deprecated client to Elasticsearch 7.17.13.
Original Pull Request #2695
Closes #2689
2023-09-13 20:05:41 +02:00
Peter-Josef Meisch 7f390845d3 Polishing.
(cherry picked from commit a82952b124)
(cherry picked from commit 4628908e84)
2023-09-03 16:04:19 +02:00
Sébastien Comeau 868a994e33 Fix: missing PhraseSuggestion.Entry.Option's score and collateMatch values.
Original Pull Request #2680
Closes #2681

(cherry picked from commit 7c466395c4)
(cherry picked from commit 922f4b1760)
2023-09-03 16:04:18 +02:00
Peter-Josef Meisch 7d9e6a5a2a Fix search_after field values (#2679)
Closes #2678

(cherry picked from commit 9adc4d2b36)
(cherry picked from commit 4614c62bb5)
2023-08-28 21:19:48 +02:00
Mark Paluch b34ed6fd2b After release cleanups.
See #2629
2023-08-18 10:46:31 +02:00
Mark Paluch ff4e07d350 Prepare next development iteration.
See #2629
2023-08-18 10:46:29 +02:00
7 changed files with 243 additions and 68 deletions
+4 -4
View File
@@ -5,12 +5,12 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>5.0.9</version>
<version>5.0.10</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>3.0.9</version>
<version>3.0.10</version>
</parent>
<name>Spring Data Elasticsearch</name>
@@ -18,10 +18,10 @@
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<properties>
<springdata.commons>3.0.9</springdata.commons>
<springdata.commons>3.0.10</springdata.commons>
<!-- version of the RestHighLevelClient -->
<elasticsearch-rhlc>7.17.12</elasticsearch-rhlc>
<elasticsearch-rhlc>7.17.13</elasticsearch-rhlc>
<!-- version of the new ElasticsearchClient -->
<elasticsearch-java>8.5.3</elasticsearch-java>
@@ -15,15 +15,10 @@
*/
package org.springframework.data.elasticsearch.client.elc;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.searchType;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.slices;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.time;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.timeStringMs;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.toFloat;
import static org.springframework.util.CollectionUtils.isEmpty;
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
import static org.springframework.util.CollectionUtils.*;
import co.elastic.clients.elasticsearch._types.Conflicts;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.InlineScript;
import co.elastic.clients.elasticsearch._types.OpType;
import co.elastic.clients.elasticsearch._types.SortOptions;
@@ -37,18 +32,7 @@ import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch._types.query_dsl.Like;
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.ClosePointInTimeRequest;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.DeleteRequest;
import co.elastic.clients.elasticsearch.core.GetRequest;
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.MgetRequest;
import co.elastic.clients.elasticsearch.core.MsearchRequest;
import co.elastic.clients.elasticsearch.core.OpenPointInTimeRequest;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.UpdateByQueryRequest;
import co.elastic.clients.elasticsearch.core.UpdateRequest;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
@@ -58,17 +42,8 @@ import co.elastic.clients.elasticsearch.core.msearch.MultisearchBody;
import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.Rescore;
import co.elastic.clients.elasticsearch.core.search.SourceConfig;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.elasticsearch.indices.GetAliasRequest;
import co.elastic.clients.elasticsearch.indices.GetIndexRequest;
import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsRequest;
import co.elastic.clients.elasticsearch.indices.GetMappingRequest;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.elasticsearch.indices.PutMappingRequest;
import co.elastic.clients.elasticsearch.indices.RefreshRequest;
import co.elastic.clients.elasticsearch.indices.UpdateAliasesRequest;
import co.elastic.clients.elasticsearch.indices.update_aliases.Action;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.JsonpDeserializer;
@@ -85,7 +60,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -107,19 +81,7 @@ import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.BaseQuery;
import org.springframework.data.elasticsearch.core.query.BulkOptions;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.GeoDistanceOrder;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
import org.springframework.data.elasticsearch.core.query.Order;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
import org.springframework.data.elasticsearch.core.query.ScriptData;
import org.springframework.data.elasticsearch.core.query.SourceFilter;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
import org.springframework.data.elasticsearch.core.reindex.Remote;
import org.springframework.data.elasticsearch.support.DefaultStringObjectMap;
@@ -918,7 +880,7 @@ class RequestConverter {
.docAsUpsert(query.getDocAsUpsert()) //
.ifSeqNo(query.getIfSeqNo() != null ? Long.valueOf(query.getIfSeqNo()) : null) //
.ifPrimaryTerm(query.getIfPrimaryTerm() != null ? Long.valueOf(query.getIfPrimaryTerm()) : null) //
.refresh(TypeUtils.refresh(refreshPolicy)) //
.refresh(query.getRefreshPolicy() != null ? refresh(query.getRefreshPolicy()) : refresh(refreshPolicy)) //
.retryOnConflict(query.getRetryOnConflict()) //
;
@@ -1121,8 +1083,7 @@ class RequestConverter {
}
if (!isEmpty(query.getSearchAfter())) {
bb.searchAfter(query.getSearchAfter().stream().map(it -> FieldValue.of(it.toString()))
.collect(Collectors.toList()));
bb.searchAfter(query.getSearchAfter().stream().map(TypeUtils::toFieldValue).toList());
}
query.getRescorerQueries().forEach(rescorerQuery -> bb.rescore(getRescore(rescorerQuery)));
@@ -1261,8 +1222,7 @@ class RequestConverter {
}
if (!isEmpty(query.getSearchAfter())) {
builder.searchAfter(
query.getSearchAfter().stream().map(it -> FieldValue.of(it.toString())).collect(Collectors.toList()));
builder.searchAfter(query.getSearchAfter().stream().map(TypeUtils::toFieldValue).toList());
}
query.getRescorerQueries().forEach(rescorerQuery -> builder.rescore(getRescore(rescorerQuery)));
@@ -192,7 +192,8 @@ class SearchDocumentResponseBuilder {
var phraseSuggestOptions = phraseSuggest.options();
List<PhraseSuggestion.Entry.Option> options = new ArrayList<>();
phraseSuggestOptions.forEach(optionES -> options
.add(new PhraseSuggestion.Entry.Option(optionES.text(), optionES.highlighted(), null, null)));
.add(new PhraseSuggestion.Entry.Option(optionES.text(), optionES.highlighted(), optionES.score(),
optionES.collateMatch())));
entries.add(new PhraseSuggestion.Entry(phraseSuggest.text(), phraseSuggest.offset(), phraseSuggest.length(),
options, null));
});
@@ -24,6 +24,7 @@ import co.elastic.clients.elasticsearch.core.search.HighlighterOrder;
import co.elastic.clients.elasticsearch.core.search.HighlighterTagsSchema;
import co.elastic.clients.elasticsearch.core.search.HighlighterType;
import co.elastic.clients.elasticsearch.core.search.ScoreMode;
import co.elastic.clients.json.JsonData;
import java.time.Duration;
@@ -127,6 +128,40 @@ final class TypeUtils {
}
}
@Nullable
static FieldValue toFieldValue(@Nullable Object fieldValue) {
if (fieldValue == null) {
return FieldValue.NULL;
}
if (fieldValue instanceof Boolean b) {
return b ? FieldValue.TRUE : FieldValue.FALSE;
}
if (fieldValue instanceof String s) {
return FieldValue.of(s);
}
if (fieldValue instanceof Long l) {
return FieldValue.of(l);
}
if (fieldValue instanceof Integer i) {
return FieldValue.of((long) i);
}
if (fieldValue instanceof Double d) {
return FieldValue.of(d);
}
if (fieldValue instanceof Float f) {
return FieldValue.of((double) f);
}
return FieldValue.of(JsonData.of(fieldValue));
}
@Nullable
static GeoDistanceType geoDistanceType(GeoDistanceOrder.DistanceType distanceType) {
+2 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 5.0.9 (2022.0.9)
Spring Data Elasticsearch 5.0.10 (2022.0.10)
Copyright (c) [2013-2021] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -25,3 +25,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
@@ -0,0 +1,111 @@
/*
* Copyright 2023 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.client.elc;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import java.util.ArrayList;
import java.util.List;
import org.assertj.core.api.SoftAssertions;
import org.json.JSONException;
import org.junit.jupiter.api.Test;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
/**
* Tests for the factory class to create {@link SearchDocumentResponse} instances.
*
* @author Sébastien Comeau
* @since 5.2
*/
class SearchDocumentResponseBuilderUnitTests {
private JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper();
@Test // #2681
void shouldGetPhraseSuggestion() throws JSONException {
// arrange
final var hitsMetadata = new HitsMetadata.Builder<EntityAsMap>()
.total(total -> total
.value(0)
.relation(TotalHitsRelation.Eq))
.hits(new ArrayList<>())
.build();
final var suggestionTest = new Suggestion.Builder<EntityAsMap>()
.phrase(phrase -> phrase
.text("National")
.offset(0)
.length(8)
.options(option -> option
.text("nations")
.highlighted("highlighted-nations")
.score(0.11480146)
.collateMatch(false))
.options(option -> option
.text("national")
.highlighted("highlighted-national")
.score(0.08063514)
.collateMatch(false)))
.build();
final var sortProperties = ImmutableMap.<String, List<Suggestion<EntityAsMap>>> builder()
.put("suggestionTest", ImmutableList.of(suggestionTest))
.build();
// act
final var actual = SearchDocumentResponseBuilder.from(hitsMetadata, null, null, null, sortProperties, null,
jsonpMapper);
// assert
SoftAssertions softly = new SoftAssertions();
softly.assertThat(actual).isNotNull();
softly.assertThat(actual.getSuggest()).isNotNull();
softly.assertThat(actual.getSuggest().getSuggestions()).isNotNull().hasSize(1);
final var actualSuggestion = actual.getSuggest().getSuggestions().get(0);
softly.assertThat(actualSuggestion.getName()).isEqualTo("suggestionTest");
softly.assertThat(actualSuggestion.getEntries()).isNotNull().hasSize(1);
final var actualEntry = actualSuggestion.getEntries().get(0);
softly.assertThat(actualEntry).isNotNull();
softly.assertThat(actualEntry.getText()).isEqualTo("National");
softly.assertThat(actualEntry.getOffset()).isEqualTo(0);
softly.assertThat(actualEntry.getLength()).isEqualTo(8);
softly.assertThat(actualEntry.getOptions()).isNotNull().hasSize(2);
final var actualOption1 = actualEntry.getOptions().get(0);
softly.assertThat(actualOption1.getText()).isEqualTo("nations");
softly.assertThat(actualOption1.getHighlighted()).isEqualTo("highlighted-nations");
softly.assertThat(actualOption1.getScore()).isEqualTo(0.11480146);
softly.assertThat(actualOption1.getCollateMatch()).isEqualTo(false);
final var actualOption2 = actualEntry.getOptions().get(1);
softly.assertThat(actualOption2.getText()).isEqualTo("national");
softly.assertThat(actualOption2.getHighlighted()).isEqualTo("highlighted-national");
softly.assertThat(actualOption2.getScore()).isEqualTo(0.08063514);
softly.assertThat(actualOption2.getCollateMatch()).isEqualTo(false);
softly.assertAll();
}
}
@@ -62,7 +62,7 @@ public abstract class SearchAfterIntegrationTests {
@Test
@Order(java.lang.Integer.MAX_VALUE)
void cleanup() {
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + '*')).delete();
}
@Test // #1143
@@ -85,11 +85,11 @@ public abstract class SearchAfterIntegrationTests {
query.setSearchAfter(searchAfter);
SearchHits<Entity> searchHits = operations.search(query, Entity.class);
if (searchHits.getSearchHits().size() == 0) {
if (searchHits.getSearchHits().isEmpty()) {
break;
}
foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList()));
searchAfter = searchHits.getSearchHit((int) (searchHits.getSearchHits().size() - 1)).getSortValues();
foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).toList());
searchAfter = searchHits.getSearchHit(searchHits.getSearchHits().size() - 1).getSortValues();
if (++loop > 10) {
fail("loop not terminating");
@@ -99,16 +99,69 @@ public abstract class SearchAfterIntegrationTests {
assertThat(foundEntities).containsExactlyElementsOf(entities);
}
@Test // #2678
@DisplayName("should be able to handle different search after type values including null")
void shouldBeAbleToHandleDifferentSearchAfterTypeValuesIncludingNull() {
List<Entity> entities = IntStream.rangeClosed(1, 10)
.mapToObj(i -> {
var message = (i % 2 == 0) ? null : "message " + i;
var value = (i % 3 == 0) ? null : (long) i;
return new Entity((long) i, message, value);
})
.collect(Collectors.toList());
operations.save(entities);
Query query = Query.findAll();
query.setPageable(PageRequest.of(0, 3));
query.addSort(Sort.by(Sort.Direction.ASC, "id"));
query.addSort(Sort.by(Sort.Direction.ASC, "keyword"));
query.addSort(Sort.by(Sort.Direction.ASC, "value"));
List<Object> searchAfter = null;
List<Entity> foundEntities = new ArrayList<>();
int loop = 0;
do {
query.setSearchAfter(searchAfter);
SearchHits<Entity> searchHits = operations.search(query, Entity.class);
if (searchHits.getSearchHits().isEmpty()) {
break;
}
foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).toList());
searchAfter = searchHits.getSearchHit(searchHits.getSearchHits().size() - 1).getSortValues();
if (++loop > 10) {
fail("loop not terminating");
}
} while (true);
assertThat(foundEntities).containsExactlyElementsOf(entities);
}
@SuppressWarnings("unused")
@Document(indexName = "#{@indexNameProvider.indexName()}")
private static class Entity {
@Nullable
@Id private Long id;
@Nullable
@Field(type = FieldType.Text) private String message;
@Field(type = FieldType.Keyword) private String keyword;
public Entity(@Nullable Long id, @Nullable String message) {
@Nullable
@Field(type = FieldType.Long) private Long value;
public Entity() {}
public Entity(@Nullable Long id, @Nullable String keyword) {
this.id = id;
this.message = message;
this.keyword = keyword;
}
public Entity(@Nullable Long id, @Nullable String keyword, @Nullable Long value) {
this.id = id;
this.keyword = keyword;
this.value = value;
}
@Nullable
@@ -121,30 +174,44 @@ public abstract class SearchAfterIntegrationTests {
}
@Nullable
public String getMessage() {
return message;
public String getKeyword() {
return keyword;
}
public void setMessage(@Nullable String message) {
this.message = message;
public void setKeyword(@Nullable String keyword) {
this.keyword = keyword;
}
@Nullable
public Long getValue() {
return value;
}
public void setValue(@Nullable Long value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Entity entity))
if (o == null || getClass() != o.getClass())
return false;
Entity entity = (Entity) o;
if (!Objects.equals(id, entity.id))
return false;
return Objects.equals(message, entity.message);
if (!Objects.equals(keyword, entity.keyword))
return false;
return Objects.equals(value, entity.value);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (message != null ? message.hashCode() : 0);
result = 31 * result + (keyword != null ? keyword.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
return result;
}
}