This is an automated email from the ASF dual-hosted git repository. dsmiley pushed a commit to branch branch_9x in repository https://gitbox.apache.org/repos/asf/solr.git
commit e9340cdb8bd1e97c296d53ffae42586dabfde758 Author: Sonu Sharma <[email protected]> AuthorDate: Sat Jun 6 09:26:03 2026 +0530 SOLR-18271: QueryElevation support for Combined Query feature (#4476) Adds QueryElevationComponent support to the Combined Query feature, so that elevated docIds (via elevateIds / configured elevations) are honored when results from multiple subqueries are combined and merged across shards. (cherry picked from commit f24dd94794619f7ab991dda7124427708c285d2c) --- .../SOLR-18271-query-elevation-combined-query.yml | 8 +++ .../handler/component/CombinedQueryComponent.java | 1 + .../handler/component/QueryElevationComponent.java | 42 +++++++++++- .../collection1/conf/solrconfig-combined-query.xml | 15 ++++- .../component/CombinedQuerySolrCloudTest.java | 74 +++++++++++++++++----- .../DistributedCombinedQueryComponentTest.java | 63 ++++++++++++++---- 6 files changed, 169 insertions(+), 34 deletions(-) diff --git a/changelog/unreleased/SOLR-18271-query-elevation-combined-query.yml b/changelog/unreleased/SOLR-18271-query-elevation-combined-query.yml new file mode 100644 index 00000000000..a2acaa2e623 --- /dev/null +++ b/changelog/unreleased/SOLR-18271-query-elevation-combined-query.yml @@ -0,0 +1,8 @@ +title: Support for using Query Elevation with CombinedQueryComponent (RRF) +type: added +authors: + - name: Sonu Sharma + nick: ercsonusharma +links: + - name: SOLR-18271 + url: https://issues.apache.org/jira/browse/SOLR-18271 diff --git a/solr/core/src/java/org/apache/solr/handler/component/CombinedQueryComponent.java b/solr/core/src/java/org/apache/solr/handler/component/CombinedQueryComponent.java index 1d2a86746a5..699fe8d2fd8 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/CombinedQueryComponent.java +++ b/solr/core/src/java/org/apache/solr/handler/component/CombinedQueryComponent.java @@ -153,6 +153,7 @@ public class CombinedQueryComponent extends QueryComponent implements SolrCoreAw final var unparsedQuery = params.get(queryKey); ResponseBuilder rbNew = new ResponseBuilder(rb.req, new SolrQueryResponse(), rb.components); rbNew.setQueryString(unparsedQuery); + rbNew.setDebug(rb.isDebug()); super.prepare(rbNew); crb.setFilters(rbNew.getFilters()); crb.responseBuilders.add(rbNew); diff --git a/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java b/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java index c7bef72294c..2e07653ab99 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java +++ b/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java @@ -112,6 +112,7 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore @VisibleForTesting static final String FIELD_TYPE = "queryFieldType"; @VisibleForTesting static final String CONFIG_FILE = "config-file"; private static final String EXCLUDE = "exclude"; + private static final String DEBUG_QUERY_BOOSTING = "queryBoosting"; /** * @see #getBoostDocs(SolrIndexSearcher, Set, Map) @@ -488,6 +489,45 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore return; } + if (rb instanceof CombinedQueryResponseBuilder) { + prepareCombined((CombinedQueryResponseBuilder) rb); + } else { + prepareElevationComponent(rb); + } + } + + /** + * Elevates each subquery and mirrors the resulting SortSpec/filters onto the parent crb so {@link + * CombinedQueryComponent#mergeIds} can read {@code _elevate_} from each shard's {@code + * sort_values_i} during distributed merge. + */ + private void prepareCombined(CombinedQueryResponseBuilder crb) throws IOException { + if (crb.responseBuilders.isEmpty()) { + return; + } + for (ResponseBuilder thisRb : crb.responseBuilders) { + prepareElevationComponent(thisRb); + } + // Subqueries get identical elevation treatment, so any one is representative. + ResponseBuilder representative = crb.responseBuilders.get(0); + crb.setSortSpec(representative.getSortSpec()); + crb.setFilters(representative.getFilters()); + + if (crb.isDebug() && crb.isDebugQuery()) { + List<Object> debugPerSubquery = new ArrayList<>(crb.responseBuilders.size()); + for (ResponseBuilder thisRb : crb.responseBuilders) { + Object queryBoosting = thisRb.getDebugInfo().get(DEBUG_QUERY_BOOSTING); + if (queryBoosting != null) { + debugPerSubquery.add(queryBoosting); + } + } + if (!debugPerSubquery.isEmpty()) { + crb.addDebugInfo(DEBUG_QUERY_BOOSTING, debugPerSubquery); + } + } + } + + private void prepareElevationComponent(ResponseBuilder rb) throws IOException { Elevation elevation = getElevation(rb); if (elevation != null) { setQuery(rb, elevation); @@ -771,7 +811,7 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore SimpleOrderedMap<Object> dbg = new SimpleOrderedMap<>(); dbg.add("q", rb.getQueryString()); dbg.add("match", match); - rb.addDebugInfo("queryBoosting", dbg); + rb.addDebugInfo(DEBUG_QUERY_BOOSTING, dbg); } // --------------------------------------------------------------------------------- diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-combined-query.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-combined-query.xml index b96ff9cd687..35908f42195 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-combined-query.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-combined-query.xml @@ -98,7 +98,18 @@ <requestHandler name="/search" class="solr.CombinedQuerySearchHandler"> </requestHandler> - <searchComponent class="solr.CombinedQueryComponent" name="combined_query"> + <requestHandler name="/search-elevate" class="solr.CombinedQuerySearchHandler"> + <arr name="last-components"> + <str>elevator</str> + </arr> + </requestHandler> + + <searchComponent name="elevator" class="solr.QueryElevationComponent">> + <str name="queryFieldType">string</str> + <str name="config-file">elevate.xml</str> + </searchComponent> + + <searchComponent class="solr.CombinedQueryComponent" name="combined_query"> <int name="maxCombinerQueries">2</int> <lst name="combiners"> <lst name="test"> @@ -159,7 +170,7 @@ </highlighting> </searchComponent> - <initParams path="/select,/search"> + <initParams path="/select,/search,/search-elevate"> <lst name="defaults"> <str name="df">text</str> </lst> diff --git a/solr/core/src/test/org/apache/solr/handler/component/CombinedQuerySolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/component/CombinedQuerySolrCloudTest.java index 1173e2cf51e..3c5f56261ec 100644 --- a/solr/core/src/test/org/apache/solr/handler/component/CombinedQuerySolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/component/CombinedQuerySolrCloudTest.java @@ -16,12 +16,15 @@ */ package org.apache.solr.handler.component; +import static org.apache.solr.cloud.AbstractZkTestCase.SOLRHOME; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.cloud.AbstractFullDistribZkTestBase; +import org.apache.solr.cloud.ZkTestServer; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ShardParams; @@ -49,6 +52,12 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { configString = "solrconfig-combined-query.xml"; } + @Override + public void distribSetUp() throws Exception { + super.distribSetUp(); + ZkTestServer.putConfig("conf1", zkServer.getZkClient(), SOLRHOME, "elevate.xml"); + } + @Override protected String getCloudSchemaFile() { return "schema-vector-catchall.xml"; @@ -121,7 +130,7 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { query( CommonParams.JSON, "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:2^10\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:2^=10\"}}}," + "\"limit\":5," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\"]}}", @@ -141,8 +150,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":5," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; @@ -161,8 +170,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^1 OR 5^2 OR 7^3 OR 10^1)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":5,\"sort\":\"mod3_idv desc, score desc\"" + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; @@ -183,8 +192,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { query( CommonParams.JSON, "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}", CommonParams.QT, @@ -194,8 +203,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { query( CommonParams.JSON, "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":4," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}", @@ -206,8 +215,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { query( CommonParams.JSON, "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":4,\"offset\":3," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}", @@ -227,7 +236,7 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}}," + + "{\"lexical\":{\"lucene\":{\"query\":\"id:(2^=2 OR 3^=1 OR 6^=2 OR 5^=1)\"}}}," + "\"limit\":3,\"offset\":1" + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"facet\":true,\"facet.field\":\"mod3_idv\",\"facet.mincount\":1," @@ -248,8 +257,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(8^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":4," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"facet\":true,\"facet.field\":\"mod3_idv\"," @@ -269,6 +278,38 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { rsp.getHighlighting().get("5").get("title").get(0)); } + /** + * Tests the combined query feature with faceting, highlighting and elevation. + * + * @throws Exception if any unexpected error occurs during the test execution. + */ + @Test + public void testElevatedQueriesWithFacetAndHighlights() throws Exception { + prepareIndexDocs(); + String jsonQuery = + "{\"queries\": {" + + "\"lexical1\": {\"lucene\": {\"query\": \"id:(2^=3 OR 3^=1 OR 6^=2 OR 5^=2)\"}}," + + "\"lexical2\": {\"lucene\": {\"query\": \"id:(4^=1 OR 5^=2 OR 7^=3 OR 10^=2)\"}}}," + + "\"limit\": 4," + + "\"fields\": [\"id\", \"score\", \"title\"]," + + "\"params\": {\"combiner\": true, \"elevateIds\": \"6,10\"," + + "\"combiner.query\": [\"lexical1\", \"lexical2\"]," + + "\"facet\": true, \"facet.field\": \"mod3_idv\"," + + "\"hl\": true, \"hl.fl\": \"title\", \"hl.q\": \"test doc\"}}"; + QueryResponse rsp = query(CommonParams.JSON, jsonQuery, CommonParams.QT, "/search-elevate"); + assertEquals(4, rsp.getResults().size()); + assertFieldValues(rsp.getResults(), id, "6", "10", "5", "7"); + assertEquals("mod3_idv", rsp.getFacetFields().get(0).getName()); + assertEquals("[1 (3), 0 (2), 2 (2)]", rsp.getFacetFields().get(0).getValues().toString()); + assertEquals(4, rsp.getHighlighting().size()); + assertEquals( + "title <em>test</em> for <em>doc</em> 10", + rsp.getHighlighting().get("10").get("title").get(0)); + assertEquals( + "title <em>test</em> for <em>doc</em> 5", + rsp.getHighlighting().get("5").get("title").get(0)); + } + /** * Tests the combined query feature with faceting, highlighting and collapse. * @@ -280,9 +321,8 @@ public class CombinedQuerySolrCloudTest extends AbstractFullDistribZkTestBase { prepareIndexDocsColocated(); String jsonQuery = "{\"queries\": {" - + "\"lexical1\": {\"lucene\": {\"query\": \"id:(CO!2^3 OR CO!3^1 OR CO!6^2 OR CO!5^1)\"}}," - + "\"lexical2\": {\"lucene\": {\"query\": \"id:(CO!8^1 OR CO!5^2 OR CO!7^3 OR CO!10^2)\"}}" - + "}," + + "\"lexical1\": {\"lucene\": {\"query\": \"id:(CO!2^=3 OR CO!3^=1 OR CO!6^=2 OR CO!5^=1)\"}}," + + "\"lexical2\": {\"lucene\": {\"query\": \"id:(CO!8^=1 OR CO!5^=2 OR CO!7^=3 OR CO!10^=2)\"}}}," + "\"limit\": 3," + "\"fields\": [\"id\", \"score\", \"title\"]," + "\"params\": {\"combiner\": true, \"facet\": true, \"facet.field\": \"id\"," diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java index e6b2805236f..f45cee60cfc 100644 --- a/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java +++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java @@ -120,7 +120,7 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:2^10\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:2^=10\"}}}," + "\"limit\":5," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\"]}}"; @@ -152,8 +152,8 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":5," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; @@ -173,8 +173,8 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":5,\"sort\":\"mod3_idv desc, score desc\"," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; @@ -194,16 +194,16 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch prepareIndexDocs(); String jsonQueryAll = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; QueryResponse rsp = query(CommonParams.JSON, jsonQueryAll, CommonParams.QT, "/search"); assertFieldValues(rsp.getResults(), id, "5", "7", "2", "6", "3", "10", "4"); String jsonQueryLimit4 = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":4," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; @@ -211,8 +211,8 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch assertFieldValues(rsp.getResults(), id, "5", "7", "2", "6"); String jsonQueryPage = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":4,\"offset\":3," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"combiner.query\":[\"lexical1\",\"lexical2\"]}}"; @@ -232,7 +232,7 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}}," + + "{\"lexical\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}}," + "\"limit\":3,\"offset\":1," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"facet\":true,\"facet.field\":\"mod3_idv\"," @@ -254,8 +254,8 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch prepareIndexDocs(); String jsonQuery = "{\"queries\":" - + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^2 OR 3^1 OR 6^2 OR 5^1)\"}}," - + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^1 OR 5^2 OR 7^3 OR 10^2)\"}}}," + + "{\"lexical1\":{\"lucene\":{\"query\":\"id:(2^=4 OR 3^=2 OR 6^=3 OR 5^=1)\"}}," + + "\"lexical2\":{\"lucene\":{\"query\":\"id:(4^=1 OR 5^=3 OR 7^=4 OR 10^=2)\"}}}," + "\"limit\":4," + "\"fields\":[\"id\",\"score\",\"title\"]," + "\"params\":{\"combiner\":true,\"facet\":true,\"facet.field\":\"mod3_idv\"," @@ -275,6 +275,41 @@ public class DistributedCombinedQueryComponentTest extends BaseDistributedSearch rsp.getHighlighting().get("5").get("title").get(0)); } + /** + * Tests the combined query feature with faceting, highlighting and elevation with debug. + * + * @throws Exception if any unexpected error occurs during the test execution. + */ + @Test + public void testElevatedQueriesWithFacetAndHighlights() throws Exception { + prepareIndexDocs(); + String jsonQuery = + "{\"queries\": {" + + "\"lexical1\": {\"lucene\": {\"query\": \"id:(2^=2 OR 3^=1 OR 6^=2 OR 1^=3)\"}}," + + "\"lexical2\": {\"lucene\": {\"query\": \"id:(4^=1 OR 1^=2 OR 7^=3 OR 10^=2)\"}}}," + + "\"limit\": 4," + + "\"fields\": [\"id\", \"score\", \"title\"]," + + "\"params\": {\"combiner\": true, \"elevateIds\": \"10,6\"," + + "\"combiner.query\": [\"lexical1\", \"lexical2\"]," + + "\"facet\": true, \"facet.field\": \"mod3_idv\"," + + "\"hl\": true, \"hl.fl\": \"title\", \"hl.q\": \"test doc\", \"debug\": \"true\"}}"; + handle.put("debug", SKIP); + QueryResponse rsp = query(CommonParams.JSON, jsonQuery, CommonParams.QT, "/search-elevate"); + assertEquals(4, rsp.getResults().size()); + assertFieldValues(rsp.getResults(), id, "10", "6", "1", "7"); + assertEquals("mod3_idv", rsp.getFacetFields().get(0).getName()); + assertEquals("[1 (4), 0 (2), 2 (1)]", rsp.getFacetFields().get(0).getValues().toString()); + assertEquals(4, rsp.getHighlighting().size()); + assertEquals( + "title <em>test</em> for <em>doc</em> 1", + rsp.getHighlighting().get("1").get("title").get(0)); + assertEquals( + "title <em>test</em> for <em>doc</em> 6", + rsp.getHighlighting().get("6").get("title").get(0)); + assertTrue(rsp.getDebugMap().containsKey("queryBoosting")); + assertEquals(2, ((List<?>) rsp.getDebugMap().get("queryBoosting")).size()); + } + /** * @see org.apache.solr.handler.component.CombinedQuerySolrCloudTest#testForcedDistrib() */
