diff --git a/CHANGELOG.md b/CHANGELOG.md index ad8be5bda9..6e804fbb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added - Added support for "smartcn" analyzer ([#605](https://github.com/opensearch-project/opensearch-java/pull/605)) +- Added support for "script_fields" in multi search request ([#632](https://github.com/opensearch-project/opensearch-java/pull/632)) ### Dependencies diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/core/msearch/MultisearchBody.java b/java-client/src/main/java/org/opensearch/client/opensearch/core/msearch/MultisearchBody.java index f58b987ad2..e03538d484 100644 --- a/java-client/src/main/java/org/opensearch/client/opensearch/core/msearch/MultisearchBody.java +++ b/java-client/src/main/java/org/opensearch/client/opensearch/core/msearch/MultisearchBody.java @@ -32,6 +32,7 @@ package org.opensearch.client.opensearch.core.msearch; +import org.opensearch.client.opensearch._types.ScriptField; import org.opensearch.client.opensearch._types.SortOptions; import org.opensearch.client.opensearch._types.aggregations.Aggregation; import org.opensearch.client.opensearch._types.query_dsl.Query; @@ -96,6 +97,8 @@ public class MultisearchBody implements JsonpSerializable { @Nullable private SourceConfig source; + private final Map scriptFields; + // --------------------------------------------------------------------------------------------- private MultisearchBody(Builder builder) { @@ -113,7 +116,7 @@ private MultisearchBody(Builder builder) { this.suggest = builder.suggest; this.highlight = builder.highlight; this.source = builder.source; - + this.scriptFields = ApiTypeHelper.unmodifiable(builder.scriptFields); } public static MultisearchBody of(Function> fn) { @@ -221,6 +224,10 @@ public final SourceConfig source() { return this.source; } + public final Map scriptFields() { + return this.scriptFields; + } + /** * Serialize this object to JSON. */ @@ -316,6 +323,18 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { } + if (ApiTypeHelper.isDefined(this.scriptFields)) { + generator.writeKey("script_fields"); + generator.writeStartObject(); + for (Map.Entry item0 : this.scriptFields.entrySet()) { + generator.writeKey(item0.getKey()); + item0.getValue().serialize(generator, mapper); + + } + generator.writeEnd(); + + } + } // --------------------------------------------------------------------------------------------- @@ -364,6 +383,8 @@ public static class Builder extends ObjectBuilderBase implements ObjectBuilder scriptFields; + /** * API name: {@code aggregations} @@ -571,6 +592,29 @@ public final Builder source(Function map) { + this.scriptFields = _mapPutAll(this.scriptFields, map); + return this; + } + + /** + * API name: {@code script_fields} + */ + public final Builder scriptFields(String key, ScriptField value) { + this.scriptFields = _mapPut(this.scriptFields, key, value); + return this; + } + + /** + * API name: {@code script_fields} + */ + public final Builder scriptFields(String key, Function> fn) { + return scriptFields(key, fn.apply(new ScriptField.Builder()).build()); + } + /** * Builds a {@link MultisearchBody}. * @@ -609,6 +653,8 @@ protected static void setupMultisearchBodyDeserializer(ObjectDeserializer response = sendMSearchRequest(index, List.of(sortedItemsQuery)); + assertEquals(1, response.responses().size()); + var hits = response.responses().get(0).result().hits().hits(); + assertEquals(3, hits.size()); + assertNull(hits.get(0).score()); + assertNull(hits.get(1).score()); + assertNull(hits.get(2).score()); + + Map scriptFields = new HashMap<>(); + scriptFields.put("quantity", new ScriptField.Builder().script(Script.of(s -> s.inline(new InlineScript.Builder() + .lang("painless") + .source("doc['quantity'].value + params.inc") + .params("inc", JsonData.of(1)) + .build()))) + .build()); + + + RequestItem requestItem = createMSearchQueryWithScriptFields("small", scriptFields); + + MsearchResponse responseWithScriptFields = sendMSearchRequest(index, List.of(requestItem)); + var hitsWithScriptFields = responseWithScriptFields.responses().get(0).result().hits().hits(); + assertEquals(2, hitsWithScriptFields.size()); + // validating that the quantity for small items is increased by 1 + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = mapper.readTree(hitsWithScriptFields.get(0).fields().get("quantity").toString()); + assertEquals(2, (int) mapper.treeToValue(node.get(0), int.class)); + + node = mapper.readTree(hitsWithScriptFields.get(1).fields().get("quantity").toString()); + assertEquals(3, (int) mapper.treeToValue(node.get(0), int.class)); + } + private void assertResponseSources(MultiSearchResponseItem response) { List> hitsWithHighlights = response.result().hits().hits(); @@ -198,6 +245,14 @@ private RequestItem createMSearchQuery(String itemSize) { return createMSearchQuery(itemSize, null, List.of()); } + private RequestItem createMSearchQueryWithScriptFields(String itemSize, Map scriptFields) { + return RequestItem.of(item -> item.header(header -> header) + .body(body -> body.query(createItemSizeSearchQuery(itemSize)) + .scriptFields(scriptFields) + ) + ); + } + private RequestItem createMSearchQueryWithHighlight(String itemSize) { return createMSearchQuery(itemSize, "size", List.of()); } diff --git a/samples/src/main/java/org/opensearch/client/samples/Search.java b/samples/src/main/java/org/opensearch/client/samples/Search.java index ccc1acb679..ea41bfc48c 100644 --- a/samples/src/main/java/org/opensearch/client/samples/Search.java +++ b/samples/src/main/java/org/opensearch/client/samples/Search.java @@ -47,7 +47,7 @@ * Run with: ./gradlew :samples:run -Dsamples.mainClass=Search */ public class Search { - private static final Logger LOGGER = LogManager.getLogger(IndexingBasics.class); + private static final Logger LOGGER = LogManager.getLogger(Search.class); private static OpenSearchClient client;