-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Add a builder for SearchContext #47198
Conversation
This change removes all subclass of SearchContext and replace them with a simple Builder than can be used to create final SearchContext that cannot modify the search request attributes. This commit also ensures that all sub-search contexts (top_hits agg, inner_hits, percolator, ...) are independent of their parent context and sets the nested scope in the associated query shard context if the sub-context is nested. Relates elastic#46523
Pinging @elastic/es-search |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a couple of small comments/questions, nothing major. Great change!
innerHitsContext.version(innerHitBuilder.isVersion()); | ||
innerHitsContext.seqNoAndPrimaryTerm(innerHitBuilder.isSeqNoAndPrimaryTerm()); | ||
innerHitsContext.trackScores(innerHitBuilder.isTrackScores()); | ||
protected SearchContext createSubSearchContext(QueryShardContext cloneShardContext, SearchContext parentContext) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be possible to share these different createSubSearchContext methods into a single e.g. SearchContext#createSubSearchContext? Or does each one do and set slightly different things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried a different approach in #47733. We don't need a full search context to run the fetch phase or the highlight phase. I started with the highlight phase but it could be applicable to the fetch phase too and in this case we wouldn't need a sub search context.
|
||
// TODO: when types are complete removed just use String instead for the id: | ||
private Uid uid; | ||
|
||
protected InnerHitSubContext(String name, SearchContext context) { | ||
super(context); | ||
protected InnerHitsSubContext(String name, SearchContext subSearchContext) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to only accept what's needed here instead of the whole search context? seems like sort, size and searcher may be enough? Though I see that the class member is protected and subclasses need more. Probably good as-is.
*/ | ||
COLLECTION, | ||
public Builder buildHighlight(HighlightBuilder builder) throws SearchException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see why these methods return the Builder itself, but maybe this should be done only for the set methods? In some cases we also end up never using the return type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to have these as set methods, and then call build
on these sub-builders during the parent contexts build
method - that is, SearchContextBuilder
shouldn't have a SearchContextHighlight
member, it should have a HighlightBuilder
member.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++, we can require a SearchSourceBuilder
and create everything internally. I'll finish the cleanup of the sub search context first and will come back to this afterward.
@@ -38,7 +38,7 @@ | |||
/** | |||
* Various test for {@link org.elasticsearch.test.AbstractQueryTestCase} | |||
*/ | |||
public class AbstractQueryTestCaseTests extends ESTestCase { | |||
public class AbstractQueryTestCaseTests extends ESTestCase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super minor nit: revert this one? ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to make reasoning about these things so much easier. I have a few questions, but looks great overall.
SearchContext.Builder builder = new SearchContext.Builder(parentContext.id(), | ||
parentContext.getTask(), | ||
parentContext.nodeId(), | ||
parentContext.indexShard(), | ||
parentContext.getQueryShardContext(), | ||
parentContext.searcher(), | ||
parentContext.fetchPhase(), | ||
parentContext.shardTarget().getClusterAlias(), | ||
parentContext.numberOfShards(), | ||
parentContext::getRelativeTimeInMillis, | ||
parentContext.source()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this work as a simple copy contructor? Or do we need to be picky about which member variables we're copying over?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried a different approach in #47733. We don't need a full search context to run the highlight phase. With this change we wouldn't need to clone the search context at all.
searchContext, parent, pipelineAggregators, metaData); | ||
} | ||
|
||
private SearchContext.Builder parse(SearchContext.Builder builder) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this method is needed?
* @param clusterService The cluster service to build the slice query (if any). | ||
* @param multiBucketConsumer The bucket consumer for aggregations. | ||
*/ | ||
public static Builder parseShardSearchRequest(Builder builder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this make more sense as a method on Builder?
*/ | ||
COLLECTION, | ||
public Builder buildHighlight(HighlightBuilder builder) throws SearchException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to have these as set methods, and then call build
on these sub-builders during the parent contexts build
method - that is, SearchContextBuilder
shouldn't have a SearchContextHighlight
member, it should have a HighlightBuilder
member.
@@ -44,8 +44,6 @@ | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
|
|||
import static org.mockito.Mockito.when; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
aggregator.postCollection(); | ||
InternalGlobal result = (InternalGlobal) aggregator.buildAggregation(0L); | ||
verify.accept(result, (InternalMin) result.getAggregations().asMap().get("in_global")); | ||
try (SearchContext context = aggregator.context()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If aggregator.context()
is creating a new context that needs to be closed, maybe we should call it buildContext
or something similar, to ensure that it doesn't get mistaken for a simple getter?
* Creates the final {@link SearchContext} and set the provided | ||
* {@link Runnable} to be executed when the context is closed. | ||
*/ | ||
public SearchContext build(Runnable onClose) throws SearchException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why we take onClose
as a parameter here, and don't set it on the Builder directly? Almost every invocation seems to be build(() -> {})
which suggests that it's not necessary.
Today built-in highlighter and plugins have access to the SearchContext through the highlighter context. However most of the information exposed in the SearchContext are not needed and a QueryShardContext would be enough to perform highlighting. This change replaces the SearchContext by the informations that are absolutely required by highlighter: a QueryShardContext and the SearchContextHighlight. This change allows to reduce the exposure of the complex SearchContext and remove the needs to clone it in the percolator sub phase. Relates elastic#47198 Relates elastic#46523
Today built-in highlighter and plugins have access to the SearchContext through the highlighter context. However most of the information exposed in the SearchContext are not needed and a QueryShardContext would be enough to perform highlighting. This change replaces the SearchContext by the informations that are absolutely required by highlighter: a QueryShardContext and the SearchContextHighlight. This change allows to reduce the exposure of the complex SearchContext and remove the needs to clone it in the percolator sub phase. Relates #47198 Relates #46523
Today built-in highlighter and plugins have access to the SearchContext through the highlighter context. However most of the information exposed in the SearchContext are not needed and a QueryShardContext would be enough to perform highlighting. This change replaces the SearchContext by the informations that are absolutely required by highlighter: a QueryShardContext and the SearchContextHighlight. This change allows to reduce the exposure of the complex SearchContext and remove the needs to clone it in the percolator sub phase. Relates #47198 Relates #46523
I took another approach with #47733 so this pr is obsolete. I'll open a new one that is less invasive. |
This change removes all subclass of SearchContext and replace them with a simple
Builder than can be used to create final SearchContext that cannot modify
the search request attributes. This commit also ensures that all sub-search
contexts (top_hits agg, inner_hits, percolator, ...) are independent of their
parent context and sets the nested scope in the associated query shard context
if the sub-context is nested.
Relates #46523