mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-29 15:22:11 +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.RuntimeField;
|
||||||
import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
|
import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType;
|
||||||
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
|
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._types.query_dsl.Like;
|
||||||
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
|
import co.elastic.clients.elasticsearch.cluster.HealthRequest;
|
||||||
import co.elastic.clients.elasticsearch.core.*;
|
import co.elastic.clients.elasticsearch.core.*;
|
||||||
@ -1298,6 +1299,12 @@ class RequestConverter {
|
|||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
builder.indicesBoost(boosts);
|
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) {
|
private Rescore getRescore(RescorerQuery rescorerQuery) {
|
||||||
@ -1560,8 +1567,7 @@ class RequestConverter {
|
|||||||
.index(Arrays.asList(index.getIndexNames())) //
|
.index(Arrays.asList(index.getIndexNames())) //
|
||||||
.preference(query.getPreference()) //
|
.preference(query.getPreference()) //
|
||||||
.routing(query.getRoute()) //
|
.routing(query.getRoute()) //
|
||||||
.searchType(searchType(query.getSearchType()))
|
.searchType(searchType(query.getSearchType())).source(query.getSource()) //
|
||||||
.source(query.getSource()) //
|
|
||||||
;
|
;
|
||||||
|
|
||||||
var expandWildcards = query.getExpandWildcards();
|
var expandWildcards = query.getExpandWildcards();
|
||||||
|
@ -78,9 +78,9 @@ public class BaseQuery implements Query {
|
|||||||
@Nullable protected PointInTime pointInTime;
|
@Nullable protected PointInTime pointInTime;
|
||||||
private boolean queryIsUpdatedByConverter = false;
|
private boolean queryIsUpdatedByConverter = false;
|
||||||
@Nullable private Integer reactiveBatchSize = null;
|
@Nullable private Integer reactiveBatchSize = null;
|
||||||
@Nullable private Boolean allowNoIndices = null;
|
@Nullable private Boolean allowNoIndices = null;
|
||||||
|
|
||||||
private EnumSet<IndicesOptions.WildcardStates> expandWildcards;
|
private EnumSet<IndicesOptions.WildcardStates> expandWildcards;
|
||||||
|
private List<DocValueField> docValueFields = new ArrayList<>();
|
||||||
|
|
||||||
public BaseQuery() {}
|
public BaseQuery() {}
|
||||||
|
|
||||||
@ -114,6 +114,7 @@ public class BaseQuery implements Query {
|
|||||||
this.reactiveBatchSize = builder.getReactiveBatchSize();
|
this.reactiveBatchSize = builder.getReactiveBatchSize();
|
||||||
this.allowNoIndices = builder.getAllowNoIndices();
|
this.allowNoIndices = builder.getAllowNoIndices();
|
||||||
this.expandWildcards = builder.getExpandWildcards();
|
this.expandWildcards = builder.getExpandWildcards();
|
||||||
|
this.docValueFields = builder.getDocValueFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -524,4 +525,22 @@ public class BaseQuery implements Query {
|
|||||||
public EnumSet<IndicesOptions.WildcardStates> getExpandWildcards() {
|
public EnumSet<IndicesOptions.WildcardStates> getExpandWildcards() {
|
||||||
return expandWildcards;
|
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);
|
private EnumSet<IndicesOptions.WildcardStates> expandWildcards = EnumSet.noneOf(IndicesOptions.WildcardStates.class);
|
||||||
|
|
||||||
@Nullable Integer reactiveBatchSize;
|
@Nullable Integer reactiveBatchSize;
|
||||||
|
private final List<DocValueField> docValueFields = new ArrayList<>();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Sort getSort() {
|
public Sort getSort() {
|
||||||
@ -218,6 +219,13 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
|||||||
return expandWildcards;
|
return expandWildcards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public List<DocValueField> getDocValueFields() {
|
||||||
|
return docValueFields;
|
||||||
|
}
|
||||||
|
|
||||||
public SELF withPageable(Pageable pageable) {
|
public SELF withPageable(Pageable pageable) {
|
||||||
this.pageable = pageable;
|
this.pageable = pageable;
|
||||||
return self();
|
return self();
|
||||||
@ -423,6 +431,18 @@ public abstract class BaseQueryBuilder<Q extends BaseQuery, SELF extends BaseQue
|
|||||||
return self();
|
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();
|
public abstract Q build();
|
||||||
|
|
||||||
private SELF self() {
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -471,6 +471,12 @@ public interface Query {
|
|||||||
*/
|
*/
|
||||||
EnumSet<IndicesOptions.WildcardStates> getExpandWildcards();
|
EnumSet<IndicesOptions.WildcardStates> getExpandWildcards();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a possible empty list of docvalue_field values to be set on the query.
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
List<DocValueField> getDocValueFields();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
|
@ -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