Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased 3.x]
### Added
- Add support for include_named_queries_score in msearch ([#19102](https://github.com/opensearch-project/OpenSearch/issues/19102))
- Use Lucene `pack` method for `half_float` and `usigned_long` when using `ApproximatePointRangeQuery`.

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ public static MultiSearchRequest parseRequest(
maxConcurrentShardRequests = null;
}

Boolean includeNamedQueriesScore = null;
if (restRequest.hasParam("include_named_queries_score")) {
includeNamedQueriesScore = restRequest.paramAsBoolean("include_named_queries_score", false);
}

parseMultiLineRequest(restRequest, multiRequest.indicesOptions(), allowExplicitIndex, (searchRequest, parser) -> {
searchRequest.source(SearchSourceBuilder.fromXContent(parser, false));
RestSearchAction.checkRestTotalHits(restRequest, searchRequest);
Expand Down Expand Up @@ -171,6 +176,13 @@ public static MultiSearchRequest parseRequest(
if (request.getCancelAfterTimeInterval() == null) {
request.setCancelAfterTimeInterval(cancelAfterTimeInterval);
}

// If the `include_named_queries_score` URL parameter is set on the msearch request but not in the individual
// search body, copy it to the individual request's search body. The search body parameter determines whether
// the scores are computed during query execution.
if (includeNamedQueriesScore != null && request.source().includeNamedQueriesScore() == null) {
request.source().includeNamedQueriesScores(includeNamedQueriesScore);
}
}
return multiRequest;
}
Expand Down
5 changes: 2 additions & 3 deletions server/src/main/java/org/opensearch/search/SearchHit.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.SourceFieldMapper;
import org.opensearch.index.seqno.SequenceNumbers;
import org.opensearch.rest.action.search.RestSearchAction;
import org.opensearch.search.fetch.subphase.highlight.HighlightField;
import org.opensearch.search.lookup.SourceLookup;
import org.opensearch.transport.RemoteClusterAware;
Expand Down Expand Up @@ -731,8 +730,8 @@ public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) t
}
sortValues.toXContent(builder, params);
if (!matchedQueries.isEmpty()) {
boolean includeMatchedQueriesScore = params.paramAsBoolean(RestSearchAction.INCLUDE_NAMED_QUERIES_SCORE_PARAM, false);
if (includeMatchedQueriesScore) {
boolean includeNamedQueriesScore = matchedQueries.values().stream().anyMatch(value -> value != null && !Float.isNaN(value));
if (includeNamedQueriesScore) {
builder.startObject(Fields.MATCHED_QUERIES);
for (Map.Entry<String, Float> entry : matchedQueries.entrySet()) {
builder.field(entry.getKey(), entry.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1559,7 +1559,9 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc
}
}
context.trackScores(source.trackScores());
context.includeNamedQueriesScore(source.includeNamedQueriesScore());
if (source.includeNamedQueriesScore() != null) {
context.includeNamedQueriesScore(source.includeNamedQueriesScore());
}
if (source.trackTotalHitsUpTo() != null
&& source.trackTotalHitsUpTo() != SearchContext.TRACK_TOTAL_HITS_ACCURATE
&& context.scrollContext() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,16 +625,16 @@ public SearchSourceBuilder trackScores(boolean trackScores) {
* Applies when there are named queries, to return the scores along as well
* Defaults to {@code false}.
*/
public SearchSourceBuilder includeNamedQueriesScores(boolean includeNamedQueriesScore) {
public SearchSourceBuilder includeNamedQueriesScores(Boolean includeNamedQueriesScore) {
this.includeNamedQueriesScore = includeNamedQueriesScore;
return this;
}

/**
* Indicates whether scores will be returned as part of every search matched query.s
*/
public boolean includeNamedQueriesScore() {
return includeNamedQueriesScore != null && includeNamedQueriesScore;
public Boolean includeNamedQueriesScore() {
return includeNamedQueriesScore;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.opensearch.common.CheckedBiConsumer;
import org.opensearch.common.CheckedRunnable;
import org.opensearch.common.logging.DeprecationLogger;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.common.xcontent.XContentHelper;
import org.opensearch.common.xcontent.XContentType;
Expand All @@ -56,6 +57,7 @@
import org.opensearch.rest.RestRequest;
import org.opensearch.rest.action.search.RestMultiSearchAction;
import org.opensearch.search.Scroll;
import org.opensearch.search.SearchModule;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.test.OpenSearchTestCase;
import org.opensearch.test.StreamsUtils;
Expand Down Expand Up @@ -196,6 +198,63 @@ public void testDefaultIndicesOptions() throws IOException {
);
}

public void testIncludeNamedQueriesScore() throws Exception {
SearchModule searchModule = new SearchModule(Settings.EMPTY, Collections.emptyList());
NamedXContentRegistry xContentRegistry = new NamedXContentRegistry(searchModule.getNamedXContents());

// URL query parameter: include_named_queries_score
assertIncludeNamedQueriesScore("", "false", false, true);

// URL query parameter: include_named_queries_score=true
assertIncludeNamedQueriesScore("true", "false", false, true);

// URL query parameter: include_named_queries_score=false
assertIncludeNamedQueriesScore("false", "true", true, false);

// No URL query parameter
assertIncludeNamedQueriesScore(null, "true", true, null);
}

private void assertIncludeNamedQueriesScore(
String urlParamValue,
String bodyParamValue,
Boolean expectedFirstRequest,
Boolean expectedSecondRequest
) throws IOException {
SearchModule searchModule = new SearchModule(Settings.EMPTY, Collections.emptyList());
NamedXContentRegistry xContentRegistry = new NamedXContentRegistry(searchModule.getNamedXContents());

final String requestContent = "{\"index\":\"test\"}\r\n"
+ "{\"query\":{\"term\":{\"field\":{\"value\":\"xxx\",\"_name\":\"value_name\"}}},\"include_named_queries_score\":"
+ bodyParamValue
+ "}\r\n"
+ "{}\r\n"
+ "{\"query\":{\"term\":{\"field\":{\"value\":\"xxx\",\"_name\":\"value_name\"}}}}\r\n";

FakeRestRequest.Builder builder = new FakeRestRequest.Builder(xContentRegistry).withContent(
new BytesArray(requestContent),
MediaTypeRegistry.JSON
);
if (urlParamValue != null) {
builder = builder.withParams(Collections.singletonMap("include_named_queries_score", urlParamValue));
}

FakeRestRequest restRequest = builder.build();
MultiSearchRequest request = RestMultiSearchAction.parseRequest(restRequest, null, true);

assertThat(request.requests().size(), equalTo(2));
assertEquals(
"First request's include_named_queries_score did not match",
expectedFirstRequest,
request.requests().get(0).source().includeNamedQueriesScore()
);
assertEquals(
"Second request's include_named_queries_score did not match",
expectedSecondRequest,
request.requests().get(1).source().includeNamedQueriesScore()
);
}

public void testSimpleAdd2() throws Exception {
MultiSearchRequest request = parseMultiSearchRequestFromFile("/org/opensearch/action/search/simple-msearch2.json");
assertThat(request.requests().size(), equalTo(5));
Expand Down