diff --git a/solr/core/src/java/org/apache/solr/handler/component/MergeStrategy.java b/solr/core/src/java/org/apache/solr/handler/component/MergeStrategy.java index 0ff19bd523e..8c3483be422 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/MergeStrategy.java +++ b/solr/core/src/java/org/apache/solr/handler/component/MergeStrategy.java @@ -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. +* +* Note: This API is experimental and may change in non backward-compatible ways in the future +**/ public interface MergeStrategy { 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 ac2689b9d17..83a55afc38c 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 @@ -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); diff --git a/solr/core/src/java/org/apache/solr/search/RankQuery.java b/solr/core/src/java/org/apache/solr/search/RankQuery.java index da8c00a1387..86ee49a11cb 100644 --- a/solr/core/src/java/org/apache/solr/search/RankQuery.java +++ b/solr/core/src/java/org/apache/solr/search/RankQuery.java @@ -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; + +/** + * Note: This API is experimental and may change in non backward-compatible ways in the future + **/ + 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); } \ No newline at end of file diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java index 50e82bf352d..44a5e89b47e 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -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()) { diff --git a/solr/core/src/test/org/apache/solr/search/MergeStrategyTest.java b/solr/core/src/test/org/apache/solr/search/MergeStrategyTest.java index 68b8c9e8a7d..19bc9f0056d 100644 --- a/solr/core/src/test/org/apache/solr/search/MergeStrategyTest.java +++ b/solr/core/src/test/org/apache/solr/search/MergeStrategyTest.java @@ -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); diff --git a/solr/core/src/test/org/apache/solr/search/RankQueryTest.java b/solr/core/src/test/org/apache/solr/search/RankQueryTest.java index 8f749861907..c98e62ba575 100644 --- a/solr/core/src/test/org/apache/solr/search/RankQueryTest.java +++ b/solr/core/src/test/org/apache/solr/search/RankQueryTest.java @@ -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']", diff --git a/solr/core/src/test/org/apache/solr/search/TestRankQueryPlugin.java b/solr/core/src/test/org/apache/solr/search/TestRankQueryPlugin.java index 267b7e923f4..cea0185daa1 100644 --- a/solr/core/src/test/org/apache/solr/search/TestRankQueryPlugin.java +++ b/solr/core/src/test/org/apache/solr/search/TestRankQueryPlugin.java @@ -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 diff --git a/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java b/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java index 4256abe60a7..0f122c54fbd 100644 --- a/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java +++ b/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java @@ -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";