From 2d7b6b419f0c19407eaeeaeb3e92c99719761654 Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Wed, 3 Apr 2024 09:14:33 -0400 Subject: [PATCH] Add missed fields to MultisearchBody: seqNoPrimaryTerm, storedFields, explain, fields, indicesBoost Signed-off-by: Andriy Redko --- CHANGELOG.md | 1 + .../core/msearch/MultisearchBody.java | 259 +++++++++++++++++- .../AbstractMultiSearchRequestIT.java | 43 +++ 3 files changed, 302 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee8107917..21f24bb957 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ This section is for maintaining a changelog for all breaking changes for the cli ## [Unreleased 2.x] ### Added +- Add missed fields to MultisearchBody: seqNoPrimaryTerm, storedFields, explain, fields, indicesBoost ([#914](https://github.com/opensearch-project/opensearch-java/pull/914)) ### Dependencies - Bumps `io.github.classgraph:classgraph` from 4.8.161 to 4.8.165 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 812377e3a8..dde14f797e 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 @@ -46,7 +46,9 @@ 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.FieldAndFormat; import org.opensearch.client.opensearch._types.query_dsl.Query; +import org.opensearch.client.opensearch.core.SearchRequest.Builder; import org.opensearch.client.opensearch.core.search.Highlight; import org.opensearch.client.opensearch.core.search.SourceConfig; import org.opensearch.client.opensearch.core.search.Suggester; @@ -97,6 +99,18 @@ public class MultisearchBody implements JsonpSerializable { private final Map scriptFields; + @Nullable + private final Boolean seqNoPrimaryTerm; + + private final List storedFields; + + @Nullable + private final Boolean explain; + + private final List fields; + + private final List> indicesBoost; + // --------------------------------------------------------------------------------------------- private MultisearchBody(Builder builder) { @@ -115,6 +129,11 @@ private MultisearchBody(Builder builder) { this.highlight = builder.highlight; this.source = builder.source; this.scriptFields = ApiTypeHelper.unmodifiable(builder.scriptFields); + this.seqNoPrimaryTerm = builder.seqNoPrimaryTerm; + this.storedFields = ApiTypeHelper.unmodifiable(builder.storedFields); + this.explain = builder.explain; + this.fields = ApiTypeHelper.unmodifiable(builder.fields); + this.indicesBoost = ApiTypeHelper.unmodifiable(builder.indicesBoost); } public static MultisearchBody of(Function> fn) { @@ -226,6 +245,59 @@ public final Map scriptFields() { return this.scriptFields; } + /** + * If true, returns sequence number and primary term of the last modification of + * each hit. See Optimistic concurrency control. + *

+ * API name: {@code seq_no_primary_term} + */ + @Nullable + public final Boolean seqNoPrimaryTerm() { + return this.seqNoPrimaryTerm; + } + + /** + * List of stored fields to return as part of a hit. If no fields are specified, + * no stored fields are included in the response. If this field is specified, + * the _source parameter defaults to false. You can pass _source: true to return + * both source fields and stored fields in the search response. + *

+ * API name: {@code stored_fields} + */ + public final List storedFields() { + return this.storedFields; + } + + /** + * If true, returns detailed information about score computation as part of a + * hit. + *

+ * API name: {@code explain} + */ + @Nullable + public final Boolean explain() { + return this.explain; + } + + /** + * Array of wildcard (*) patterns. The request returns values for field names + * matching these patterns in the hits.fields property of the response. + *

+ * API name: {@code fields} + */ + public final List fields() { + return this.fields; + } + + /** + * Boosts the _score of documents from specified indices. + *

+ * API name: {@code indices_boost} + */ + public final List> indicesBoost() { + return this.indicesBoost; + } + /** * Serialize this object to JSON. */ @@ -333,6 +405,54 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { } + if (this.seqNoPrimaryTerm != null) { + generator.writeKey("seq_no_primary_term"); + generator.write(this.seqNoPrimaryTerm); + } + + if (ApiTypeHelper.isDefined(this.storedFields)) { + generator.writeKey("stored_fields"); + generator.writeStartArray(); + for (String item0 : this.storedFields) { + generator.write(item0); + + } + generator.writeEnd(); + } + + if (this.explain != null) { + generator.writeKey("explain"); + generator.write(this.explain); + + } + + if (ApiTypeHelper.isDefined(this.fields)) { + generator.writeKey("fields"); + generator.writeStartArray(); + for (FieldAndFormat item0 : this.fields) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + } + + if (ApiTypeHelper.isDefined(this.indicesBoost)) { + generator.writeKey("indices_boost"); + generator.writeStartArray(); + for (Map item0 : this.indicesBoost) { + generator.writeStartObject(); + if (item0 != null) { + for (Map.Entry item1 : item0.entrySet()) { + generator.writeKey(item1.getKey()); + generator.write(item1.getValue()); + + } + } + generator.writeEnd(); + + } + generator.writeEnd(); + } } // --------------------------------------------------------------------------------------------- @@ -383,6 +503,21 @@ public static class Builder extends ObjectBuilderBase implements ObjectBuilder scriptFields; + @Nullable + private Boolean seqNoPrimaryTerm; + + @Nullable + private List storedFields; + + @Nullable + private Boolean explain; + + @Nullable + private List fields; + + @Nullable + private List> indicesBoost; + /** * API name: {@code aggregations} *

