SOLR-1665: Add more control to debug via options for timings, etc.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@990577 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Grant Ingersoll 2010-08-29 13:16:56 +00:00
parent 13fd70521a
commit 0bb2e73041
13 changed files with 397 additions and 223 deletions

View File

@ -249,7 +249,8 @@ New Features
* SOLR-2059: Add "types" attribute to WordDelimiterFilterFactory, which * SOLR-2059: Add "types" attribute to WordDelimiterFilterFactory, which
allows you to customize how WordDelimiterFilter tokenizes text with allows you to customize how WordDelimiterFilter tokenizes text with
a configuration file. (Peter Karich, rmuir) a configuration file. (Peter Karich, rmuir)
* SOLR-1665: Add debug component options for timings, results and query info only (gsingers, hossman, yonik)
Optimizations Optimizations
---------------------- ----------------------

View File

@ -58,8 +58,28 @@ public interface CommonParams {
/** default query field */ /** default query field */
public static final String DF = "df"; public static final String DF = "df";
/** whether to include debug data */ /** whether to include debug data for all components pieces, including doing explains*/
public static final String DEBUG_QUERY = "debugQuery"; public static final String DEBUG_QUERY = "debugQuery";
/**
* Whether to provide debug info for specific items.
*
* @see #DEBUG_QUERY
*/
public static final String DEBUG = "debug";
/**
* {@link #DEBUG} value indicating an interest in debug output related to timing
*/
public static final String TIMING = "timing";
/**
* {@link #DEBUG} value indicating an interest in debug output related to the results (explains)
*/
public static final String RESULTS = "results";
/**
* {@link #DEBUG} value indicating an interest in debug output related to the Query (parsing, etc.)
*/
public static final String QUERY = "query";
/** /**
* boolean indicating whether score explanations should structured (true), * boolean indicating whether score explanations should structured (true),

View File

@ -23,9 +23,12 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
@ -56,6 +59,7 @@ import org.apache.solr.search.DocList;
import org.apache.solr.search.DocListAndSet; import org.apache.solr.search.DocListAndSet;
import org.apache.solr.search.QueryParsing; import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.util.SolrPluginUtils; import org.apache.solr.util.SolrPluginUtils;
/** /**
@ -192,24 +196,41 @@ public class MoreLikeThisHandler extends RequestHandlerBase
rsp.add( "facet_counts", f.getFacetCounts() ); rsp.add( "facet_counts", f.getFacetCounts() );
} }
} }
boolean dbg = req.getParams().getBool(CommonParams.DEBUG_QUERY, false);
// Copied from StandardRequestHandler... perhaps it should be added to doStandardDebug?
try { boolean dbgQuery = false, dbgResults = false;
NamedList<Object> dbg = SolrPluginUtils.doStandardDebug(req, q, mlt.mltquery, mltDocs.docList ); if (dbg == false){//if it's true, we are doing everything anyway.
if (null != dbg) { String[] dbgParams = req.getParams().getParams(CommonParams.DEBUG);
if (null != filters) { for (int i = 0; i < dbgParams.length; i++) {
dbg.add("filter_queries",req.getParams().getParams(CommonParams.FQ)); if (dbgParams[i].equals(CommonParams.QUERY)){
List<String> fqs = new ArrayList<String>(filters.size()); dbgQuery = true;
for (Query fq : filters) { } else if (dbgParams[i].equals(CommonParams.RESULTS)){
fqs.add(QueryParsing.toString(fq, req.getSchema())); dbgResults = true;
}
dbg.add("parsed_filter_queries",fqs);
} }
rsp.add("debug", dbg);
} }
} catch (Exception e) { } else {
SolrException.logOnce(SolrCore.log, "Exception during debug", e); dbgQuery = true;
rsp.add("exception_during_debug", SolrException.toStr(e)); dbgResults = true;
}
// Copied from StandardRequestHandler... perhaps it should be added to doStandardDebug?
if (dbg == true) {
try {
NamedList<Object> dbgInfo = SolrPluginUtils.doStandardDebug(req, q, mlt.mltquery, mltDocs.docList, dbgQuery, dbgResults);
if (null != dbgInfo) {
if (null != filters) {
dbgInfo.add("filter_queries",req.getParams().getParams(CommonParams.FQ));
List<String> fqs = new ArrayList<String>(filters.size());
for (Query fq : filters) {
fqs.add(QueryParsing.toString(fq, req.getSchema()));
}
dbgInfo.add("parsed_filter_queries",fqs);
}
rsp.add("debug", dbgInfo);
}
} catch (Exception e) {
SolrException.logOnce(SolrCore.log, "Exception during debug", e);
rsp.add("exception_during_debug", SolrException.toStr(e));
}
} }
} }

View File

@ -18,7 +18,8 @@
package org.apache.solr.handler.component; package org.apache.solr.handler.component;
import static org.apache.solr.common.params.CommonParams.FQ; import static org.apache.solr.common.params.CommonParams.FQ;
import org.apache.solr.common.params.HighlightParams;
import org.apache.solr.common.params.CommonParams;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
@ -51,8 +52,9 @@ public class DebugComponent extends SearchComponent
public void process(ResponseBuilder rb) throws IOException public void process(ResponseBuilder rb) throws IOException
{ {
if( rb.isDebug() ) { if( rb.isDebug() ) {
NamedList stdinfo = SolrPluginUtils.doStandardDebug( rb.req, NamedList stdinfo = SolrPluginUtils.doStandardDebug( rb.req,
rb.getQueryString(), rb.getQuery(), rb.getResults().docList); rb.getQueryString(), rb.getQuery(), rb.getResults().docList, rb.isDebugQuery(), rb.isDebugResults());
NamedList info = rb.getDebugInfo(); NamedList info = rb.getDebugInfo();
if( info == null ) { if( info == null ) {
@ -63,12 +65,12 @@ public class DebugComponent extends SearchComponent
info.addAll( stdinfo ); info.addAll( stdinfo );
} }
if (rb.getQparser() != null) { if (rb.isDebugQuery() && rb.getQparser() != null) {
rb.getQparser().addDebugInfo(rb.getDebugInfo()); rb.getQparser().addDebugInfo(rb.getDebugInfo());
} }
if (null != rb.getDebugInfo() ) { if (null != rb.getDebugInfo() ) {
if (null != rb.getFilters() ) { if (rb.isDebugQuery() && null != rb.getFilters() ) {
info.add("filter_queries",rb.req.getParams().getParams(FQ)); info.add("filter_queries",rb.req.getParams().getParams(FQ));
List<String> fqs = new ArrayList<String>(rb.getFilters().size()); List<String> fqs = new ArrayList<String>(rb.getFilters().size());
for (Query fq : rb.getFilters()) { for (Query fq : rb.getFilters()) {
@ -90,9 +92,9 @@ public class DebugComponent extends SearchComponent
// Turn on debug to get explain only when retrieving fields // Turn on debug to get explain only when retrieving fields
if ((sreq.purpose & ShardRequest.PURPOSE_GET_FIELDS) != 0) { if ((sreq.purpose & ShardRequest.PURPOSE_GET_FIELDS) != 0) {
sreq.purpose |= ShardRequest.PURPOSE_GET_DEBUG; sreq.purpose |= ShardRequest.PURPOSE_GET_DEBUG;
sreq.params.set("debugQuery", "true"); sreq.params.set(CommonParams.DEBUG_QUERY, "true");
} else { } else {
sreq.params.set("debugQuery", "false"); sreq.params.set(CommonParams.DEBUG_QUERY, "false");
} }
} }

View File

@ -30,7 +30,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.QueryElevationParams; import org.apache.solr.common.params.QueryElevationParams;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -406,7 +408,9 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore
SimpleOrderedMap<Object> dbg = new SimpleOrderedMap<Object>(); SimpleOrderedMap<Object> dbg = new SimpleOrderedMap<Object>();
dbg.add( "q", qstr ); dbg.add( "q", qstr );
dbg.add( "match", match ); dbg.add( "match", match );
rb.addDebugInfo( "queryBoosting", dbg ); if (rb.isDebugQuery()) {
rb.addDebugInfo("queryBoosting", dbg );
}
} }
} }

View File

@ -26,11 +26,15 @@ import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.DocListAndSet; import org.apache.solr.search.DocListAndSet;
import org.apache.solr.search.QParser; import org.apache.solr.search.QParser;
import org.apache.solr.search.SortSpec;
import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SortSpec;
import org.apache.solr.util.SolrPluginUtils;
import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* This class is experimental and will be changing in the future. * This class is experimental and will be changing in the future.
@ -38,8 +42,9 @@ import java.util.Map;
* @version $Id$ * @version $Id$
* @since solr 1.3 * @since solr 1.3
*/ */
public class ResponseBuilder public class ResponseBuilder {
{
public SolrQueryRequest req; public SolrQueryRequest req;
public SolrQueryResponse rsp; public SolrQueryResponse rsp;
public boolean doHighlights; public boolean doHighlights;
@ -50,7 +55,8 @@ public class ResponseBuilder
private boolean needDocList = false; private boolean needDocList = false;
private boolean needDocSet = false; private boolean needDocSet = false;
private int fieldFlags = 0; private int fieldFlags = 0;
private boolean debug = false; //private boolean debug = false;
private boolean debugTimings, debugQuery, debugResults;
private QParser qparser = null; private QParser qparser = null;
private String queryString = null; private String queryString = null;
@ -76,20 +82,21 @@ public class ResponseBuilder
public static final String SHARDS = "shards"; public static final String SHARDS = "shards";
public static final String IDS = "ids"; public static final String IDS = "ids";
/*** /**
public static final String NUMDOCS = "nd"; * public static final String NUMDOCS = "nd";
public static final String DOCFREQS = "tdf"; * public static final String DOCFREQS = "tdf";
public static final String TERMS = "terms"; * public static final String TERMS = "terms";
public static final String EXTRACT_QUERY_TERMS = "eqt"; * public static final String EXTRACT_QUERY_TERMS = "eqt";
public static final String LOCAL_SHARD = "local"; * public static final String LOCAL_SHARD = "local";
public static final String DOC_QUERY = "dq"; * public static final String DOC_QUERY = "dq";
***/ * *
*/
public static int STAGE_START = 0; public static int STAGE_START = 0;
public static int STAGE_PARSE_QUERY = 1000; public static int STAGE_PARSE_QUERY = 1000;
public static int STAGE_EXECUTE_QUERY = 2000; public static int STAGE_EXECUTE_QUERY = 2000;
public static int STAGE_GET_FIELDS = 3000; public static int STAGE_GET_FIELDS = 3000;
public static int STAGE_DONE = Integer.MAX_VALUE; public static int STAGE_DONE = Integer.MAX_VALUE;
public int stage; // What stage is this current request at? public int stage; // What stage is this current request at?
@ -102,15 +109,15 @@ public class ResponseBuilder
public int getShardNum(String shard) { public int getShardNum(String shard) {
for (int i=0; i<shards.length; i++) { for (int i = 0; i < shards.length; i++) {
if (shards[i]==shard || shards[i].equals(shard)) return i; if (shards[i] == shard || shards[i].equals(shard)) return i;
} }
return -1; return -1;
} }
public void addRequest(SearchComponent me, ShardRequest sreq) { public void addRequest(SearchComponent me, ShardRequest sreq) {
outgoing.add(sreq); outgoing.add(sreq);
if ((sreq.purpose & ShardRequest.PURPOSE_PRIVATE)==0) { if ((sreq.purpose & ShardRequest.PURPOSE_PRIVATE) == 0) {
// if this isn't a private request, let other components modify it. // if this isn't a private request, let other components modify it.
for (SearchComponent component : components) { for (SearchComponent component : components) {
if (component != me) { if (component != me) {
@ -151,11 +158,37 @@ public class ResponseBuilder
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
public boolean isDebug() { public boolean isDebug() {
return debug; return debugQuery || debugTimings || debugResults;
}
public void setDebug(boolean dbg){
debugQuery = dbg;
debugTimings = dbg;
debugResults = dbg;
} }
public void setDebug(boolean debug) { public boolean isDebugTimings() {
this.debug = debug; return debugTimings;
}
public void setDebugTimings(boolean debugTimings) {
this.debugTimings = debugTimings;
}
public boolean isDebugQuery() {
return debugQuery;
}
public void setDebugQuery(boolean debugQuery) {
this.debugQuery = debugQuery;
}
public boolean isDebugResults() {
return debugResults;
}
public void setDebugResults(boolean debugResults) {
this.debugResults = debugResults;
} }
public NamedList<Object> getDebugInfo() { public NamedList<Object> getDebugInfo() {
@ -272,23 +305,23 @@ public class ResponseBuilder
*/ */
public SolrIndexSearcher.QueryCommand getQueryCommand() { public SolrIndexSearcher.QueryCommand getQueryCommand() {
SolrIndexSearcher.QueryCommand cmd = new SolrIndexSearcher.QueryCommand(); SolrIndexSearcher.QueryCommand cmd = new SolrIndexSearcher.QueryCommand();
cmd.setQuery( getQuery() ) cmd.setQuery(getQuery())
.setFilterList( getFilters() ) .setFilterList(getFilters())
.setSort( getSortSpec().getSort() ) .setSort(getSortSpec().getSort())
.setOffset( getSortSpec().getOffset() ) .setOffset(getSortSpec().getOffset())
.setLen( getSortSpec().getCount() ) .setLen(getSortSpec().getCount())
.setFlags( getFieldFlags() ) .setFlags(getFieldFlags())
.setNeedDocSet( isNeedDocSet() ); .setNeedDocSet(isNeedDocSet());
return cmd; return cmd;
} }
/** /**
* Sets results from a SolrIndexSearcher.QueryResult. * Sets results from a SolrIndexSearcher.QueryResult.
*/ */
public void setResult( SolrIndexSearcher.QueryResult result ) { public void setResult(SolrIndexSearcher.QueryResult result) {
setResults( result.getDocListAndSet() ); setResults(result.getDocListAndSet());
if( result.isPartialResults() ) { if (result.isPartialResults()) {
rsp.getResponseHeader().add( "partialResults", Boolean.TRUE ); rsp.getResponseHeader().add("partialResults", Boolean.TRUE);
} }
} }
} }

View File

@ -20,7 +20,6 @@ package org.apache.solr.handler.component;
import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.RTimer; import org.apache.solr.common.util.RTimer;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.ShardParams; import org.apache.solr.common.params.ShardParams;
@ -32,7 +31,8 @@ import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrResponse; import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
import org.apache.solr.util.SolrPluginUtils;
import org.apache.solr.util.plugin.SolrCoreAware; import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.ParseException;
@ -175,7 +175,11 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware
rb.req = req; rb.req = req;
rb.rsp = rsp; rb.rsp = rsp;
rb.components = components; rb.components = components;
rb.setDebug(req.getParams().getBool(CommonParams.DEBUG_QUERY, false)); boolean dbg = req.getParams().getBool(CommonParams.DEBUG_QUERY, false);
rb.setDebug(dbg);
if (dbg == false){//if it's true, we are doing everything anyway.
SolrPluginUtils.getDebugInterests(req.getParams().getParams(CommonParams.DEBUG), rb);
}
final RTimer timer = rb.isDebug() ? new RTimer() : null; final RTimer timer = rb.isDebug() ? new RTimer() : null;
@ -218,10 +222,9 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware
timer.stop(); timer.stop();
// add the timing info // add the timing info
if( rb.getDebugInfo() == null ) { if (rb.isDebugTimings()) {
rb.setDebugInfo( new SimpleOrderedMap<Object>() ); rb.addDebugInfo("timing", timer.asNamedList() );
} }
rb.getDebugInfo().add( "timing", timer.asNamedList() );
} }
} else { } else {

View File

@ -22,7 +22,6 @@ import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.*; import org.apache.lucene.search.*;
import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.index.LogByteSizeMergePolicy;
import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
@ -34,6 +33,7 @@ import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.StrUtils;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.highlight.SolrHighlighter; import org.apache.solr.highlight.SolrHighlighter;
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.response.SolrQueryResponse;
@ -61,7 +61,7 @@ import java.lang.reflect.InvocationTargetException;
* <p>:TODO: refactor StandardRequestHandler to use these utilities</p> * <p>:TODO: refactor StandardRequestHandler to use these utilities</p>
* *
* <p>:TODO: Many "standard" functionality methods are not cognisant of * <p>:TODO: Many "standard" functionality methods are not cognisant of
* default parameter settings. * default parameter settings.
*/ */
public class SolrPluginUtils { public class SolrPluginUtils {
final static Logger log = LoggerFactory.getLogger( SolrPluginUtils.class ); final static Logger log = LoggerFactory.getLogger( SolrPluginUtils.class );
@ -75,7 +75,7 @@ public class SolrPluginUtils {
public static void setDefaults(SolrQueryRequest req, SolrParams defaults) { public static void setDefaults(SolrQueryRequest req, SolrParams defaults) {
setDefaults(req, defaults, null, null); setDefaults(req, defaults, null, null);
} }
/** /**
* Set default-ish params on a SolrQueryRequest. * Set default-ish params on a SolrQueryRequest.
* *
@ -89,7 +89,7 @@ public class SolrPluginUtils {
*/ */
public static void setDefaults(SolrQueryRequest req, SolrParams defaults, public static void setDefaults(SolrQueryRequest req, SolrParams defaults,
SolrParams appends, SolrParams invariants) { SolrParams appends, SolrParams invariants) {
SolrParams p = req.getParams(); SolrParams p = req.getParams();
if (defaults != null) { if (defaults != null) {
p = new DefaultSolrParams(p,defaults); p = new DefaultSolrParams(p,defaults);
@ -120,16 +120,16 @@ public class SolrPluginUtils {
throws IOException { throws IOException {
return (null == f) ? s.getDocSet(q).size() : s.numDocs(q,f); return (null == f) ? s.getDocSet(q).size() : s.numDocs(q,f);
} }
/** /**
* Returns the param, or the default if it's empty or not specified. * Returns the param, or the default if it's empty or not specified.
* @deprecated use SolrParam.get(String,String) * @deprecated use SolrParam.get(String,String)
*/ */
public static String getParam(SolrQueryRequest req, public static String getParam(SolrQueryRequest req,
String param, String def) { String param, String def) {
String v = req.getParam(param); String v = req.getParam(param);
// Note: parameters passed but given only white-space value are // Note: parameters passed but given only white-space value are
// considered equivalent to passing nothing for that parameter. // considered equivalent to passing nothing for that parameter.
@ -138,7 +138,7 @@ public class SolrPluginUtils {
} }
return v; return v;
} }
/** /**
* Treats the param value as a Number, returns the default if nothing is * Treats the param value as a Number, returns the default if nothing is
* there or if it's not a number. * there or if it's not a number.
@ -146,7 +146,7 @@ public class SolrPluginUtils {
*/ */
public static Number getNumberParam(SolrQueryRequest req, public static Number getNumberParam(SolrQueryRequest req,
String param, Number def) { String param, Number def) {
Number r = def; Number r = def;
String v = req.getParam(param); String v = req.getParam(param);
if (null == v || "".equals(v.trim())) { if (null == v || "".equals(v.trim())) {
@ -159,23 +159,23 @@ public class SolrPluginUtils {
} }
return r; return r;
} }
/** /**
* Treats parameter value as a boolean. The string 'false' is false; * Treats parameter value as a boolean. The string 'false' is false;
* any other non-empty string is true. * any other non-empty string is true.
* @deprecated use SolrParam.getBool(String,boolean) * @deprecated use SolrParam.getBool(String,boolean)
*/ */
public static boolean getBooleanParam(SolrQueryRequest req, public static boolean getBooleanParam(SolrQueryRequest req,
String param, boolean def) { String param, boolean def) {
String v = req.getParam(param); String v = req.getParam(param);
if (null == v || "".equals(v.trim())) { if (null == v || "".equals(v.trim())) {
return def; return def;
} }
return !"false".equals(v.trim()); return !"false".equals(v.trim());
} }
private final static Pattern splitList=Pattern.compile(",| "); private final static Pattern splitList=Pattern.compile(",| ");
/** Split a value that may contain a comma, space of bar separated list. */ /** Split a value that may contain a comma, space of bar separated list. */
public static String[] split(String value){ public static String[] split(String value){
return splitList.split(value.trim(), 0); return splitList.split(value.trim(), 0);
@ -226,7 +226,7 @@ public class SolrPluginUtils {
* <ul> * <ul>
* <li>Locates the document-retrieval costs in one spot, which helps * <li>Locates the document-retrieval costs in one spot, which helps
* detailed performance measurement</li> * detailed performance measurement</li>
* *
* <li>Determines a priori what fields will be needed to be fetched by * <li>Determines a priori what fields will be needed to be fetched by
* various subtasks, like response writing and highlighting. This * various subtasks, like response writing and highlighting. This
* minimizes the chance that many needed fields will be loaded lazily. * minimizes the chance that many needed fields will be loaded lazily.
@ -253,13 +253,13 @@ public class SolrPluginUtils {
// add highlight fields // add highlight fields
SolrHighlighter highligher = req.getCore().getHighlighter(); SolrHighlighter highligher = req.getCore().getHighlighter();
if(highligher.isHighlightingEnabled(req.getParams())) { if(highligher.isHighlightingEnabled(req.getParams())) {
for(String field: highligher.getHighlightFields(query, req, null)) for(String field: highligher.getHighlightFields(query, req, null))
fieldFilter.add(field); fieldFilter.add(field);
} }
// fetch unique key if one exists. // fetch unique key if one exists.
SchemaField keyField = req.getSearcher().getSchema().getUniqueKeyField(); SchemaField keyField = req.getSearcher().getSchema().getUniqueKeyField();
if(null != keyField) if(null != keyField)
fieldFilter.add(keyField.getName()); fieldFilter.add(keyField.getName());
} }
// get documents // get documents
@ -269,85 +269,26 @@ public class SolrPluginUtils {
} }
} }
/**
* <p>
* Returns a NamedList containing many "standard" pieces of debugging
* information.
* </p>
*
* <ul>
* <li>rawquerystring - the 'q' param exactly as specified by the client
* </li>
* <li>querystring - the 'q' param after any preprocessing done by the plugin
* </li>
* <li>parsedquery - the main query executed formated by the Solr
* QueryParsing utils class (which knows about field types)
* </li>
* <li>parsedquery_toString - the main query executed formated by it's
* own toString method (in case it has internal state Solr
* doesn't know about)
* </li>
* <li>expain - the list of score explanations for each document in
* results against query.
* </li>
* <li>otherQuery - the query string specified in 'explainOther' query param.
* </li>
* <li>explainOther - the list of score explanations for each document in
* results against 'otherQuery'
* </li>
* </ul>
*
* @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
* @deprecated Use doStandardDebug(SolrQueryRequest,String,Query,DocList) with setDefaults
*/
public static NamedList doStandardDebug(SolrQueryRequest req,
String userQuery,
Query query,
DocList results,
org.apache.solr.util.CommonParams params)
throws IOException {
String debug = getParam(req, CommonParams.DEBUG_QUERY, params.debugQuery);
NamedList dbg = null; public static Set<String> getDebugInterests(String[] params, ResponseBuilder rb){
if (debug!=null) { Set<String> debugInterests = new HashSet<String>();
dbg = new SimpleOrderedMap(); if (params != null) {
for (int i = 0; i < params.length; i++) {
/* userQuery may have been pre-processes .. expose that */ if (params[i].equalsIgnoreCase("all") || params[i].equalsIgnoreCase("true")){
dbg.add("rawquerystring", req.getQueryString()); rb.setDebug(true);
dbg.add("querystring", userQuery); break;
//still might add others
/* QueryParsing.toString isn't perfect, use it to see converted } else if (params[i].equals(CommonParams.TIMING)){
* values, use regular toString to see any attributes of the rb.setDebugTimings(true);
* underlying Query it may have missed. } else if (params[i].equals(CommonParams.QUERY)){
*/ rb.setDebugQuery(true);
dbg.add("parsedquery",QueryParsing.toString(query, req.getSchema())); } else if (params[i].equals(CommonParams.RESULTS)){
dbg.add("parsedquery_toString", query.toString()); rb.setDebugResults(true);
}
dbg.add("explain", getExplainList
(query, results, req.getSearcher(), req.getSchema()));
String otherQueryS = req.getParam("explainOther");
if (otherQueryS != null && otherQueryS.length() > 0) {
DocList otherResults = doSimpleQuery
(otherQueryS,req.getSearcher(), req.getSchema(),0,10);
dbg.add("otherQuery",otherQueryS);
dbg.add("explainOther", getExplainList
(query, otherResults,
req.getSearcher(),
req.getSchema()));
} }
} }
return debugInterests;
return dbg;
} }
/** /**
* <p> * <p>
* Returns a NamedList containing many "standard" pieces of debugging * Returns a NamedList containing many "standard" pieces of debugging
@ -383,55 +324,59 @@ public class SolrPluginUtils {
* (and perhaps other clauses) that identifies the main * (and perhaps other clauses) that identifies the main
* result set of the response. * result set of the response.
* @param results 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, public static NamedList doStandardDebug(SolrQueryRequest req,
String userQuery, String userQuery,
Query query, Query query,
DocList results) DocList results, boolean dbgQuery, boolean dbgResults)
throws IOException { throws IOException {
String debug = req.getParams().get(CommonParams.DEBUG_QUERY);
NamedList dbg = null; NamedList dbg = null;
if (debug!=null) {
dbg = new SimpleOrderedMap();
SolrIndexSearcher searcher = req.getSearcher(); dbg = new SimpleOrderedMap();
IndexSchema schema = req.getSchema();
boolean explainStruct SolrIndexSearcher searcher = req.getSearcher();
= req.getParams().getBool(CommonParams.EXPLAIN_STRUCT,false); IndexSchema schema = req.getSchema();
/* userQuery may have been pre-processes .. expose that */ boolean explainStruct
= req.getParams().getBool(CommonParams.EXPLAIN_STRUCT, false);
/* userQuery may have been pre-processes .. expose that */
if (dbgQuery) {
dbg.add("rawquerystring", req.getParams().get(CommonParams.Q)); dbg.add("rawquerystring", req.getParams().get(CommonParams.Q));
dbg.add("querystring", userQuery); dbg.add("querystring", userQuery);
/* QueryParsing.toString isn't perfect, use it to see converted /* QueryParsing.toString isn't perfect, use it to see converted
* values, use regular toString to see any attributes of the * values, use regular toString to see any attributes of the
* underlying Query it may have missed. * underlying Query it may have missed.
*/ */
dbg.add("parsedquery",QueryParsing.toString(query, schema)); dbg.add("parsedquery", QueryParsing.toString(query, schema));
dbg.add("parsedquery_toString", query.toString()); dbg.add("parsedquery_toString", query.toString());
}
NamedList<Explanation> explain if (dbgResults) {
= getExplanations(query, results, searcher, schema); NamedList<Explanation> explain
= getExplanations(query, results, searcher, schema);
dbg.add("explain", explainStruct ? dbg.add("explain", explainStruct ?
explanationsToNamedLists(explain) : explanationsToNamedLists(explain) :
explanationsToStrings(explain)); explanationsToStrings(explain));
String otherQueryS = req.getParams().get(CommonParams.EXPLAIN_OTHER); String otherQueryS = req.getParams().get(CommonParams.EXPLAIN_OTHER);
if (otherQueryS != null && otherQueryS.length() > 0) { if (otherQueryS != null && otherQueryS.length() > 0) {
DocList otherResults = doSimpleQuery DocList otherResults = doSimpleQuery
(otherQueryS,req.getSearcher(), req.getSchema(),0,10); (otherQueryS, req.getSearcher(), req.getSchema(), 0, 10);
dbg.add("otherQuery",otherQueryS); dbg.add("otherQuery", otherQueryS);
NamedList<Explanation> explainO NamedList<Explanation> explainO
= getExplanations(query, otherResults, searcher, schema); = getExplanations(query, otherResults, searcher, schema);
dbg.add("explainOther", explainStruct ? dbg.add("explainOther", explainStruct ?
explanationsToNamedLists(explainO) : explanationsToNamedLists(explainO) :
explanationsToStrings(explainO)); explanationsToStrings(explainO));
} }
} }
return dbg; return dbg;
} }
@ -456,11 +401,11 @@ public class SolrPluginUtils {
return out; return out;
} }
public static NamedList<NamedList<Object>> explanationsToNamedLists public static NamedList<NamedList<Object>> explanationsToNamedLists
(NamedList<Explanation> explanations) { (NamedList<Explanation> explanations) {
NamedList<NamedList<Object>> out NamedList<NamedList<Object>> out
= new SimpleOrderedMap<NamedList<Object>>(); = new SimpleOrderedMap<NamedList<Object>>();
for (Map.Entry<String,Explanation> entry : explanations) { for (Map.Entry<String,Explanation> entry : explanations) {
out.add(entry.getKey(), explanationToNamedList(entry.getValue())); out.add(entry.getKey(), explanationToNamedList(entry.getValue()));
@ -475,11 +420,11 @@ public class SolrPluginUtils {
* @param docs The Documents you want explained relative that query * @param docs The Documents you want explained relative that query
*/ */
public static NamedList<Explanation> getExplanations public static NamedList<Explanation> getExplanations
(Query query, (Query query,
DocList docs, DocList docs,
SolrIndexSearcher searcher, SolrIndexSearcher searcher,
IndexSchema schema) throws IOException { IndexSchema schema) throws IOException {
NamedList<Explanation> explainList = new SimpleOrderedMap<Explanation>(); NamedList<Explanation> explainList = new SimpleOrderedMap<Explanation>();
DocIterator iterator = docs.iterator(); DocIterator iterator = docs.iterator();
for (int i=0; i<docs.size(); i++) { for (int i=0; i<docs.size(); i++) {
@ -508,8 +453,8 @@ public class SolrPluginUtils {
* *
* @param query The Query you want explanations in the context of * @param query The Query you want explanations in the context of
* @param docs The Documents you want explained relative that query * @param docs The Documents you want explained relative that query
* @deprecated this returns the explanations as Strings, instead it * @deprecated this returns the explanations as Strings, instead it
* is recommeded to use getExplanations and call toString() * is recommeded to use getExplanations and call toString()
* yourself, or use explanationsToNamedLists * yourself, or use explanationsToNamedLists
*/ */
@Deprecated @Deprecated
@ -543,7 +488,7 @@ public class SolrPluginUtils {
DocList results = searcher.getDocList(query,(DocSet)null, sort, start, limit); DocList results = searcher.getDocList(query,(DocSet)null, sort, start, limit);
return results; return results;
} }
/** /**
* Given a string containing fieldNames and boost info, * Given a string containing fieldNames and boost info,
* converts it to a Map from field name to boost info. * converts it to a Map from field name to boost info.
@ -596,7 +541,7 @@ public class SolrPluginUtils {
*/ */
public static List<Query> parseFuncs(IndexSchema s, String in) public static List<Query> parseFuncs(IndexSchema s, String in)
throws ParseException { throws ParseException {
Map<String,Float> ff = parseFieldBoosts(in); Map<String,Float> ff = parseFieldBoosts(in);
List<Query> funcs = new ArrayList<Query>(ff.keySet().size()); List<Query> funcs = new ArrayList<Query>(ff.keySet().size());
for (String f : ff.keySet()) { for (String f : ff.keySet()) {
@ -610,7 +555,7 @@ public class SolrPluginUtils {
return funcs; return funcs;
} }
/** /**
* Checks the number of optional clauses in the query, and compares it * Checks the number of optional clauses in the query, and compares it
* with the specification string to determine the proper value to use. * with the specification string to determine the proper value to use.
@ -662,11 +607,11 @@ public class SolrPluginUtils {
static int calculateMinShouldMatch(int optionalClauseCount, String spec) { static int calculateMinShouldMatch(int optionalClauseCount, String spec) {
int result = optionalClauseCount; int result = optionalClauseCount;
if (-1 < spec.indexOf("<")) { if (-1 < spec.indexOf("<")) {
/* we have conditional spec(s) */ /* we have conditional spec(s) */
for (String s : spec.trim().split(" ")) { for (String s : spec.trim().split(" ")) {
String[] parts = s.split("<"); String[] parts = s.split("<");
int upperBound = (new Integer(parts[0])).intValue(); int upperBound = (new Integer(parts[0])).intValue();
@ -694,10 +639,10 @@ public class SolrPluginUtils {
return (optionalClauseCount < result ? return (optionalClauseCount < result ?
optionalClauseCount : (result < 0 ? 0 : result)); optionalClauseCount : (result < 0 ? 0 : result));
} }
/** /**
* Recursively walks the "from" query pulling out sub-queries and * Recursively walks the "from" query pulling out sub-queries and
* adding them to the "to" query. * adding them to the "to" query.
@ -711,17 +656,17 @@ public class SolrPluginUtils {
public static void flattenBooleanQuery(BooleanQuery to, BooleanQuery from) { public static void flattenBooleanQuery(BooleanQuery to, BooleanQuery from) {
for (BooleanClause clause : (List<BooleanClause>)from.clauses()) { for (BooleanClause clause : (List<BooleanClause>)from.clauses()) {
Query cq = clause.getQuery(); Query cq = clause.getQuery();
cq.setBoost(cq.getBoost() * from.getBoost()); cq.setBoost(cq.getBoost() * from.getBoost());
if (cq instanceof BooleanQuery if (cq instanceof BooleanQuery
&& !clause.isRequired() && !clause.isRequired()
&& !clause.isProhibited()) { && !clause.isProhibited()) {
/* we can recurse */ /* we can recurse */
flattenBooleanQuery(to, (BooleanQuery)cq); flattenBooleanQuery(to, (BooleanQuery)cq);
} else { } else {
to.add(clause); to.add(clause);
} }
@ -753,7 +698,7 @@ public class SolrPluginUtils {
private final static Pattern DANGLING_OP_PATTERN = Pattern.compile( "\\s+[-+\\s]+$" ); private final static Pattern DANGLING_OP_PATTERN = Pattern.compile( "\\s+[-+\\s]+$" );
// Pattern to detect consecutive + and/or - operators // Pattern to detect consecutive + and/or - operators
// \s+[+-](?:\s*[+-]+)+ // \s+[+-](?:\s*[+-]+)+
private final static Pattern CONSECUTIVE_OP_PATTERN = Pattern.compile( "\\s+[+-](?:\\s*[+-]+)+" ); private final static Pattern CONSECUTIVE_OP_PATTERN = Pattern.compile( "\\s+[+-](?:\\s*[+-]+)+" );
/** /**
* Strips operators that are used illegally, otherwise reuturns it's * Strips operators that are used illegally, otherwise reuturns it's
@ -844,9 +789,9 @@ public class SolrPluginUtils {
*/ */
protected Query getFieldQuery(String field, String queryText, boolean quoted) protected Query getFieldQuery(String field, String queryText, boolean quoted)
throws ParseException { throws ParseException {
if (aliases.containsKey(field)) { if (aliases.containsKey(field)) {
Alias a = aliases.get(field); Alias a = aliases.get(field);
DisjunctionMaxQuery q = new DisjunctionMaxQuery(a.tie); DisjunctionMaxQuery q = new DisjunctionMaxQuery(a.tie);
@ -854,7 +799,7 @@ public class SolrPluginUtils {
* in which case we should return null * in which case we should return null
*/ */
boolean ok = false; boolean ok = false;
for (String f : a.fields.keySet()) { for (String f : a.fields.keySet()) {
Query sub = getFieldQuery(f,queryText,quoted); Query sub = getFieldQuery(f,queryText,quoted);
@ -876,7 +821,7 @@ public class SolrPluginUtils {
} }
} }
} }
} }
/** /**
@ -906,7 +851,7 @@ public class SolrPluginUtils {
SolrCore.log.warn("Invalid sort \""+sort+"\" was specified, ignoring", sortE); SolrCore.log.warn("Invalid sort \""+sort+"\" was specified, ignoring", sortE);
return null; return null;
} }
return ss; return ss;
} }
@ -923,8 +868,8 @@ public class SolrPluginUtils {
* *
* @return null if no queries are generated * @return null if no queries are generated
*/ */
public static List<Query> parseQueryStrings(SolrQueryRequest req, public static List<Query> parseQueryStrings(SolrQueryRequest req,
String[] queries) throws ParseException { String[] queries) throws ParseException {
if (null == queries || 0 == queries.length) return null; if (null == queries || 0 == queries.length) return null;
List<Query> out = new ArrayList<Query>(queries.length); List<Query> out = new ArrayList<Query>(queries.length);
for (String q : queries) { for (String q : queries) {
@ -971,9 +916,9 @@ public class SolrPluginUtils {
* @since solr 1.4 * @since solr 1.4
*/ */
public static SolrDocumentList docListToSolrDocumentList( public static SolrDocumentList docListToSolrDocumentList(
DocList docs, DocList docs,
SolrIndexSearcher searcher, SolrIndexSearcher searcher,
Set<String> fields, Set<String> fields,
Map<SolrDocument, Integer> ids ) throws IOException Map<SolrDocument, Integer> ids ) throws IOException
{ {
DocumentBuilder db = new DocumentBuilder(searcher.getSchema()); DocumentBuilder db = new DocumentBuilder(searcher.getSchema());
@ -1011,12 +956,12 @@ public class SolrPluginUtils {
/** /**
* Given a SolrQueryResponse replace the DocList if it is in the result. * Given a SolrQueryResponse replace the DocList if it is in the result.
* Otherwise add it to the response * Otherwise add it to the response
* *
* @since solr 1.4 * @since solr 1.4
*/ */
public static void addOrReplaceResults(SolrQueryResponse rsp, SolrDocumentList docs) public static void addOrReplaceResults(SolrQueryResponse rsp, SolrDocumentList docs)
{ {
NamedList vals = rsp.getValues(); NamedList vals = rsp.getValues();
int idx = vals.indexOf( "response", 0 ); int idx = vals.indexOf( "response", 0 );
@ -1029,7 +974,7 @@ public class SolrPluginUtils {
vals.add( "response", docs ); vals.add( "response", docs );
} }
} }
public static void invokeSetters(Object bean, NamedList initArgs) { public static void invokeSetters(Object bean, NamedList initArgs) {
if (initArgs == null) return; if (initArgs == null) return;
Class clazz = bean.getClass(); Class clazz = bean.getClass();
@ -1042,7 +987,7 @@ public class SolrPluginUtils {
Method method = null; Method method = null;
try { try {
for (Method m : methods) { for (Method m : methods) {
if (m.getName().equals(setterName) && m.getParameterTypes().length == 1) { if (m.getName().equals(setterName) && m.getParameterTypes().length == 1) {
method = m; method = m;
break; break;
} }

View File

@ -271,7 +271,7 @@ public class BasicFunctionalityTest extends SolrTestCaseJ4 {
assertQ(req("text:hello") assertQ(req("text:hello")
,"//*[@numFound='2']" ,"//*[@numFound='2']"
); );
String resp = h.query(lrf.makeRequest("q", "text:hello", "debugQuery", "true")); String resp = h.query(lrf.makeRequest("q", "text:hello", CommonParams.DEBUG_QUERY, "true"));
//System.out.println(resp); //System.out.println(resp);
// second doc ranked first // second doc ranked first
assertTrue( resp.indexOf("\"2\"") < resp.indexOf("\"1\"") ); assertTrue( resp.indexOf("\"2\"") < resp.indexOf("\"1\"") );
@ -290,7 +290,7 @@ public class BasicFunctionalityTest extends SolrTestCaseJ4 {
assertQ(req("text:hello"), assertQ(req("text:hello"),
"//*[@numFound='2']" "//*[@numFound='2']"
); );
String resp = h.query(lrf.makeRequest("q", "text:hello", "debugQuery", "true")); String resp = h.query(lrf.makeRequest("q", "text:hello", CommonParams.DEBUG_QUERY, "true"));
//System.out.println(resp); //System.out.println(resp);
// second doc ranked first // second doc ranked first
assertTrue( resp.indexOf("\"2\"") < resp.indexOf("\"1\"") ); assertTrue( resp.indexOf("\"2\"") < resp.indexOf("\"1\"") );

View File

@ -17,6 +17,7 @@
package org.apache.solr; package org.apache.solr;
import org.apache.solr.common.params.CommonParams;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -120,7 +121,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
,"version", "2.0" ,"version", "2.0"
,"bq", "subject:hell^400" ,"bq", "subject:hell^400"
,"bq", "subject:cool^4" ,"bq", "subject:cool^4"
,"debugQuery", "true" , CommonParams.DEBUG_QUERY, "true"
) )
,"//*[@numFound='3']" ,"//*[@numFound='3']"
,"//result/doc[1]/int[@name='id'][.='666']" ,"//result/doc[1]/int[@name='id'][.='666']"
@ -179,7 +180,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
,"qt", "dismax" ,"qt", "dismax"
,"version", "2.0" ,"version", "2.0"
,"bq", "subject:hell OR subject:cool" ,"bq", "subject:hell OR subject:cool"
,"debugQuery", "true" ,CommonParams.DEBUG_QUERY, "true"
)); ));
assertTrue(p.matcher(resp).find()); assertTrue(p.matcher(resp).find());
assertFalse(p_bool.matcher(resp).find()); assertFalse(p_bool.matcher(resp).find());
@ -189,7 +190,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
,"version", "2.0" ,"version", "2.0"
,"bq", "subject:hell OR subject:cool" ,"bq", "subject:hell OR subject:cool"
,"bq","" ,"bq",""
,"debugQuery", "true" ,CommonParams.DEBUG_QUERY, "true"
)); ));
assertTrue(p.matcher(resp).find()); assertTrue(p.matcher(resp).find());
assertTrue(p_bool.matcher(resp).find()); assertTrue(p_bool.matcher(resp).find());

View File

@ -20,6 +20,7 @@ package org.apache.solr;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.params.CommonParams;
/** /**
* TODO? perhaps use: * TODO? perhaps use:
@ -133,7 +134,7 @@ public class TestDistributedSearch extends BaseDistributedSearchTestCase {
handle.put("time", SKIPVAL); handle.put("time", SKIPVAL);
query("q","now their fox sat had put","fl","*,score", query("q","now their fox sat had put","fl","*,score",
"debugQuery", "true"); CommonParams.DEBUG_QUERY, "true");
// TODO: This test currently fails because debug info is obtained only // TODO: This test currently fails because debug info is obtained only
// on shards with matches. // on shards with matches.

View File

@ -0,0 +1,142 @@
package org.apache.solr.handler.component;
/**
* 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.
*/
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.CommonParams;
import org.junit.BeforeClass;
import org.junit.Test;
/**
*
*
**/
public class DebugComponentTest extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml", "schema.xml");
assertU(adoc("id", "1", "title", "this is a title."));
assertU(adoc("id", "2", "title", "this is another title."));
assertU(adoc("id", "3", "title", "Mary had a little lamb."));
assertU(commit());
}
@Test
public void testBasicInterface() throws Exception {
//make sure the basics are in place
assertQ(req("q", "*:*", CommonParams.DEBUG_QUERY, "true"),
"//str[@name='rawquerystring']='*:*'",
"//str[@name='querystring']='*:*'",
"//str[@name='parsedquery']='MatchAllDocsQuery(*:*)'",
"//str[@name='parsedquery_toString']='*:*'",
"count(//lst[@name='explain']/*)=3",
"//lst[@name='explain']/str[@name='1']",
"//lst[@name='explain']/str[@name='2']",
"//lst[@name='explain']/str[@name='3']",
"//str[@name='QParser']",// make sure the QParser is specified
"count(//lst[@name='timing']/*)=3", //should be three pieces to timings
"//lst[@name='timing']/double[@name='time']", //make sure we have a time value, but don't specify it's result
"count(//lst[@name='prepare']/*)>0",
"//lst[@name='prepare']/double[@name='time']",
"count(//lst[@name='process']/*)>0",
"//lst[@name='process']/double[@name='time']"
);
}
// Test the ability to specify which pieces to include
@Test
public void testPerItemInterface() throws Exception {
//Same as debugQuery = true
assertQ(req("q", "*:*", "debug", "true"),
"//str[@name='rawquerystring']='*:*'",
"//str[@name='querystring']='*:*'",
"//str[@name='parsedquery']='MatchAllDocsQuery(*:*)'",
"//str[@name='parsedquery_toString']='*:*'",
"//str[@name='QParser']",// make sure the QParser is specified
"count(//lst[@name='explain']/*)=3",
"//lst[@name='explain']/str[@name='1']",
"//lst[@name='explain']/str[@name='2']",
"//lst[@name='explain']/str[@name='3']",
"count(//lst[@name='timing']/*)=3", //should be three pieces to timings
"//lst[@name='timing']/double[@name='time']", //make sure we have a time value, but don't specify it's result
"count(//lst[@name='prepare']/*)>0",
"//lst[@name='prepare']/double[@name='time']",
"count(//lst[@name='process']/*)>0",
"//lst[@name='process']/double[@name='time']"
);
//timing only
assertQ(req("q", "*:*", "debug", CommonParams.TIMING),
"count(//str[@name='rawquerystring'])=0",
"count(//str[@name='querystring'])=0",
"count(//str[@name='parsedquery'])=0",
"count(//str[@name='parsedquery_toString'])=0",
"count(//lst[@name='explain']/*)=0",
"count(//str[@name='QParser'])=0",// make sure the QParser is specified
"count(//lst[@name='timing']/*)=3", //should be three pieces to timings
"//lst[@name='timing']/double[@name='time']", //make sure we have a time value, but don't specify it's result
"count(//lst[@name='prepare']/*)>0",
"//lst[@name='prepare']/double[@name='time']",
"count(//lst[@name='process']/*)>0",
"//lst[@name='process']/double[@name='time']"
);
//query only
assertQ(req("q", "*:*", "debug", CommonParams.QUERY),
"//str[@name='rawquerystring']='*:*'",
"//str[@name='querystring']='*:*'",
"//str[@name='parsedquery']='MatchAllDocsQuery(*:*)'",
"//str[@name='parsedquery_toString']='*:*'",
"count(//lst[@name='explain']/*)=0",
"//str[@name='QParser']",// make sure the QParser is specified
"count(//lst[@name='timing']/*)=0"
);
//explains
assertQ(req("q", "*:*", "debug", CommonParams.RESULTS),
"count(//str[@name='rawquerystring'])=0",
"count(//str[@name='querystring'])=0",
"count(//str[@name='parsedquery'])=0",
"count(//str[@name='parsedquery_toString'])=0",
"count(//lst[@name='explain']/*)=3",
"//lst[@name='explain']/str[@name='1']",
"//lst[@name='explain']/str[@name='2']",
"//lst[@name='explain']/str[@name='3']",
"count(//str[@name='QParser'])=0",// make sure the QParser is specified
"count(//lst[@name='timing']/*)=0"
);
assertQ(req("q", "*:*", "debug", CommonParams.RESULTS,
"debug", CommonParams.QUERY),
"//str[@name='rawquerystring']='*:*'",
"//str[@name='querystring']='*:*'",
"//str[@name='parsedquery']='MatchAllDocsQuery(*:*)'",
"//str[@name='parsedquery_toString']='*:*'",
"//str[@name='QParser']",// make sure the QParser is specified
"count(//lst[@name='explain']/*)=3",
"//lst[@name='explain']/str[@name='1']",
"//lst[@name='explain']/str[@name='2']",
"//lst[@name='explain']/str[@name='3']",
"count(//lst[@name='timing']/*)=0"
);
}
}

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.solr.search; package org.apache.solr.search;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.util.AbstractSolrTestCase; import org.apache.solr.util.AbstractSolrTestCase;
public class TestQueryTypes extends AbstractSolrTestCase { public class TestQueryTypes extends AbstractSolrTestCase {
@ -262,7 +263,7 @@ public class TestQueryTypes extends AbstractSolrTestCase {
,"qf","v_t" ,"qf","v_t"
,"bf","sqrt(v_f)^100 log(sum(v_f,1))^50" ,"bf","sqrt(v_f)^100 log(sum(v_f,1))^50"
,"bq","{!prefix f=v_t}he" ,"bq","{!prefix f=v_t}he"
,"debugQuery","on" , CommonParams.DEBUG_QUERY,"on"
) )
,"//result[@numFound='2']" ,"//result[@numFound='2']"
); );