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 000000000000..a2acaa2e6234 --- /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 8b097bc304d4..1e5c0b11aa1d 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 @@ -151,6 +151,7 @@ public void prepare(ResponseBuilder rb) throws IOException { 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 2bc9ae3d0bb2..7e079b95882f 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 void prepare(ResponseBuilder rb) throws IOException { return; } + if (rb instanceof CombinedQueryResponseBuilder crb) { + prepareCombined(crb); + } 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.getFirst(); + crb.setSortSpec(representative.getSortSpec()); + crb.setFilters(representative.getFilters()); + + if (crb.isDebug() && crb.isDebugQuery()) { + List 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); @@ -767,7 +807,7 @@ private void addDebugInfo(ResponseBuilder rb, Elevation elevation) { SimpleOrderedMap 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 b96ff9cd6874..35908f42195f 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 @@ - + + + elevator + + + + > + string + elevate.xml + + + 2 @@ -159,7 +170,7 @@ - + text 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 4f5f31d80063..39a7e69e23f6 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 CombinedQuerySolrCloudTest() { 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 void testSingleLexicalQuery() throws Exception { 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 void testMultipleLexicalQuery() throws Exception { 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 void testMultipleQueryWithSort() throws Exception { 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 void testHybridQueryWithPagination() throws Exception { 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 void testHybridQueryWithPagination() throws Exception { 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 void testHybridQueryWithPagination() throws Exception { 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 void testQueryWithFaceting() throws Exception { 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 void testQueriesWithFacetAndHighlights() throws Exception { 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,48 @@ public void testQueriesWithFacetAndHighlights() throws Exception { rsp.getHighlighting().get("5").get("title").getFirst()); } + /** + * 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().getFirst().getName()); + assertEquals("[1 (3), 0 (2), 2 (2)]", rsp.getFacetFields().getFirst().getValues().toString()); + assertEquals(4, rsp.getHighlighting().size()); + assertEquals( + "title test for doc 10", + rsp.getHighlighting().get("10").get("title").getFirst()); + assertEquals( + "title test for doc 5", + rsp.getHighlighting().get("5").get("title").getFirst()); + } + /** * Tests the combined query feature with faceting, highlighting and collapse. * @@ -284,12 +335,12 @@ public void testQueriesWithFacetAndHighlightsCollapse() throws Exception { "queries": { "lexical1": { "lucene": { - "query": "id:(CO!2^3 OR CO!3^1 OR CO!6^2 OR CO!5^1)" + "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)" + "query": "id:(CO!8^=1 OR CO!5^=2 OR CO!7^=3 OR CO!10^=2)" } } }, 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 bb9105cad302..9a11751b1418 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 @@ -122,7 +122,7 @@ public void testSingleLexicalQuery() throws Exception { 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\"]}}", @@ -154,8 +154,8 @@ public void testMultipleLexicalQuery() throws Exception { 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\"]}}"; @@ -174,8 +174,8 @@ public void testMultipleQueryWithSort() throws Exception { 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\"]}}"; @@ -196,8 +196,8 @@ public void testHybridQueryWithPagination() throws Exception { query( CommonParams.JSON, "{\"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\"]}}", CommonParams.QT, @@ -207,8 +207,8 @@ public void testHybridQueryWithPagination() throws Exception { query( CommonParams.JSON, "{\"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\"]}}", @@ -219,8 +219,8 @@ public void testHybridQueryWithPagination() throws Exception { query( CommonParams.JSON, "{\"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\"]}}", @@ -240,7 +240,7 @@ public void testQueryWithFaceting() throws Exception { 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\",\"facet.mincount\":1," @@ -261,8 +261,8 @@ public void testQueriesWithFacetAndHighlights() throws Exception { 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\"," @@ -282,6 +282,52 @@ public void testQueriesWithFacetAndHighlights() throws Exception { rsp.getHighlighting().get("5").get("title").getFirst()); } + /** + * 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().getFirst().getName()); + assertEquals("[1 (4), 0 (2), 2 (1)]", rsp.getFacetFields().getFirst().getValues().toString()); + assertEquals(4, rsp.getHighlighting().size()); + assertEquals( + "title test for doc 1", + rsp.getHighlighting().get("1").get("title").getFirst()); + assertEquals( + "title test for doc 6", + rsp.getHighlighting().get("6").get("title").getFirst()); + assertTrue(rsp.getDebugMap().containsKey("queryBoosting")); + assertEquals(2, ((List) rsp.getDebugMap().get("queryBoosting")).size()); + } + /** * @see org.apache.solr.handler.component.CombinedQuerySolrCloudTest#testForcedDistrib() */