Skip to content

[Backport 9.0] Support include_names_queries_score #983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2025
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ public class MsearchRequest extends RequestBase implements NdJsonpSerializable,
@Nullable
private final Boolean ignoreUnavailable;

@Nullable
private final Boolean includeNamedQueriesScore;

private final List<String> index;

@Nullable
Expand Down Expand Up @@ -136,6 +139,7 @@ private MsearchRequest(Builder builder) {
this.expandWildcards = ApiTypeHelper.unmodifiable(builder.expandWildcards);
this.ignoreThrottled = builder.ignoreThrottled;
this.ignoreUnavailable = builder.ignoreUnavailable;
this.includeNamedQueriesScore = builder.includeNamedQueriesScore;
this.index = ApiTypeHelper.unmodifiable(builder.index);
this.maxConcurrentSearches = builder.maxConcurrentSearches;
this.maxConcurrentShardRequests = builder.maxConcurrentShardRequests;
Expand Down Expand Up @@ -210,6 +214,22 @@ public final Boolean ignoreUnavailable() {
return this.ignoreUnavailable;
}

/**
* Indicates whether hit.matched_queries should be rendered as a map that
* includes the name of the matched query associated with its score (true) or as
* an array containing the name of the matched queries (false) This
* functionality reruns each named query on every hit in a search response.
* Typically, this adds a small overhead to a request. However, using
* computationally expensive named queries on a large number of hits may add
* significant overhead.
* <p>
* API name: {@code include_named_queries_score}
*/
@Nullable
public final Boolean includeNamedQueriesScore() {
return this.includeNamedQueriesScore;
}

/**
* Comma-separated list of data streams, indices, and index aliases to search.
* <p>
Expand Down Expand Up @@ -320,6 +340,9 @@ public static class Builder extends RequestBase.AbstractBuilder<Builder> impleme
@Nullable
private Boolean ignoreUnavailable;

@Nullable
private Boolean includeNamedQueriesScore;

@Nullable
private List<String> index;

Expand Down Expand Up @@ -413,6 +436,22 @@ public final Builder ignoreUnavailable(@Nullable Boolean value) {
return this;
}

/**
* Indicates whether hit.matched_queries should be rendered as a map that
* includes the name of the matched query associated with its score (true) or as
* an array containing the name of the matched queries (false) This
* functionality reruns each named query on every hit in a search response.
* Typically, this adds a small overhead to a request. However, using
* computationally expensive named queries on a large number of hits may add
* significant overhead.
* <p>
* API name: {@code include_named_queries_score}
*/
public final Builder includeNamedQueriesScore(@Nullable Boolean value) {
this.includeNamedQueriesScore = value;
return this;
}

/**
* Comma-separated list of data streams, indices, and index aliases to search.
* <p>
Expand Down Expand Up @@ -613,6 +652,9 @@ public MsearchRequest build() {
params.put("expand_wildcards",
request.expandWildcards.stream().map(v -> v.jsonValue()).collect(Collectors.joining(",")));
}
if (request.includeNamedQueriesScore != null) {
params.put("include_named_queries_score", String.valueOf(request.includeNamedQueriesScore));
}
if (request.searchType != null) {
params.put("search_type", request.searchType.jsonValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ public class SearchRequest extends RequestBase implements JsonpSerializable {
@Nullable
private final Boolean ignoreUnavailable;

@Nullable
private final Boolean includeNamedQueriesScore;

private final List<String> index;

private final List<NamedValue<Double>> indicesBoost;
Expand Down Expand Up @@ -304,6 +307,7 @@ private SearchRequest(Builder builder) {
this.highlight = builder.highlight;
this.ignoreThrottled = builder.ignoreThrottled;
this.ignoreUnavailable = builder.ignoreUnavailable;
this.includeNamedQueriesScore = builder.includeNamedQueriesScore;
this.index = ApiTypeHelper.unmodifiable(builder.index);
this.indicesBoost = ApiTypeHelper.unmodifiable(builder.indicesBoost);
this.knn = ApiTypeHelper.unmodifiable(builder.knn);
Expand Down Expand Up @@ -598,6 +602,22 @@ public final Boolean ignoreUnavailable() {
return this.ignoreUnavailable;
}

/**
* If <code>true</code>, the response includes the score contribution from any
* named queries.
* <p>
* This functionality reruns each named query on every hit in a search response.
* Typically, this adds a small overhead to a request. However, using
* computationally expensive named queries on a large number of hits may add
* significant overhead.
* <p>
* API name: {@code include_named_queries_score}
*/
@Nullable
public final Boolean includeNamedQueriesScore() {
return this.includeNamedQueriesScore;
}

/**
* A comma-separated list of data streams, indices, and aliases to search. It
* supports wildcards (<code>*</code>). To search all data streams and indices,
Expand Down Expand Up @@ -1363,6 +1383,9 @@ public static class Builder extends RequestBase.AbstractBuilder<Builder> impleme
@Nullable
private Boolean ignoreUnavailable;

@Nullable
private Boolean includeNamedQueriesScore;

@Nullable
private List<String> index;

Expand Down Expand Up @@ -1883,6 +1906,22 @@ public final Builder ignoreUnavailable(@Nullable Boolean value) {
return this;
}

/**
* If <code>true</code>, the response includes the score contribution from any
* named queries.
* <p>
* This functionality reruns each named query on every hit in a search response.
* Typically, this adds a small overhead to a request. However, using
* computationally expensive named queries on a large number of hits may add
* significant overhead.
* <p>
* API name: {@code include_named_queries_score}
*/
public final Builder includeNamedQueriesScore(@Nullable Boolean value) {
this.includeNamedQueriesScore = value;
return this;
}

/**
* A comma-separated list of data streams, indices, and aliases to search. It
* supports wildcards (<code>*</code>). To search all data streams and indices,
Expand Down Expand Up @@ -2909,6 +2948,9 @@ protected static void setupSearchRequestDeserializer(ObjectDeserializer<SearchRe
if (request.forceSyntheticSource != null) {
params.put("force_synthetic_source", String.valueOf(request.forceSyntheticSource));
}
if (request.includeNamedQueriesScore != null) {
params.put("include_named_queries_score", String.valueOf(request.includeNamedQueriesScore));
}
if (request.lenient != null) {
params.put("lenient", String.valueOf(request.lenient));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public class Hit<TDocument> implements JsonpSerializable {

private final Map<String, InnerHitsResult> innerHits;

private final List<String> matchedQueries;
private final Map<String, Double> matchedQueries;

@Nullable
private final NestedIdentity nested;
Expand Down Expand Up @@ -212,7 +212,7 @@ public final Map<String, InnerHitsResult> innerHits() {
/**
* API name: {@code matched_queries}
*/
public final List<String> matchedQueries() {
public final Map<String, Double> matchedQueries() {
return this.matchedQueries;
}

Expand Down Expand Up @@ -380,12 +380,21 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
}
if (ApiTypeHelper.isDefined(this.matchedQueries)) {
generator.writeKey("matched_queries");
generator.writeStartArray();
for (String item0 : this.matchedQueries) {
generator.write(item0);
if (this.matchedQueries.values().stream().allMatch(Objects::isNull)) {
generator.writeStartArray();
for (String item0 : this.matchedQueries.keySet()) {
generator.write(item0);
}
generator.writeEnd();
} else {
generator.writeStartObject();
for (Map.Entry<String, Double> item0 : this.matchedQueries.entrySet()) {
generator.writeKey(item0.getKey());
generator.write(item0.getValue());

}
generator.writeEnd();
}
generator.writeEnd();

}
if (this.nested != null) {
Expand Down Expand Up @@ -509,7 +518,7 @@ public static class Builder<TDocument> extends WithJsonObjectBuilderBase<Builder
private Map<String, InnerHitsResult> innerHits;

@Nullable
private List<String> matchedQueries;
private Map<String, Double> matchedQueries;

@Nullable
private NestedIdentity nested;
Expand Down Expand Up @@ -662,20 +671,20 @@ public final Builder<TDocument> innerHits(String key,
/**
* API name: {@code matched_queries}
* <p>
* Adds all elements of <code>list</code> to <code>matchedQueries</code>.
* Adds all entries of <code>map</code> to <code>matchedQueries</code>.
*/
public final Builder<TDocument> matchedQueries(List<String> list) {
this.matchedQueries = _listAddAll(this.matchedQueries, list);
public final Builder<TDocument> matchedQueries(Map<String, Double> map) {
this.matchedQueries = _mapPutAll(this.matchedQueries, map);
return this;
}

/**
* API name: {@code matched_queries}
* <p>
* Adds one or more values to <code>matchedQueries</code>.
* Adds an entry to <code>matchedQueries</code>.
*/
public final Builder<TDocument> matchedQueries(String value, String... values) {
this.matchedQueries = _listAdd(this.matchedQueries, value, values);
public final Builder<TDocument> matchedQueries(String key, Double value) {
this.matchedQueries = _mapPut(this.matchedQueries, key, value);
return this;
}

Expand Down Expand Up @@ -937,7 +946,8 @@ protected static <TDocument> void setupHitDeserializer(ObjectDeserializer<Hit.Bu
JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer())), "highlight");
op.add(Builder::innerHits, JsonpDeserializer.stringMapDeserializer(InnerHitsResult._DESERIALIZER),
"inner_hits");
op.add(Builder::matchedQueries, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()),
op.add(Builder::matchedQueries,
JsonpDeserializer.stringArrayMapUnionDeserializer(JsonpDeserializer.doubleDeserializer()),
"matched_queries");
op.add(Builder::nested, NestedIdentity._DESERIALIZER, "_nested");
op.add(Builder::ignored, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ static <T> JsonpDeserializer<Map<String, T>> stringMapDeserializer(JsonpDeserial
return new JsonpDeserializerBase.StringMapDeserializer<T>(itemDeserializer);
}

static <T> JsonpDeserializer<Map<String, T>> stringArrayMapUnionDeserializer(JsonpDeserializer<T> itemDeserializer) {
return new JsonpDeserializerBase.StringArrayMapUnionDeserializer<T>(itemDeserializer);
}

static <K extends JsonEnum, V> JsonpDeserializer<Map<K, V>> enumMapDeserializer(
JsonpDeserializer<K> keyDeserializer, JsonpDeserializer<V> valueDeserializer
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,43 @@ public Map<String, T> deserialize(JsonParser parser, JsonpMapper mapper, Event e
}
}

// Used for fields such as matched_queries, which can be either an array or a dictionary, where the array
// value type is the same as the dictionary key type
static class StringArrayMapUnionDeserializer<T> extends JsonpDeserializerBase<Map<String, T>> {
private final JsonpDeserializer<T> itemDeserializer;

protected StringArrayMapUnionDeserializer(JsonpDeserializer<T> itemDeserializer) {
super(EnumSet.of(Event.START_OBJECT,Event.START_ARRAY));
this.itemDeserializer = itemDeserializer;
}

@Override
public Map<String, T> deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
Map<String, T> result = new HashMap<>();
String key = null;
try {
// Array case, deserializing it into a map with null values
if (event == Event.START_ARRAY) {
while ((event = parser.next()) != Event.END_ARRAY) {
JsonpUtils.expectEvent(parser, Event.VALUE_STRING, event);
result.put(parser.getString(),null);
}
} else {
// Dictionary case
while ((event = parser.next()) != Event.END_OBJECT) {
JsonpUtils.expectEvent(parser, Event.KEY_NAME, event);
key = parser.getString();
T value = itemDeserializer.deserialize(parser, mapper);
result.put(key, value);
}
}
} catch (Exception e) {
throw JsonpMappingException.from(e, null, key, parser);
}
return result;
}
}

static class EnumMapDeserializer<K, V> extends JsonpDeserializerBase<Map<K, V>> {
private final JsonpDeserializer<K> keyDeserializer;
private final JsonpDeserializer<V> valueDeserializer;
Expand Down
Loading