mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-28 14:52:20 +00:00
Option to add docvalue_fields to a search query.
Original Pull Request #2446 #Closes 2316
This commit is contained in:
parent
0971acfe25
commit
6805fff1fa
@ -31,6 +31,7 @@ import co.elastic.clients.elasticsearch._types.mapping.Property;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.RuntimeField;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
|
||||
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.Like;
|
||||
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
|
||||
import co.elastic.clients.elasticsearch.core.*;
|
||||
@ -1298,6 +1299,12 @@ class RequestConverter {
|
||||
// noinspection unchecked
|
||||
builder.indicesBoost(boosts);
|
||||
}
|
||||
|
||||
if (!isEmpty(query.getDocValueFields())) {
|
||||
builder.docvalueFields(query.getDocValueFields().stream() //
|
||||
.map(docValueField -> FieldAndFormat.of(b -> b.field(docValueField.field()).format(docValueField.format())))
|
||||
.toList());
|
||||
}
|
||||
}
|
||||
|
||||
private Rescore getRescore(RescorerQuery rescorerQuery) {
|
||||
@ -1554,14 +1561,13 @@ class RequestConverter {
|
||||
|
||||
return SearchTemplateRequest.of(builder -> {
|
||||
builder //
|
||||
.allowNoIndices(query.getAllowNoIndices()) //
|
||||
.explain(query.getExplain()) //
|
||||
.id(query.getId()) //
|
||||
.index(Arrays.asList(index.getIndexNames())) //
|
||||
.preference(query.getPreference()) //
|
||||
.routing(query.getRoute()) //
|
||||
.searchType(searchType(query.getSearchType()))
|
||||
.source(query.getSource()) //
|
||||
.allowNoIndices(query.getAllowNoIndices()) //
|
||||
.explain(query.getExplain()) //
|
||||
.id(query.getId()) //
|
||||
.index(Arrays.asList(index.getIndexNames())) //
|
||||
.preference(query.getPreference()) //
|
||||
.routing(query.getRoute()) //
|
||||
.searchType(searchType(query.getSearchType())).source(query.getSource()) //
|
||||
;
|
||||
|
||||
var expandWildcards = query.getExpandWildcards();
|
||||
@ -1577,7 +1583,7 @@ class RequestConverter {
|
||||
Function<Map.Entry<String, Object>, String> keyMapper = Map.Entry::getKey;
|
||||
Function<Map.Entry<String, Object>, JsonData> valueMapper = entry -> JsonData.of(entry.getValue(), jsonpMapper);
|
||||
Map<String, JsonData> params = query.getParams().entrySet().stream()
|
||||
.collect(Collectors.toMap(keyMapper, valueMapper));
|
||||
.collect(Collectors.toMap(keyMapper, valueMapper));
|
||||
builder.params(params);
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,9 @@ public class BaseQuery implements Query {
|
||||
@Nullable protected PointInTime pointInTime;
|
||||
private boolean queryIsUpdatedByConverter = false;
|
||||
@Nullable private Integer reactiveBatchSize = null;
|
||||
@Nullable private Boolean allowNoIndices = null;
|
||||
|
||||
@Nullable private Boolean allowNoIndices = null;
|
||||
private EnumSet<IndicesOptions.WildcardStates> expandWildcards;
|
||||
private List<DocValueField> docValueFields = new ArrayList<>();
|
||||
|
||||
public BaseQuery() {}
|
||||
|
||||
@ -114,6 +114,7 @@ public class BaseQuery implements Query {
|
||||
this.reactiveBatchSize = builder.getReactiveBatchSize();
|
||||
this.allowNoIndices = builder.getAllowNoIndices();
|
||||
this.expandWildcards = builder.getExpandWildcards();
|
||||
this.docValueFields = builder.getDocValueFields();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -524,4 +525,22 @@ public class BaseQuery implements Query {
|
||||
public EnumSet<IndicesOptions.WildcardStates> getExpandWildcards() {
|
||||
return expandWildcards;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
@Override
|
||||
public List<DocValueField> getDocValueFields() {
|
||||
return docValueFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
public void setDocValueFields(List<DocValueField> docValueFields) {
|
||||
|
||||
Assert.notNull(docValueFields, "getDocValueFields must not be null");
|
||||
|
||||
this.docValueFields = docValueFields;
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
private EnumSet<IndicesOptions.WildcardStates> expandWildcards = EnumSet.noneOf(IndicesOptions.WildcardStates.class);
|
||||
|
||||
@Nullable Integer reactiveBatchSize;
|
||||
private final List<DocValueField> docValueFields = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
public Sort getSort() {
|
||||
@ -218,6 +219,13 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return expandWildcards;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
public List<DocValueField> getDocValueFields() {
|
||||
return docValueFields;
|
||||
}
|
||||
|
||||
public SELF withPageable(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
return self();
|
||||
@ -423,6 +431,18 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
public SELF withDocValueFields(List<DocValueField> docValueFields) {
|
||||
|
||||
Assert.notNull(docValueFields, "docValueFields must not be null");
|
||||
|
||||
this.docValueFields.clear();
|
||||
this.docValueFields.addAll(docValueFields);
|
||||
return self();
|
||||
}
|
||||
|
||||
public abstract Q build();
|
||||
|
||||
private SELF self() {
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.core.query;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Record defining a docvalue_field to be used in a query.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.1
|
||||
*/
|
||||
public record DocValueField(String field, @Nullable String format) {
|
||||
public DocValueField {
|
||||
Assert.notNull(field, "field must not be null");
|
||||
}
|
||||
|
||||
public DocValueField(String field) {
|
||||
this(field, null);
|
||||
}
|
||||
}
|
@ -472,8 +472,14 @@ public interface Query {
|
||||
EnumSet<IndicesOptions.WildcardStates> getExpandWildcards();
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
*/
|
||||
* @return a possible empty list of docvalue_field values to be set on the query.
|
||||
* @since 5.1
|
||||
*/
|
||||
List<DocValueField> getDocValueFields();
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
*/
|
||||
enum SearchType {
|
||||
QUERY_THEN_FETCH, DFS_QUERY_THEN_FETCH
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
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.core.convert.MappingElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.core.query.DocValueField;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
class RequestConverterTest {
|
||||
|
||||
private static final SimpleElasticsearchMappingContext mappingContext = new SimpleElasticsearchMappingContext();
|
||||
private static final MappingElasticsearchConverter converter = new MappingElasticsearchConverter(mappingContext);
|
||||
private JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper();
|
||||
private RequestConverter requestConverter = new RequestConverter(converter, jsonpMapper);
|
||||
|
||||
@Test // #2316
|
||||
@DisplayName("should add docvalue_fields")
|
||||
void shouldAddDocvalueFields() {
|
||||
|
||||
var docValueFields = List.of( //
|
||||
new DocValueField("field1"), //
|
||||
new DocValueField("field2", "format2") //
|
||||
);
|
||||
// doesn't matter what type of query is used, the relevant part for docvalue_fields is in the base builder.
|
||||
var query = StringQuery.builder("""
|
||||
{
|
||||
"match_all":{}
|
||||
}
|
||||
""") //
|
||||
.withDocValueFields(docValueFields) //
|
||||
.build();
|
||||
|
||||
var searchRequest = requestConverter.searchRequest(query, SampleEntity.class, IndexCoordinates.of("foo"), true);
|
||||
|
||||
var fieldAndFormats = searchRequest.docvalueFields();
|
||||
assertThat(fieldAndFormats).hasSize(2);
|
||||
assertThat(fieldAndFormats.get(0).field()).isEqualTo("field1");
|
||||
assertThat(fieldAndFormats.get(0).format()).isNull();
|
||||
assertThat(fieldAndFormats.get(1).field()).isEqualTo("field2");
|
||||
assertThat(fieldAndFormats.get(1).format()).isEqualTo("format2");
|
||||
}
|
||||
|
||||
@Document(indexName = "does-not-matter")
|
||||
static class SampleEntity {
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text) private String text;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user