Skip to content
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

Closed
wants to merge 5 commits into from

Conversation

jimczi
Copy link
Contributor

@jimczi jimczi commented Sep 27, 2019

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

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
@jimczi jimczi added >non-issue :Search/Search Search-related issues that do not fall into other categories v8.0.0 v7.5.0 labels Sep 27, 2019
@jimczi jimczi requested a review from javanna September 27, 2019 08:40
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-search

@jimczi jimczi requested a review from romseygeek October 2, 2019 10:38
Copy link
Member

@javanna javanna left a 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 {
Copy link
Member

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?

Copy link
Contributor Author

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) {
Copy link
Member

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 {
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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 {
Copy link
Member

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? ;)

Copy link
Contributor

@romseygeek romseygeek left a 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.

Comment on lines +172 to +182
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());
Copy link
Contributor

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?

Copy link
Contributor Author

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) {
Copy link
Contributor

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,
Copy link
Contributor

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 {
Copy link
Contributor

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;
Copy link
Contributor

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()) {
Copy link
Contributor

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 {
Copy link
Contributor

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.

jimczi added a commit to jimczi/elasticsearch that referenced this pull request Oct 8, 2019
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
jimczi added a commit that referenced this pull request Oct 9, 2019
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
jimczi added a commit that referenced this pull request Oct 10, 2019
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
@jimczi
Copy link
Contributor Author

jimczi commented Oct 14, 2019

I took another approach with #47733 so this pr is obsolete. I'll open a new one that is less invasive.

@jimczi jimczi closed this Oct 14, 2019
@jimczi jimczi deleted the search_context_cleanup branch October 14, 2019 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>non-issue :Search/Search Search-related issues that do not fall into other categories v7.5.0 v8.0.0-alpha1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants