SOLR-3316: Distributed grouping failed when rows parameter was set to 0 and sometimes returned a wrong
hit count as matches.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/branch_3x@1310445 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index fc3e810..abe558b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -319,6 +319,9 @@
* SOLR-3200: Fix SignatureUpdateProcessor "all fields" mode to use all
fields of each document instead of the fields specified by the first
document indexed (Spyros Kapnissis via hossman)
+
+* SOLR-3316: Distributed grouping failed when rows parameter was set to 0 and
+ sometimes returned a wrong hit count as matches. (Cody Young, Martijn van Groningen)
Other Changes
----------------------
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 8ea030c..0e716b1 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
@@ -24,7 +24,6 @@
import org.apache.lucene.search.grouping.GroupDocs;
import org.apache.lucene.search.grouping.SearchGroup;
import org.apache.lucene.search.grouping.TopGroups;
-import org.apache.lucene.util.BytesRef;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
@@ -265,6 +264,7 @@
CommandHandler.Builder topsGroupsActionBuilder = new CommandHandler.Builder()
.setQueryCommand(cmd)
.setNeedDocSet(false) // Order matters here
+ .setIncludeHitCount(true)
.setSearcher(searcher);
for (String field : groupingSpec.getFields()) {
@@ -280,6 +280,7 @@
commandHandler.execute();
SearchGroupsResultTransformer serializer = new SearchGroupsResultTransformer(searcher);
rsp.add("firstPhase", commandHandler.processResult(result, serializer));
+ rsp.add("totalHitCount", commandHandler.getTotalHitCount());
rb.setResult(result);
return;
} else if (params.getBool(GroupParams.GROUP_DISTRIBUTED_SECOND, false)) {
@@ -291,7 +292,7 @@
for (String field : groupingSpec.getFields()) {
String[] topGroupsParam = params.getParams(GroupParams.GROUP_DISTRIBUTED_TOPGROUPS_PREFIX + field);
if (topGroupsParam == null) {
- continue;
+ topGroupsParam = new String[0];
}
List<SearchGroup<String>> topGroups = new ArrayList<SearchGroup<String>>(topGroupsParam.length);
@@ -638,7 +639,7 @@
Map<String, Object> combinedMap = new LinkedHashMap<String, Object>();
combinedMap.putAll(rb.mergedTopGroups);
combinedMap.putAll(rb.mergedQueryCommandResults);
- endResultTransformer.transform(combinedMap, rb.rsp, rb.getGroupingSpec(), solrDocumentSource);
+ endResultTransformer.transform(combinedMap, rb, solrDocumentSource);
}
private void regularFinishStage(ResponseBuilder rb) {
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
index 7fa1e0d..0e81eba 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
@@ -158,6 +158,7 @@
public final Map<String, TopGroups<String>> mergedTopGroups = new HashMap<String, TopGroups<String>>();
public final Map<String, QueryCommandResult> mergedQueryCommandResults = new HashMap<String, QueryCommandResult>();
public final Map<Object, SolrDocument> retrievedDocuments = new HashMap<Object, SolrDocument>();
+ public int totalHitCount; // Hit count used when distributed grouping is performed.
// Used for timeAllowed parameter. First phase elapsed time is subtracted from the time allowed for the second phase.
public int firstPhaseElapsedTime;
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java b/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
index 0cf162f..52b7573 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
@@ -47,6 +47,7 @@
private SolrIndexSearcher searcher;
private boolean needDocSet = false;
private boolean truncateGroups = false;
+ private boolean includeHitCount = false;
public Builder setQueryCommand(SolrIndexSearcher.QueryCommand queryCommand) {
this.queryCommand = queryCommand;
@@ -76,6 +77,11 @@
return this;
}
+ public Builder setIncludeHitCount(boolean includeHitCount) {
+ this.includeHitCount = includeHitCount;
+ return this;
+ }
+
public Builder setTruncateGroups(boolean truncateGroups) {
this.truncateGroups = truncateGroups;
return this;
@@ -86,7 +92,7 @@
throw new IllegalStateException("All fields must be set");
}
- return new CommandHandler(queryCommand, commands, searcher, needDocSet, truncateGroups);
+ return new CommandHandler(queryCommand, commands, searcher, needDocSet, truncateGroups, includeHitCount);
}
}
@@ -98,19 +104,24 @@
private final SolrIndexSearcher searcher;
private final boolean needDocset;
private final boolean truncateGroups;
+ private final boolean includeHitCount;
private boolean partialResults = false;
+ private int totalHitCount;
private DocSet docSet;
private CommandHandler(SolrIndexSearcher.QueryCommand queryCommand,
List<Command> commands,
SolrIndexSearcher searcher,
- boolean needDocset, boolean truncateGroups) {
+ boolean needDocset,
+ boolean truncateGroups,
+ boolean includeHitCount) {
this.queryCommand = queryCommand;
this.commands = commands;
this.searcher = searcher;
this.needDocset = needDocset;
this.truncateGroups = truncateGroups;
+ this.includeHitCount = includeHitCount;
}
@SuppressWarnings("unchecked")
@@ -127,12 +138,14 @@
Filter luceneFilter = pf.filter;
Query query = QueryUtils.makeQueryable(queryCommand.getQuery());
- if (truncateGroups && nrOfCommands > 0) {
+ if (truncateGroups) {
docSet = computeGroupedDocSet(query, luceneFilter, collectors);
} else if (needDocset) {
docSet = computeDocSet(query, luceneFilter, collectors);
- } else {
+ } else if (!collectors.isEmpty()) {
searchWithTimeLimiter(query, luceneFilter, MultiCollector.wrap(collectors.toArray(new Collector[nrOfCommands])));
+ } else {
+ searchWithTimeLimiter(query, luceneFilter, null);
}
}
@@ -182,12 +195,25 @@
if (queryCommand.getTimeAllowed() > 0 ) {
collector = new TimeLimitingCollector(collector, TimeLimitingCollector.getGlobalCounter(), queryCommand.getTimeAllowed());
}
+
+ TotalHitCountCollector hitCountCollector = new TotalHitCountCollector();
+ if (includeHitCount) {
+ collector = MultiCollector.wrap(collector, hitCountCollector);
+ }
+
try {
searcher.search(query, luceneFilter, collector);
} catch (TimeLimitingCollector.TimeExceededException x) {
partialResults = true;
logger.warn( "Query: " + query + "; " + x.getMessage() );
}
+
+ if (includeHitCount) {
+ totalHitCount = hitCountCollector.getTotalHits();
+ }
}
+ public int getTotalHitCount() {
+ return totalHitCount;
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
index a598b72..57bbd0d 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
@@ -27,6 +27,7 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -69,7 +70,7 @@
private final Sort groupSort;
private final int topNGroups;
- private TermFirstPassGroupingCollector collector;
+ private TermFirstPassGroupingCollector firstPassGroupingCollector;
private SearchGroupsFieldCommand(SchemaField field, Sort groupSort, int topNGroups) {
this.field = field;
@@ -78,12 +79,20 @@
}
public List<Collector> create() throws IOException {
- collector = new TermFirstPassGroupingCollector(field.getName(), groupSort, topNGroups);
- return Arrays.asList((Collector) collector);
+ if (topNGroups > 0) {
+ firstPassGroupingCollector = new TermFirstPassGroupingCollector(field.getName(), groupSort, topNGroups);
+ return Arrays.asList((Collector) firstPassGroupingCollector);
+ } else {
+ return Collections.emptyList();
+ }
}
public Collection<SearchGroup<String>> result() {
- return collector.getTopGroups(0, true);
+ if (topNGroups > 0) {
+ return firstPassGroupingCollector.getTopGroups(0, true);
+ } else {
+ return Collections.emptyList();
+ }
}
public Sort getSortWithinGroup() {
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
index 20e0ba8..2f3dbce 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
@@ -19,17 +19,14 @@
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Sort;
-import org.apache.lucene.search.grouping.SearchGroup;
-import org.apache.lucene.search.grouping.TermAllGroupsCollector;
-import org.apache.lucene.search.grouping.TermSecondPassGroupingCollector;
-import org.apache.lucene.search.grouping.TopGroups;
-import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.search.grouping.*;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.grouping.Command;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -130,6 +127,10 @@
}
public List<Collector> create() throws IOException {
+ if (firstPhaseGroups.isEmpty()) {
+ return Collections.emptyList();
+ }
+
List<Collector> collectors = new ArrayList<Collector>();
secondPassCollector = new TermSecondPassGroupingCollector(
field.getName(), firstPhaseGroups, groupSort, sortWithinGroup, maxDocPerGroup, needScores, needMaxScore, true
@@ -143,7 +144,12 @@
return collectors;
}
+ @SuppressWarnings("unchecked")
public TopGroups<String> result() {
+ if (firstPhaseGroups.isEmpty()) {
+ return new TopGroups<String>(groupSort.getSort(), sortWithinGroup.getSort(), 0, 0, new GroupDocs[0]);
+ }
+
TopGroups<String> result = secondPassCollector.getTopGroups(0);
if (allGroupsCollector != null) {
result = new TopGroups<String>(result, allGroupsCollector.getGroupCount());
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
index 247e33b..27184d9 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
@@ -57,6 +57,7 @@
SearchGroupsResultTransformer serializer = new SearchGroupsResultTransformer(rb.req.getSearcher());
try {
int maxElapsedTime = 0;
+ int hitCountDuringFirstPhase = 0;
for (ShardResponse srsp : shardRequest.responses) {
maxElapsedTime = (int) Math.max(maxElapsedTime, srsp.getSolrResponse().getElapsedTime());
@SuppressWarnings("unchecked")
@@ -79,7 +80,9 @@
shards.add(srsp.getShard());
}
}
+ hitCountDuringFirstPhase += (Integer) srsp.getSolrResponse().getResponse().get("totalHitCount");
}
+ rb.totalHitCount = hitCountDuringFirstPhase;
rb.firstPhaseElapsedTime = maxElapsedTime;
for (String groupField : commandSearchGroups.keySet()) {
List<Collection<SearchGroup<String>>> topGroups = commandSearchGroups.get(groupField);
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/EndResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/EndResultTransformer.java
index efb5859..d559f56 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/EndResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/EndResultTransformer.java
@@ -19,8 +19,7 @@
import org.apache.lucene.search.ScoreDoc;
import org.apache.solr.common.SolrDocument;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.search.grouping.GroupingSpecification;
+import org.apache.solr.handler.component.ResponseBuilder;
import java.util.Map;
@@ -35,11 +34,10 @@
* Transforms the specified result into its final form and puts it into the specified response.
*
* @param result The map containing the grouping result (for grouping by field and query)
- * @param response The response that will be rendered to the client
- * @param groupingSpecification The grouping specification
+ * @param rb The response builder containing the response used to render the result and the grouping specification
* @param solrDocumentSource The source of {@link SolrDocument} instances
*/
- void transform(Map<String, ?> result, SolrQueryResponse response, GroupingSpecification groupingSpecification, SolrDocumentSource solrDocumentSource);
+ void transform(Map<String, ?> result, ResponseBuilder rb, SolrDocumentSource solrDocumentSource);
/**
* Abstracts the source for {@link SolrDocument} instances.
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java
index d42e367..f22bef2 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java
@@ -23,11 +23,10 @@
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.SolrIndexSearcher;
-import org.apache.solr.search.grouping.GroupingSpecification;
import org.apache.solr.search.grouping.distributed.command.QueryCommandResult;
import java.util.ArrayList;
@@ -35,7 +34,7 @@
import java.util.Map;
/**
- *
+ * Implementation of {@link EndResultTransformer} that keeps each grouped result separate in the final response.
*/
public class GroupedEndResultTransformer implements EndResultTransformer {
@@ -45,7 +44,10 @@
this.searcher = searcher;
}
- public void transform(Map<String, ?> result, SolrQueryResponse response, GroupingSpecification groupingSpecification, SolrDocumentSource solrDocumentSource) {
+ /**
+ * {@inheritDoc}
+ */
+ public void transform(Map<String, ?> result, ResponseBuilder rb, SolrDocumentSource solrDocumentSource) {
NamedList<Object> commands = new NamedList<Object>();
for (Map.Entry<String, ?> entry : result.entrySet()) {
Object value = entry.getValue();
@@ -53,7 +55,7 @@
@SuppressWarnings("unchecked")
TopGroups<String> topGroups = (TopGroups<String>) value;
NamedList<Object> command = new SimpleOrderedMap<Object>();
- command.add("matches", topGroups.totalHitCount);
+ command.add("matches", rb.totalHitCount);
if (topGroups.totalGroupCount != null) {
command.add("ngroups", topGroups.totalGroupCount);
}
@@ -75,7 +77,7 @@
if (!Float.isNaN(group.maxScore)) {
docList.setMaxScore(group.maxScore);
}
- docList.setStart(groupingSpecification.getGroupOffset());
+ docList.setStart(rb.getGroupingSpec().getGroupOffset());
for (ScoreDoc scoreDoc : group.scoreDocs) {
docList.add(solrDocumentSource.retrieve(scoreDoc));
}
@@ -93,7 +95,7 @@
if (!Float.isNaN(queryCommandResult.getTopDocs().getMaxScore())) {
docList.setMaxScore(queryCommandResult.getTopDocs().getMaxScore());
}
- docList.setStart(groupingSpecification.getGroupOffset());
+ docList.setStart(rb.getGroupingSpec().getGroupOffset());
for (ScoreDoc scoreDoc :queryCommandResult.getTopDocs().scoreDocs){
docList.add(solrDocumentSource.retrieve(scoreDoc));
}
@@ -101,7 +103,7 @@
commands.add(entry.getKey(), command);
}
}
- response.add("grouped", commands);
+ rb.rsp.add("grouped", commands);
}
}
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/MainEndResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/MainEndResultTransformer.java
index 79a3972..ae5053c 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/MainEndResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/MainEndResultTransformer.java
@@ -22,24 +22,27 @@
import org.apache.lucene.search.grouping.TopGroups;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.search.grouping.GroupingSpecification;
+import org.apache.solr.handler.component.ResponseBuilder;
import java.util.Map;
/**
- *
+ * Implementation of {@link EndResultTransformer} that transforms the grouped result into the main result list in the
+ * response.
*/
public class MainEndResultTransformer implements EndResultTransformer {
- public void transform(Map<String, ?> result, SolrQueryResponse response, GroupingSpecification groupingSpecification, SolrDocumentSource solrDocumentSource) {
- Object value = result.get(groupingSpecification.getFields()[0]);
+ /**
+ * {@inheritDoc}
+ */
+ public void transform(Map<String, ?> result, ResponseBuilder rb, SolrDocumentSource solrDocumentSource) {
+ Object value = result.get(rb.getGroupingSpec().getFields()[0]);
if (TopGroups.class.isInstance(value)) {
@SuppressWarnings("unchecked")
TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value;
SolrDocumentList docList = new SolrDocumentList();
- docList.setStart(groupingSpecification.getOffset());
- docList.setNumFound(topGroups.totalHitCount);
+ docList.setStart(rb.getGroupingSpec().getOffset());
+ docList.setNumFound(rb.totalHitCount);
Float maxScore = Float.NEGATIVE_INFINITY;
for (GroupDocs<BytesRef> group : topGroups.groups) {
@@ -53,7 +56,7 @@
if (maxScore != Float.NEGATIVE_INFINITY) {
docList.setMaxScore(maxScore);
}
- response.add("response", docList);
+ rb.rsp.add("response", docList);
}
}
}
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/SimpleEndResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/SimpleEndResultTransformer.java
index ccae84a..aa2acda 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/SimpleEndResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/SimpleEndResultTransformer.java
@@ -24,17 +24,19 @@
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.search.grouping.GroupingSpecification;
+import org.apache.solr.handler.component.ResponseBuilder;
import java.util.Map;
/**
- *
+ * Implementation of {@link EndResultTransformer} that transforms the grouped result into a single flat list.
*/
public class SimpleEndResultTransformer implements EndResultTransformer {
- public void transform(Map<String, ?> result, SolrQueryResponse response, GroupingSpecification groupingSpecification, SolrDocumentSource solrDocumentSource) {
+ /**
+ * {@inheritDoc}
+ */
+ public void transform(Map<String, ?> result, ResponseBuilder rb, SolrDocumentSource solrDocumentSource) {
NamedList<Object> commands = new SimpleOrderedMap<Object>();
for (Map.Entry<String, ?> entry : result.entrySet()) {
Object value = entry.getValue();
@@ -42,12 +44,12 @@
@SuppressWarnings("unchecked")
TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value;
NamedList<Object> command = new SimpleOrderedMap<Object>();
- command.add("matches", topGroups.totalHitCount);
+ command.add("matches", rb.totalHitCount);
if (topGroups.totalGroupCount != null) {
command.add("ngroups", topGroups.totalGroupCount);
}
SolrDocumentList docList = new SolrDocumentList();
- docList.setStart(groupingSpecification.getOffset());
+ docList.setStart(rb.getGroupingSpec().getOffset());
docList.setNumFound(topGroups.totalHitCount);
Float maxScore = Float.NEGATIVE_INFINITY;
@@ -67,6 +69,6 @@
}
}
- response.add("grouped", commands);
+ rb.rsp.add("grouped", commands);
}
}
diff --git a/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java b/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
index 3b396e1..eff7f10 100644
--- a/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
+++ b/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
@@ -17,9 +17,12 @@
* limitations under the License.
*/
+import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
/**
* TODO? perhaps use:
@@ -169,6 +172,26 @@
query("q", "*:*", "fq", s2 + ":a", "rows", 100, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10, "sort", s1 + " asc, id asc", "group.truncate", "true");
query("q", "*:*", "fq", s2 + ":a", "rows", 100, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10, "sort", s1 + " asc, id asc", "group.truncate", "true", "facet", "true", "facet.field", t1);
+ query("q", "*:*", "fq", s2 + ":a", "rows", 0, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10, "sort", s1 + " asc, id asc", "facet", "true", "facet.field", t1);
+ query("q", "*:*", "fq", s2 + ":a", "rows", 0, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10, "sort", s1 + " asc, id asc", "group.truncate", "true", "facet", "true", "facet.field", t1);
+
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ Object[] q = {"q", "*:*", "fq", s2 + ":a", "rows", 1, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10};
+
+ for (int i = 0; i < q.length; i += 2) {
+ params.add(q[i].toString(), q[i + 1].toString());
+ }
+
+ params.set("shards", shards);
+
+ int which = r.nextInt(clients.size());
+ SolrServer client = clients.get(which);
+ QueryResponse rsp = client.query(params);
+ NamedList nl = (NamedList<?>) rsp.getResponse().get("grouped");
+ nl = (NamedList<?>) nl.getVal(0);
+ int matches = (Integer) nl.getVal(0);
+ assertEquals(100 * clients.size(), matches);
+
// We cannot validate distributed grouping with scoring as first sort. since there is no global idf. We can check if no errors occur
simpleQuery("q", "*:*", "rows", 100, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10, "sort", s1 + " desc", "group.sort", "score desc"); // SOLR-2955
simpleQuery("q", "*:*", "rows", 100, "fl", "id," + s1, "group", "true", "group.field", s1, "group.limit", 10, "sort", "score desc, _docid_ asc, id asc");