You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by jb...@apache.org on 2023/09/19 14:38:48 UTC
[solr] branch main updated: SOLR-16931: ReRankScaler explain breaks with debug=true and in distributed mode (#1936)
This is an automated email from the ASF dual-hosted git repository.
jbernste pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 1c2ebe23403 SOLR-16931: ReRankScaler explain breaks with debug=true and in distributed mode (#1936)
1c2ebe23403 is described below
commit 1c2ebe23403dc2f3dfde3ac7f8cfb176256f3e72
Author: Joel Bernstein <jb...@apache.org>
AuthorDate: Tue Sep 19 10:38:41 2023 -0400
SOLR-16931: ReRankScaler explain breaks with debug=true and in distributed mode (#1936)
---
.../solr/handler/component/QueryComponent.java | 32 ++++++
.../apache/solr/search/ReRankQParserPlugin.java | 17 ++++
.../solr/search/DistributedReRankExplainTest.java | 109 +++++++++++++++++++++
.../solr/search/TestReRankQParserPlugin.java | 2 +-
4 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java b/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
index a2b46a30d46..e8457df3e08 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
@@ -88,6 +88,7 @@ import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.QueryResult;
import org.apache.solr.search.QueryUtils;
import org.apache.solr.search.RankQuery;
+import org.apache.solr.search.ReRankQParserPlugin;
import org.apache.solr.search.ReturnFields;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SolrReturnFields;
@@ -757,6 +758,7 @@ public class QueryComponent extends SearchComponent {
boolean distribSinglePass = rb.req.getParams().getBool(ShardParams.DISTRIB_SINGLE_PASS, false);
if (distribSinglePass
+ || singlePassExplain(rb.req.getParams())
|| (fields != null
&& fields.wantsField(keyFieldName)
&& fields.getRequestedFieldNames() != null
@@ -838,6 +840,36 @@ public class QueryComponent extends SearchComponent {
rb.addRequest(this, sreq);
}
+ private boolean singlePassExplain(SolrParams params) {
+
+ /*
+ * Currently there is only one explain that requires a single pass
+ * and that is the reRank when scaling is used.
+ */
+
+ String rankQuery = params.get(CommonParams.RQ);
+ if (rankQuery != null) {
+ if (rankQuery.contains(ReRankQParserPlugin.RERANK_MAIN_SCALE)
+ || rankQuery.contains(ReRankQParserPlugin.RERANK_SCALE)) {
+ boolean debugQuery = params.getBool(CommonParams.DEBUG_QUERY, false);
+ if (debugQuery) {
+ return true;
+ } else {
+ String[] debugParams = params.getParams(CommonParams.DEBUG);
+ if (debugParams != null) {
+ for (String debugParam : debugParams) {
+ if (debugParam.equals("true")) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
protected boolean addFL(StringBuilder fl, String field, boolean additionalAdded) {
if (additionalAdded) fl.append(",");
fl.append(field);
diff --git a/solr/core/src/java/org/apache/solr/search/ReRankQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/ReRankQParserPlugin.java
index 2ae72837218..e9597c3dd86 100644
--- a/solr/core/src/java/org/apache/solr/search/ReRankQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/ReRankQParserPlugin.java
@@ -17,6 +17,7 @@
package org.apache.solr.search;
import java.io.IOException;
+import java.lang.invoke.MethodHandles;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryRescorer;
@@ -25,6 +26,8 @@ import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.request.SolrQueryRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/*
*
@@ -50,6 +53,7 @@ public class ReRankQParserPlugin extends QParserPlugin {
public static final String RERANK_SCALE = "reRankScale";
public static final String RERANK_MAIN_SCALE = "reRankMainScale";
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public QParser createParser(
@@ -85,6 +89,19 @@ public class ReRankQParserPlugin extends QParserPlugin {
String mainScale = localParams.get(RERANK_MAIN_SCALE);
String reRankScale = localParams.get(RERANK_SCALE);
boolean debugQuery = params.getBool(CommonParams.DEBUG_QUERY, false);
+
+ if (!debugQuery) {
+ String[] debugParams = params.getParams(CommonParams.DEBUG);
+ if (debugParams != null) {
+ for (String debugParam : debugParams) {
+ if ("true".equals(debugParam)) {
+ debugQuery = true;
+ break;
+ }
+ }
+ }
+ }
+
double reRankScaleWeight = reRankWeight;
ReRankScaler reRankScaler =
diff --git a/solr/core/src/test/org/apache/solr/search/DistributedReRankExplainTest.java b/solr/core/src/test/org/apache/solr/search/DistributedReRankExplainTest.java
new file mode 100644
index 00000000000..defe6fef4ff
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/search/DistributedReRankExplainTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.search;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Map;
+import java.util.Random;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SolrTestCaseJ4.SuppressSSL
+public class DistributedReRankExplainTest extends SolrCloudTestCase {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private static final int numShards = 2;
+ private static final String COLLECTIONORALIAS = "collection1";
+
+ private static final int TIMEOUT = DEFAULT_TIMEOUT;
+ private static final String id = "id";
+
+ private static boolean useAlias;
+
+ @BeforeClass
+ public static void setupCluster() throws Exception {
+ System.setProperty("managed.schema.mutable", "true");
+ String collection = COLLECTIONORALIAS;
+ configureCluster(2)
+ .addConfig(
+ "conf1", TEST_PATH().resolve("configsets").resolve("cloud-managed").resolve("conf"))
+ .configure();
+ CollectionAdminRequest.createCollection(collection, "conf1", 2, 1)
+ .setPerReplicaState(SolrCloudTestCase.USE_PER_REPLICA_STATE)
+ .process(cluster.getSolrClient());
+
+ cluster.waitForActiveCollection(collection, 2, 2);
+ }
+
+ @Test
+ public void testReRankExplain() throws Exception {
+ CloudSolrClient client = cluster.getSolrClient();
+ UpdateRequest updateRequest = new UpdateRequest();
+ for (int i = 0; i < 100; i++) {
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.addField(CommonParams.ID, Integer.toString(i));
+ doc.addField("test_s", "hello");
+ updateRequest.add(doc);
+ }
+ updateRequest.process(client, COLLECTIONORALIAS);
+ client.commit(COLLECTIONORALIAS);
+
+ String[] debugParams = {CommonParams.DEBUG, CommonParams.DEBUG_QUERY};
+ Random random = random();
+ ModifiableSolrParams solrParams = new ModifiableSolrParams();
+ String reRank = "{!rerank reRankDocs=10 reRankMainScale=0-10 reRankQuery='test_s:hello'}";
+ solrParams
+ .add("q", "test_s:hello")
+ .add(debugParams[random.nextInt(2)], "true")
+ .add(CommonParams.RQ, reRank);
+ QueryRequest queryRequest = new QueryRequest(solrParams);
+ QueryResponse queryResponse = queryRequest.process(client, COLLECTIONORALIAS);
+ Map<String, Object> debug = queryResponse.getDebugMap();
+ assertNotNull(debug);
+ String explain = debug.get("explain").toString();
+ assertTrue(
+ explain.contains("5.0101576 = combined scaled first and unscaled second pass score "));
+
+ solrParams = new ModifiableSolrParams();
+ reRank = "{!rerank reRankDocs=10 reRankScale=0-10 reRankQuery='test_s:hello'}";
+ solrParams
+ .add("q", "test_s:hello")
+ .add(debugParams[random.nextInt(2)], "true")
+ .add(CommonParams.RQ, reRank);
+ queryRequest = new QueryRequest(solrParams);
+ queryResponse = queryRequest.process(client, COLLECTIONORALIAS);
+ debug = queryResponse.getDebugMap();
+ assertNotNull(debug);
+ explain = debug.get("explain").toString();
+ assertTrue(
+ explain.contains("10.005078 = combined unscaled first and scaled second pass score "));
+ }
+}
diff --git a/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java b/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
index f551ba82fca..5d769c4e57f 100644
--- a/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/TestReRankQParserPlugin.java
@@ -1522,7 +1522,7 @@ public class TestReRankQParserPlugin extends SolrTestCaseJ4 {
params.add("start", "0");
params.add("rows", "6");
params.add("df", "text");
- params.add("debugQuery", "true");
+ params.add("debug", "true");
assertQ(
req(params),
"*[count(//doc)=6]",