Skip to content

Commit

Permalink
Add support for parameters for runtime fields.
Browse files Browse the repository at this point in the history
Original Pull Request #2677
Closes #2303
  • Loading branch information
sothawo authored Aug 26, 2023
1 parent ed89843 commit 922c7dd
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public record FailureDetails(Integer status, String errorMessage) {

The classes `org.springframework.data.elasticsearch.core.RuntimeField` and `org.springframework.data.elasticsearch.core.query.ScriptType` have been moved to the subpackage `org.springframework.data.elasticsearch.core.query`.

The `type` parameter of the `ScriptData` constructir is not nullable any longer.
The `type` parameter of the `ScriptData` constructor is not nullable any longer.

[[elasticsearch-migration-guide-5.1-5.2.deprecations]]
== Deprecations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.RefreshPolicy;
import org.springframework.data.elasticsearch.core.query.ScriptType;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.*;
Expand Down Expand Up @@ -1237,14 +1236,23 @@ public MsearchRequest searchMsearchRequest(
Map<String, RuntimeField> runtimeMappings = new HashMap<>();
query.getRuntimeFields().forEach(runtimeField -> {
RuntimeField esRuntimeField = RuntimeField.of(rt -> {
RuntimeField.Builder builder = rt
RuntimeField.Builder rfb = rt
.type(RuntimeFieldType._DESERIALIZER.parse(runtimeField.getType()));
String script = runtimeField.getScript();

if (script != null) {
builder = builder.script(s -> s.inline(is -> is.source(script)));
rfb
.script(s -> s
.inline(is -> {
is.source(script);

if (runtimeField.getParams() != null) {
is.params(TypeUtils.paramsMap(runtimeField.getParams()));
}
return is;
}));
}
return builder;
return rfb;
});
runtimeMappings.put(runtimeField.getName(), esRuntimeField);
});
Expand Down Expand Up @@ -1393,14 +1401,23 @@ private <T> void prepareSearchRequest(Query query, @Nullable String routing, @Nu

Map<String, RuntimeField> runtimeMappings = new HashMap<>();
query.getRuntimeFields()
.forEach(runtimeField -> runtimeMappings.put(runtimeField.getName(), RuntimeField.of(runtimeFieldBuilder -> {
runtimeFieldBuilder.type(RuntimeFieldType._DESERIALIZER.parse(runtimeField.getType()));
.forEach(runtimeField -> runtimeMappings.put(runtimeField.getName(), RuntimeField.of(rfb -> {
rfb.type(RuntimeFieldType._DESERIALIZER.parse(runtimeField.getType()));
String script = runtimeField.getScript();

if (script != null) {
runtimeFieldBuilder.script(s -> s.inline(is -> is.source(script)));
rfb
.script(s -> s
.inline(is -> {
is.source(script);

if (runtimeField.getParams() != null) {
is.params(TypeUtils.paramsMap(runtimeField.getParams()));
}
return is;
}));
}
return runtimeFieldBuilder;

return rfb;
})));
builder.runtimeMappings(runtimeMappings);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,37 @@
import co.elastic.clients.elasticsearch._types.*;
import co.elastic.clients.elasticsearch._types.mapping.FieldType;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.core.search.*;
import co.elastic.clients.elasticsearch.core.search.BoundaryScanner;
import co.elastic.clients.elasticsearch.core.search.HighlighterEncoder;
import co.elastic.clients.elasticsearch.core.search.HighlighterFragmenter;
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.elasticsearch.indices.IndexSettings;
import co.elastic.clients.json.JsonData;

import java.io.StringReader;
import java.time.Duration;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.RefreshPolicy;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.core.query.GeoDistanceOrder;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndicesOptions;
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.UpdateResponse;
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
* Utility to handle new Elasticsearch client type values.
Expand Down Expand Up @@ -438,4 +452,18 @@ static IndexSettings indexSettings(@Nullable Map<String, Object> settings) {
return settings != null ? IndexSettings.of(b -> b.withJson(new StringReader(Document.from(settings).toJson())))
: null;
}

/**
* @since 5.2
*/
static Map<String, JsonData> paramsMap(Map<String, Object> params) {

Assert.notNull(params, "params must not be null");

Map<String, JsonData> mappedParams = new LinkedHashMap<>();
params.forEach((key, value) -> {
mappedParams.put(key, JsonData.of(value));
});
return mappedParams;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,34 @@
public class RuntimeField {

private final String name;
/**
* the type of the runtime field (long, keyword, etc.)
*/
private final String type;
@Nullable private final String script;

/**
* @since 5.2
*/
@Nullable Map<String, Object> params;

public RuntimeField(String name, String type) {
this(name, type, null);
this(name, type, null, null);
}

public RuntimeField(String name, String type, @Nullable String script) {
public RuntimeField(String name, String type, String script) {
this(name, type, script, null);
}

public RuntimeField(String name, String type, @Nullable String script, @Nullable Map<String, Object> params) {

Assert.notNull(name, "name must not be null");
Assert.notNull(type, "type must not be null");

this.name = name;
this.type = type;
this.script = script;
this.params = params;
}

public String getName() {
Expand Down Expand Up @@ -78,4 +91,12 @@ public String getType() {
public @Nullable String getScript() {
return script;
}

/**
* @since 5.2
*/
@Nullable
public Map<String, Object> getParams() {
return params;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.assertj.core.api.Assertions.*;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -251,6 +252,29 @@ private void insert(String id, String description, double price) {
operations.save(entity);
}

@Test // #2303
@DisplayName("should use parameters for runtime fields in search queries")
void shouldUseParametersForRuntimeFieldsInSearchQueries() {

insert("1", "item 1", 80.0);
insert("2", "item 2", 90.0);

RuntimeField runtimeField = new RuntimeField(
"priceWithTax",
"double",
"emit(doc['price'].value * params.tax)",
Map.of("tax", 1.19)
);
var query = CriteriaQuery.builder(
Criteria.where("priceWithTax").greaterThan(100.0))
.withRuntimeFields(List.of(runtimeField))
.build();

var searchHits = operations.search(query, SomethingToBuy.class);

assertThat(searchHits).hasSize(1);
}

@SuppressWarnings("unused")
@Document(indexName = "#{@indexNameProvider.indexName()}-something-to-by")
private static class SomethingToBuy {
Expand Down Expand Up @@ -386,13 +410,13 @@ SearchHits<SAREntity> findByValue(Integer value,

@org.springframework.data.elasticsearch.annotations.Query("""
{
"term": {
"value": {
"value": "?0"
}
}
}
""")
"term": {
"value": {
"value": "?0"
}
}
}
""")
SearchHits<SAREntity> findWithScriptedFields(Integer value,
org.springframework.data.elasticsearch.core.query.ScriptedField scriptedField1,
org.springframework.data.elasticsearch.core.query.ScriptedField scriptedField2);
Expand All @@ -401,13 +425,13 @@ SearchHits<SAREntity> findWithScriptedFields(Integer value,

@org.springframework.data.elasticsearch.annotations.Query("""
{
"term": {
"value": {
"value": "?0"
}
}
}
""")
"term": {
"value": {
"value": "?0"
}
}
}
""")
SearchHits<SAREntity> findWithRuntimeFields(Integer value, RuntimeField runtimeField1, RuntimeField runtimeField2);
}
}

0 comments on commit 922c7dd

Please sign in to comment.