SOLR-5973: Pluggable Ranking Collectors and Merge Strategies

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1597775 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Joel Bernstein 2014-05-27 13:19:15 +00:00
parent 95fd2943eb
commit 1b9c63fc9d
8 changed files with 51 additions and 25 deletions

View File

@ -23,8 +23,10 @@ import java.util.Comparator;
import java.io.IOException;
/**
* The MergeStrategy class defines custom merge logic for distributed searches.
**/
* The MergeStrategy class defines custom merge logic for distributed searches.
*
* <b>Note: This API is experimental and may change in non backward-compatible ways in the future</b>
**/
public interface MergeStrategy {

View File

@ -151,17 +151,28 @@ public class QueryComponent extends SearchComponent
q = new BooleanQuery();
}
if(q instanceof RankQuery) {
MergeStrategy mergeStrategy = ((RankQuery)q).getMergeStrategy();
if(mergeStrategy != null) {
rb.addMergeStrategy(mergeStrategy);
if(mergeStrategy.handlesMergeFields()) {
rb.mergeFieldHandler = mergeStrategy;
rb.setQuery( q );
String rankQueryString = rb.req.getParams().get(CommonParams.RQ);
if(rankQueryString != null) {
QParser rqparser = QParser.getParser(rankQueryString, defType, req);
Query rq = rqparser.getQuery();
if(rq instanceof RankQuery) {
RankQuery rankQuery = (RankQuery)rq;
rb.setQuery(rankQuery.wrap(q)); //Wrap the RankQuery around the main query.
MergeStrategy mergeStrategy = rankQuery.getMergeStrategy();
if(mergeStrategy != null) {
rb.addMergeStrategy(mergeStrategy);
if(mergeStrategy.handlesMergeFields()) {
rb.mergeFieldHandler = mergeStrategy;
}
}
} else {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"rq parameter must be a RankQuery");
}
}
rb.setQuery( q );
rb.setSortSpec( parser.getSort(true) );
rb.setQparser(parser);

View File

@ -17,13 +17,21 @@
package org.apache.solr.search;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TopDocsCollector;
import org.apache.lucene.search.Query;
import org.apache.solr.handler.component.MergeStrategy;
import java.io.IOException;
/**
* <b>Note: This API is experimental and may change in non backward-compatible ways in the future</b>
**/
public abstract class RankQuery extends Query {
public abstract TopDocsCollector getTopDocsCollector(int len, SolrIndexSearcher.QueryCommand cmd);
public abstract TopDocsCollector getTopDocsCollector(int len, SolrIndexSearcher.QueryCommand cmd, IndexSearcher searcher) throws IOException;
public abstract MergeStrategy getMergeStrategy();
public abstract RankQuery wrap(Query mainQuery);
}

View File

@ -1503,7 +1503,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable,SolrIn
Query q = cmd.getQuery();
if(q instanceof RankQuery) {
RankQuery rq = (RankQuery)q;
return rq.getTopDocsCollector(len, cmd);
return rq.getTopDocsCollector(len, cmd, this);
}
if (null == cmd.getSort()) {

View File

@ -80,18 +80,18 @@ public class MergeStrategyTest extends BaseDistributedSearchTestCase {
handle.put("_version_", SKIP);
//Test mergeStrategy that uses score
query("q", "{!rank q=$qq}", "qq", "*:*", "rows","12", "sort", "sort_i asc", "fl","*,score");
query("rq", "{!rank}", "q", "*:*", "rows","12", "sort", "sort_i asc", "fl","*,score");
//Test without mergeStrategy
query("q", "*:*", "rows","12", "sort", "sort_i asc");
//Test mergeStrategy1 that uses a sort field.
query("q", "{!rank mergeStrategy=1 q=$qq}", "qq", "*:*", "rows","12", "sort", "sort_i asc");
query("rq", "{!rank mergeStrategy=1}", "q", "*:*", "rows","12", "sort", "sort_i asc");
ModifiableSolrParams params = new ModifiableSolrParams();
params.add("qq", "*:*");
params.add("q", "*:*");
params.add("rows", "12");
params.add("q", "{!rank q=$qq}");
params.add("rq", "{!rank}");
params.add("sort", "sort_i asc");
params.add("fl","*,score");
setDistributedParams(params);

View File

@ -70,8 +70,8 @@ public class RankQueryTest extends SolrTestCaseJ4 {
ModifiableSolrParams params = new ModifiableSolrParams();
params.add("qq", "*:*");
params.add("q", "{!rank q=$qq}");
params.add("q", "*:*");
params.add("rq", "{!rank}");
params.add("sort","sort_i asc");
assertQ(req(params), "*[count(//doc)=6]",
@ -84,9 +84,9 @@ public class RankQueryTest extends SolrTestCaseJ4 {
);
params = new ModifiableSolrParams();
params.add("qq", "{!edismax bf=$bff}*:*");
params.add("q", "{!edismax bf=$bff}*:*");
params.add("bff", "field(sort_i)");
params.add("q", "{!rank q=$qq collector=1}");
params.add("rq", "{!rank collector=1}");
assertQ(req(params), "*[count(//doc)=6]",
"//result/doc[6]/str[@name='id'][.='4']",

View File

@ -85,12 +85,10 @@ public class TestRankQueryPlugin extends QParserPlugin {
}
public Query parse() throws SyntaxError {
String qs = localParams.get("q");
QParser parser = QParser.getParser(qs, null, req);
Query q = parser.getQuery();
int mergeStrategy = localParams.getInt("mergeStrategy", 0);
int collector = localParams.getInt("collector", 0);
return new TestRankQuery(collector, mergeStrategy, q);
return new TestRankQuery(collector, mergeStrategy);
}
}
@ -134,13 +132,17 @@ public class TestRankQueryPlugin extends QParserPlugin {
return q.toString(field);
}
public TestRankQuery(int collector, int mergeStrategy, Query q) {
public RankQuery wrap(Query q) {
this.q = q;
return this;
}
public TestRankQuery(int collector, int mergeStrategy) {
this.collector = collector;
this.mergeStrategy = mergeStrategy;
}
public TopDocsCollector getTopDocsCollector(int len, SolrIndexSearcher.QueryCommand cmd) {
public TopDocsCollector getTopDocsCollector(int len, SolrIndexSearcher.QueryCommand cmd, IndexSearcher searcher) {
if(collector == 0)
return new TestCollector(null);
else

View File

@ -47,6 +47,9 @@ public interface CommonParams {
/** query string */
public static final String Q ="q";
/** rank query */
public static final String RQ ="rq";
/** distrib string */
public static final String DISTRIB = "distrib";