@@ -612,6 +747,120 @@ public final Builder scriptFields(String key, Function + * API name: {@code seq_no_primary_term} + */ + public final Builder seqNoPrimaryTerm(@Nullable Boolean value) { + this.seqNoPrimaryTerm = value; + return this; + } + + /** + * List of stored fields to return as part of a hit. If no fields are specified, + * no stored fields are included in the response. If this field is specified, + * the _source parameter defaults to false. You can pass _source: true to return + * both source fields and stored fields in the search response. + *

+ * API name: {@code stored_fields} + *

+ * Adds all elements of list to storedFields. + */ + public final Builder storedFields(List list) { + this.storedFields = _listAddAll(this.storedFields, list); + return this; + } + + /** + * List of stored fields to return as part of a hit. If no fields are specified, + * no stored fields are included in the response. If this field is specified, + * the _source parameter defaults to false. You can pass _source: true to return + * both source fields and stored fields in the search response. + *

+ * API name: {@code stored_fields} + *

+ * Adds one or more values to storedFields. + */ + public final Builder storedFields(String value, String... values) { + this.storedFields = _listAdd(this.storedFields, value, values); + return this; + } + + /** + * If true, returns detailed information about score computation as part of a + * hit. + *

+ * API name: {@code explain} + */ + public final Builder explain(@Nullable Boolean value) { + this.explain = value; + return this; + } + + /** + * Array of wildcard (*) patterns. The request returns values for field names + * matching these patterns in the hits.fields property of the response. + *

+ * API name: {@code fields} + *

+ * Adds all elements of list to fields. + */ + public final Builder fields(List list) { + this.fields = _listAddAll(this.fields, list); + return this; + } + + /** + * Array of wildcard (*) patterns. The request returns values for field names + * matching these patterns in the hits.fields property of the response. + *

+ * API name: {@code fields} + *

+ * Adds one or more values to fields. + */ + public final Builder fields(FieldAndFormat value, FieldAndFormat... values) { + this.fields = _listAdd(this.fields, value, values); + return this; + } + + /** + * Array of wildcard (*) patterns. The request returns values for field names + * matching these patterns in the hits.fields property of the response. + *

+ * API name: {@code fields} + *

+ * Adds a value to fields using a builder lambda. + */ + public final Builder fields(Function> fn) { + return fields(fn.apply(new FieldAndFormat.Builder()).build()); + } + + /** + * Boosts the _score of documents from specified indices. + *

+ * API name: {@code indices_boost} + *

+ * Adds all elements of list to indicesBoost. + */ + public final Builder indicesBoost(List> list) { + this.indicesBoost = _listAddAll(this.indicesBoost, list); + return this; + } + + /** + * Boosts the _score of documents from specified indices. + *

+ * API name: {@code indices_boost} + *

+ * Adds one or more values to indicesBoost. + */ + public final Builder indicesBoost(Map value, Map... values) { + this.indicesBoost = _listAdd(this.indicesBoost, value, values); + return this; + } + /** * Builds a {@link MultisearchBody}. * @@ -651,7 +900,15 @@ protected static void setupMultisearchBodyDeserializer(ObjectDeserializer b.fields(FieldAndFormat.of(f -> f.field("name")))); + + MsearchResponse response = sendMSearchRequest(index, List.of(sortedItemsQuery)); + assertEquals(1, response.responses().size()); + assertEquals(3, response.responses().get(0).result().hits().hits().size()); + assertThat(response.responses().get(0).result().hits().hits().get(0).fields(), hasKey("name")); + assertThat(response.responses().get(0).result().hits().hits().get(1).fields(), hasKey("name")); + assertThat(response.responses().get(0).result().hits().hits().get(2).fields(), hasKey("name")); + } + + @Test + public void shouldReturnMultiSearchesStoredFields() throws Exception { + String index = "multiple_searches_request_stored_fields"; + createTestDocuments(index); + + RequestItem sortedItemsQuery = createMSearchFuzzyRequest(b -> b.storedFields("name")); + + MsearchResponse response = sendMSearchRequest(index, List.of(sortedItemsQuery)); + assertEquals(1, response.responses().size()); + assertEquals(3, response.responses().get(0).result().hits().hits().size()); + } + + @Test + public void shouldReturnMultiSearchesIndicesBoost() throws Exception { + String index = "multiple_searches_request_indices_boost"; + createTestDocuments(index); + + RequestItem sortedItemsQuery = createMSearchFuzzyRequest(b -> b.indicesBoost(Collections.singletonMap(index, 2d))); + + MsearchResponse response = sendMSearchRequest(index, List.of(sortedItemsQuery)); + assertEquals(1, response.responses().size()); + assertEquals(3, response.responses().get(0).result().hits().hits().size()); + } + private void assertResponseSources(MultiSearchResponseItem response) { List> hitsWithHighlights = response.result().hits().hits(); assertEquals(2, hitsWithHighlights.size());