diff --git a/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java b/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java index 28874ada8a7..d7ac47c14b5 100644 --- a/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java @@ -52,6 +52,7 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.StrUtils; import org.apache.solr.handler.admin.api.MoreLikeThisAPI; +import org.apache.solr.handler.component.DebugComponent; import org.apache.solr.handler.component.FacetComponent; import org.apache.solr.handler.component.ResponseBuilder; import org.apache.solr.request.SimpleFacets; @@ -246,12 +247,10 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw dbgQuery = true; dbgResults = true; } - // TODO resolve duplicated code with DebugComponent. Perhaps it should be added to - // doStandardDebug? if (dbg == true) { try { NamedList dbgInfo = - SolrPluginUtils.doStandardDebug( + DebugComponent.doStandardDebug( req, q, mlt.getRawMLTQuery(), mltDocs.docList, dbgQuery, dbgResults); if (null != filters) { dbgInfo.add("filter_queries", req.getParams().getParams(CommonParams.FQ)); diff --git a/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java b/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java index 70dd1a401f2..75cb568ff05 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java +++ b/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java @@ -31,15 +31,24 @@ import java.util.Objects; import java.util.Set; import java.util.TreeMap; +import org.apache.lucene.search.Explanation; import org.apache.lucene.search.Query; +import org.apache.lucene.search.Sort; import org.apache.solr.common.SolrDocumentList; +import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; +import org.apache.solr.common.util.StrUtils; import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.schema.IndexSchema; import org.apache.solr.search.DocList; +import org.apache.solr.search.QParser; +import org.apache.solr.search.QueryCommand; import org.apache.solr.search.QueryParsing; import org.apache.solr.search.SolrIndexSearcher; +import org.apache.solr.search.SortSpecParsing; +import org.apache.solr.search.SyntaxError; import org.apache.solr.search.facet.FacetDebugInfo; import org.apache.solr.search.stats.StatsCache; import org.apache.solr.util.SolrPluginUtils; @@ -90,7 +99,7 @@ public void process(ResponseBuilder rb) throws IOException { } NamedList stdinfo = - SolrPluginUtils.doStandardDebug( + doStandardDebug( rb.req, rb.getQueryString(), rb.wrap(rb.getQuery()), @@ -251,7 +260,7 @@ public void finishStage(ResponseBuilder rb) { info = new SimpleOrderedMap<>(); } // No responses were received from shards. Show local query info. - SolrPluginUtils.doStandardQueryDebug( + doStandardQueryDebug( rb.req, rb.getQueryString(), rb.wrap(rb.getQuery()), rb.isDebugQuery(), info); if (rb.isDebugQuery() && rb.getQparser() != null) { rb.getQparser().addDebugInfo(info); @@ -376,6 +385,125 @@ protected Object merge(Object source, Object dest, Set exclude) { return t; } + /** + * Returns a NamedList containing many "standard" pieces of debugging information. + * + *
    + *
  • rawquerystring - the 'q' param exactly as specified by the client + *
  • querystring - the 'q' param after any preprocessing done by the plugin + *
  • parsedquery - the main query executed formated by the Solr QueryParsing utils class + * (which knows about field types) + *
  • parsedquery_toString - the main query executed formatted by its own toString method (in + * case it has internal state Solr doesn't know about) + *
  • explain - the list of score explanations for each document in results against query. + *
  • otherQuery - the query string specified in 'explainOther' query param. + *
  • explainOther - the list of score explanations for each document in results against + * 'otherQuery' + *
+ * + * @param req the request we are dealing with + * @param userQuery the users query as a string, after any basic preprocessing has been done + * @param query the query built from the userQuery (and perhaps other clauses) that identifies the + * main result set of the response. + * @param results the main result set of the response + * @return The debug info + * @throws java.io.IOException if there was an IO error + */ + public static NamedList doStandardDebug( + SolrQueryRequest req, + String userQuery, + Query query, + DocList results, + boolean dbgQuery, + boolean dbgResults) + throws IOException { + NamedList dbg = new SimpleOrderedMap<>(); + doStandardQueryDebug(req, userQuery, query, dbgQuery, dbg); + doStandardResultsDebug(req, query, results, dbgResults, dbg); + return dbg; + } + + public static void doStandardQueryDebug( + SolrQueryRequest req, + String userQuery, + Query query, + boolean dbgQuery, + NamedList dbg) { + if (dbgQuery) { + /* userQuery may have been pre-processed .. expose that */ + dbg.add("rawquerystring", req.getParams().get(CommonParams.Q)); + dbg.add("querystring", userQuery); + + /* QueryParsing.toString isn't perfect, use it to see converted + * values, use regular toString to see any attributes of the + * underlying Query it may have missed. + */ + dbg.add("parsedquery", QueryParsing.toString(query, req.getSchema())); + dbg.add("parsedquery_toString", query.toString()); + } + } + + public static void doStandardResultsDebug( + SolrQueryRequest req, Query query, DocList results, boolean dbgResults, NamedList dbg) + throws IOException { + if (dbgResults) { + SolrIndexSearcher searcher = req.getSearcher(); + IndexSchema schema = searcher.getSchema(); + boolean explainStruct = req.getParams().getBool(CommonParams.EXPLAIN_STRUCT, false); + + if (results != null) { + NamedList explain = + SolrPluginUtils.getExplanations(query, results, searcher, schema); + dbg.add( + "explain", + explainStruct + ? SolrPluginUtils.explanationsToNamedLists(explain) + : SolrPluginUtils.explanationsToStrings(explain)); + } + + String otherQueryS = req.getParams().get(CommonParams.EXPLAIN_OTHER); + if (otherQueryS != null && otherQueryS.length() > 0) { + DocList otherResults = doSimpleQuery(otherQueryS, req, 0, 10); + dbg.add("otherQuery", otherQueryS); + NamedList explainO = + SolrPluginUtils.getExplanations(query, otherResults, searcher, schema); + dbg.add( + "explainOther", + explainStruct + ? SolrPluginUtils.explanationsToNamedLists(explainO) + : SolrPluginUtils.explanationsToStrings(explainO)); + } + } + } + + /** Executes a basic query */ + public static DocList doSimpleQuery(String sreq, SolrQueryRequest req, int start, int limit) + throws IOException { + List commands = StrUtils.splitSmart(sreq, ';'); + + String qs = commands.size() >= 1 ? commands.get(0) : ""; + try { + Query query = QParser.getParser(qs, req).getQuery(); + + // If the first non-query, non-filter command is a simple sort on an indexed field, then + // we can use the Lucene sort ability. + Sort sort = null; + if (commands.size() >= 2) { + sort = SortSpecParsing.parseSortSpec(commands.get(1), req).getSort(); + } + + return new QueryCommand() + .setQuery(query) + .setSort(sort) + .setOffset(start) + .setLen(limit) + .search(req.getSearcher()) + .getDocList(); + } catch (SyntaxError e) { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing query: " + qs); + } + } + ///////////////////////////////////////////// /// SolrInfoBean //////////////////////////////////////////// diff --git a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java index ed6178be4f9..f6bb5dec657 100644 --- a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java +++ b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java @@ -74,7 +74,6 @@ import org.apache.solr.search.DocList; import org.apache.solr.search.FieldParams; import org.apache.solr.search.QParser; -import org.apache.solr.search.QueryCommand; import org.apache.solr.search.QueryParsing; import org.apache.solr.search.ReturnFields; import org.apache.solr.search.SolrDocumentFetcher; @@ -279,94 +278,6 @@ public static Set getDebugInterests(String[] params, ResponseBuilder rb) return debugInterests; } - /** - * Returns a NamedList containing many "standard" pieces of debugging information. - * - *
    - *
  • rawquerystring - the 'q' param exactly as specified by the client - *
  • querystring - the 'q' param after any preprocessing done by the plugin - *
  • parsedquery - the main query executed formated by the Solr QueryParsing utils class - * (which knows about field types) - *
  • parsedquery_toString - the main query executed formatted by its own toString method (in - * case it has internal state Solr doesn't know about) - *
  • explain - the list of score explanations for each document in results against query. - *
  • otherQuery - the query string specified in 'explainOther' query param. - *
  • explainOther - the list of score explanations for each document in results against - * 'otherQuery' - *
- * - * @param req the request we are dealing with - * @param userQuery the users query as a string, after any basic preprocessing has been done - * @param query the query built from the userQuery (and perhaps other clauses) that identifies the - * main result set of the response. - * @param results the main result set of the response - * @return The debug info - * @throws java.io.IOException if there was an IO error - */ - @Deprecated // move to DebugComponent - public static NamedList doStandardDebug( - SolrQueryRequest req, - String userQuery, - Query query, - DocList results, - boolean dbgQuery, - boolean dbgResults) - throws IOException { - NamedList dbg = new SimpleOrderedMap<>(); - doStandardQueryDebug(req, userQuery, query, dbgQuery, dbg); - doStandardResultsDebug(req, query, results, dbgResults, dbg); - return dbg; - } - - @Deprecated // move to DebugComponent - public static void doStandardQueryDebug( - SolrQueryRequest req, - String userQuery, - Query query, - boolean dbgQuery, - NamedList dbg) { - if (dbgQuery) { - /* userQuery may have been pre-processed .. expose that */ - dbg.add("rawquerystring", req.getParams().get(CommonParams.Q)); - dbg.add("querystring", userQuery); - - /* QueryParsing.toString isn't perfect, use it to see converted - * values, use regular toString to see any attributes of the - * underlying Query it may have missed. - */ - dbg.add("parsedquery", QueryParsing.toString(query, req.getSchema())); - dbg.add("parsedquery_toString", query.toString()); - } - } - - @Deprecated - public static void doStandardResultsDebug( - SolrQueryRequest req, Query query, DocList results, boolean dbgResults, NamedList dbg) - throws IOException { - if (dbgResults) { - SolrIndexSearcher searcher = req.getSearcher(); - IndexSchema schema = searcher.getSchema(); - boolean explainStruct = req.getParams().getBool(CommonParams.EXPLAIN_STRUCT, false); - - if (results != null) { - NamedList explain = getExplanations(query, results, searcher, schema); - dbg.add( - "explain", - explainStruct ? explanationsToNamedLists(explain) : explanationsToStrings(explain)); - } - - String otherQueryS = req.getParams().get(CommonParams.EXPLAIN_OTHER); - if (otherQueryS != null && otherQueryS.length() > 0) { - DocList otherResults = doSimpleQuery(otherQueryS, req, 0, 10); - dbg.add("otherQuery", otherQueryS); - NamedList explainO = getExplanations(query, otherResults, searcher, schema); - dbg.add( - "explainOther", - explainStruct ? explanationsToNamedLists(explainO) : explanationsToStrings(explainO)); - } - } - } - public static NamedList explanationToNamedList(Explanation e) { NamedList out = new SimpleOrderedMap<>(); @@ -422,7 +333,7 @@ public static NamedList getExplanations( return explainList; } - private static NamedList explanationsToStrings(NamedList explanations) { + public static NamedList explanationsToStrings(NamedList explanations) { NamedList out = new SimpleOrderedMap<>(); for (Map.Entry entry : explanations) { @@ -431,35 +342,6 @@ private static NamedList explanationsToStrings(NamedList ex return out; } - /** Executes a basic query */ - @Deprecated - public static DocList doSimpleQuery(String sreq, SolrQueryRequest req, int start, int limit) - throws IOException { - List commands = StrUtils.splitSmart(sreq, ';'); - - String qs = commands.size() >= 1 ? commands.get(0) : ""; - try { - Query query = QParser.getParser(qs, req).getQuery(); - - // If the first non-query, non-filter command is a simple sort on an indexed field, then - // we can use the Lucene sort ability. - Sort sort = null; - if (commands.size() >= 2) { - sort = SortSpecParsing.parseSortSpec(commands.get(1), req).getSort(); - } - - return new QueryCommand() - .setQuery(query) - .setSort(sort) - .setOffset(start) - .setLen(limit) - .search(req.getSearcher()) - .getDocList(); - } catch (SyntaxError e) { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing query: " + qs); - } - } - private static final Pattern whitespacePattern = Pattern.compile("\\s+"); private static final Pattern caratPattern = Pattern.compile("\\^"); private static final Pattern tildePattern = Pattern.compile("[~]");