-
Notifications
You must be signed in to change notification settings - Fork 756
SOLR-17319 : Combined Query Feature for Multi Query Execution #3418
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
base: main
Are you sure you want to change the base?
Changes from all commits
bf3cd5d
182bec9
b884f0e
29e8aea
c113799
3600ed3
9b0c76e
a841bc7
91f8e09
cace1f7
299db43
840070e
d2feefc
89f63a9
d821abb
8041d66
397dbb3
d8b5588
ec0b9cb
d6fd190
86933bc
b164979
85f2cf9
a4a26aa
7fe997c
bcd1c3b
787a016
7e0727c
4dcbb57
8a65023
006b8c2
771089b
460e8cd
ac85d2f
7b0593c
c03c0f7
a52dd22
195f3f1
c1f5501
3649d3e
4eedbed
0990e7f
14ff5e1
bd637b7
2958599
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.solr.handler.component; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.apache.solr.request.SolrQueryRequest; | ||
import org.apache.solr.response.SolrQueryResponse; | ||
|
||
/** | ||
* The CombinedQueryResponseBuilder class extends the ResponseBuilder class and is responsible for | ||
* building a combined response for multiple SearchComponent objects. It orchestrates the process of | ||
* constructing the SolrQueryResponse by aggregating results from various components. | ||
*/ | ||
public class CombinedQueryResponseBuilder extends ResponseBuilder { | ||
|
||
public final List<ResponseBuilder> responseBuilders = new ArrayList<>(); | ||
|
||
/** | ||
* Constructs a CombinedQueryResponseBuilder instance. | ||
* | ||
* @param req the SolrQueryRequest object containing the query parameters and context. | ||
* @param rsp the SolrQueryResponse object to which the combined results will be added. | ||
* @param components a list of SearchComponent objects that will be used to build the response. | ||
*/ | ||
public CombinedQueryResponseBuilder( | ||
SolrQueryRequest req, SolrQueryResponse rsp, List<SearchComponent> components) { | ||
super(req, rsp, components); | ||
} | ||
|
||
/** | ||
* Propagates all the properties from parent ResponseBuilder to the all the children which are | ||
* being set later after the CombinedQueryComponent is prepared. | ||
*/ | ||
public final void propagate() { | ||
responseBuilders.forEach( | ||
thisRb -> { | ||
thisRb.setNeedDocSet(isNeedDocSet()); | ||
thisRb.setNeedDocList(isNeedDocList()); | ||
thisRb.doFacets = doFacets; | ||
thisRb.doHighlights = doHighlights; | ||
thisRb.doExpand = doExpand; | ||
thisRb.doTerms = doTerms; | ||
thisRb.doStats = doStats; | ||
thisRb.setDistribStatsDisabled(isDistribStatsDisabled()); | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.solr.handler.component; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.apache.solr.common.params.CombinerParams; | ||
import org.apache.solr.common.params.ModifiableSolrParams; | ||
import org.apache.solr.common.params.ShardParams; | ||
import org.apache.solr.request.SolrQueryRequest; | ||
import org.apache.solr.response.SolrQueryResponse; | ||
import org.apache.solr.search.facet.FacetModule; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* The CombinedQuerySearchHandler class extends the SearchHandler and provides custom behavior for | ||
* handling combined queries. It overrides methods to create a response builder based on the {@link | ||
* CombinerParams#COMBINER} parameter and to define the default components included in the search | ||
* configuration. | ||
*/ | ||
public class CombinedQuerySearchHandler extends SearchHandler { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); | ||
|
||
/** | ||
* Overrides the default response builder creation method. This method checks if the {@link | ||
* CombinerParams#COMBINER} parameter is set to true in the request. If it is, it returns an | ||
* instance of {@link CombinedQueryResponseBuilder}, otherwise, it returns an instance of {@link | ||
* ResponseBuilder}. | ||
* | ||
* @param req the SolrQueryRequest object | ||
* @param rsp the SolrQueryResponse object | ||
* @param components the list of SearchComponent objects | ||
* @return the appropriate ResponseBuilder instance based on the CombinerParams.COMBINER parameter | ||
*/ | ||
@Override | ||
protected ResponseBuilder newResponseBuilder( | ||
SolrQueryRequest req, SolrQueryResponse rsp, List<SearchComponent> components) { | ||
if (req.getParams().getBool(CombinerParams.COMBINER, false)) { | ||
return new CombinedQueryResponseBuilder(req, rsp, components); | ||
} | ||
return super.newResponseBuilder(req, rsp, components); | ||
} | ||
|
||
/** | ||
* Overrides the default components and returns a list of component names that are included in the | ||
* default configuration. | ||
* | ||
* @return a list of component names | ||
*/ | ||
@Override | ||
@SuppressWarnings("unchecked") | ||
protected List<String> getDefaultComponents() { | ||
List<String> names = new ArrayList<>(9); | ||
names.add(CombinedQueryComponent.COMPONENT_NAME); | ||
names.add(FacetComponent.COMPONENT_NAME); | ||
names.add(FacetModule.COMPONENT_NAME); | ||
names.add(MoreLikeThisComponent.COMPONENT_NAME); | ||
names.add(HighlightComponent.COMPONENT_NAME); | ||
names.add(StatsComponent.COMPONENT_NAME); | ||
names.add(DebugComponent.COMPONENT_NAME); | ||
names.add(ExpandComponent.COMPONENT_NAME); | ||
names.add(TermsComponent.COMPONENT_NAME); | ||
return names; | ||
} | ||
|
||
@Override | ||
protected void postPrepareComponents(ResponseBuilder rb) { | ||
super.postPrepareComponents(rb); | ||
// propagate the CombinedQueryResponseBuilder's state to all subBuilders after prepare | ||
if (rb instanceof CombinedQueryResponseBuilder crb) { | ||
crb.propagate(); | ||
} | ||
} | ||
|
||
/** | ||
* rb.distrib {@link ResponseBuilder} must be set for the combined query to work in case of single | ||
* core standalone mode. This method set the parameter explicitly with other required solr param | ||
* i.e. shards | ||
* | ||
* @param req the SolrQueryRequest | ||
* @return boolean denoting whether the request can be marked as distributed. | ||
*/ | ||
@Override | ||
protected boolean isDistrib(SolrQueryRequest req) { | ||
boolean isDistrib = super.isDistrib(req); | ||
if (!isDistrib | ||
&& !req.getParams().getBool(ShardParams.IS_SHARD, false) | ||
&& req.getHttpSolrCall() != null) { | ||
log.info("Configuring distributed mode to enable Combined Query."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not worth logging; or maybe trace |
||
ModifiableSolrParams solrParams = new ModifiableSolrParams(req.getParams()); | ||
String scheme = req.getHttpSolrCall().getReq().getScheme(); | ||
String host = req.getHttpSolrCall().getReq().getServerName(); | ||
int port = req.getHttpSolrCall().getReq().getServerPort(); | ||
String context = req.getHttpSolrCall().getReq().getContextPath(); | ||
String core = req.getCore().getName(); | ||
String localShardUrl = String.format("%s://%s:%d%s/%s", scheme, host, port, context, core); | ||
solrParams.set(ShardParams.SHARDS, localShardUrl); | ||
req.setParams(solrParams); | ||
Comment on lines
+114
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's a bit sneaky that a predicate looking method has a side-effect. This is a hack to work around a need for something proper -- for a component or handler to communicate we need the distributed search algorithm (no so-called short-circuit). |
||
return true; | ||
} | ||
return isDistrib; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.