mirror of https://github.com/apache/lucene.git
SOLR-3436: Group count incorrect when not all shards are queried in the second pass.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1338194 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
015d8601c8
commit
04dceabc18
|
@ -425,6 +425,9 @@ Bug Fixes
|
|||
* SOLR-3370: fixed CSVResponseWriter to respect globs in the 'fl' param
|
||||
(Keith Fligg via hossman)
|
||||
|
||||
* SOLR-3436: Group count incorrect when not all shards are queried in the second
|
||||
pass. (Francois Perron, Martijn van Groningen)
|
||||
|
||||
Other Changes
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -32,22 +32,13 @@ import org.apache.lucene.util.CharsRef;
|
|||
import org.apache.lucene.util.ReaderUtil;
|
||||
import org.apache.lucene.util.UnicodeUtil;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.util.ClientUtils;
|
||||
import org.apache.solr.cloud.CloudDescriptor;
|
||||
import org.apache.solr.cloud.ZkController;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.cloud.CloudState;
|
||||
import org.apache.solr.common.cloud.Slice;
|
||||
import org.apache.solr.common.cloud.ZkCoreNodeProps;
|
||||
import org.apache.solr.common.cloud.ZkNodeProps;
|
||||
import org.apache.solr.common.cloud.ZkStateReader;
|
||||
import org.apache.solr.common.params.*;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.common.util.StrUtils;
|
||||
import org.apache.solr.core.CoreDescriptor;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.ResultContext;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
|
@ -56,8 +47,6 @@ import org.apache.solr.schema.SchemaField;
|
|||
import org.apache.solr.search.*;
|
||||
import org.apache.solr.search.grouping.CommandHandler;
|
||||
import org.apache.solr.search.grouping.GroupingSpecification;
|
||||
import org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer;
|
||||
import org.apache.solr.search.grouping.endresulttransformer.EndResultTransformer;
|
||||
import org.apache.solr.search.grouping.distributed.ShardRequestFactory;
|
||||
import org.apache.solr.search.grouping.distributed.ShardResponseProcessor;
|
||||
import org.apache.solr.search.grouping.distributed.command.QueryCommand;
|
||||
|
@ -70,6 +59,8 @@ import org.apache.solr.search.grouping.distributed.responseprocessor.SearchGroup
|
|||
import org.apache.solr.search.grouping.distributed.responseprocessor.StoredFieldsShardResponseProcessor;
|
||||
import org.apache.solr.search.grouping.distributed.responseprocessor.TopGroupsShardResponseProcessor;
|
||||
import org.apache.solr.search.grouping.distributed.shardresultserializer.SearchGroupsResultTransformer;
|
||||
import org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer;
|
||||
import org.apache.solr.search.grouping.endresulttransformer.EndResultTransformer;
|
||||
import org.apache.solr.search.grouping.endresulttransformer.GroupedEndResultTransformer;
|
||||
import org.apache.solr.search.grouping.endresulttransformer.MainEndResultTransformer;
|
||||
import org.apache.solr.search.grouping.endresulttransformer.SimpleEndResultTransformer;
|
||||
|
@ -288,6 +279,7 @@ public class QueryComponent extends SearchComponent
|
|||
.setField(searcher.getSchema().getField(field))
|
||||
.setGroupSort(groupingSpec.getGroupSort())
|
||||
.setTopNGroups(cmd.getOffset() + cmd.getLen())
|
||||
.setIncludeGroupCount(groupingSpec.isIncludeGroupCount())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
@ -329,7 +321,6 @@ public class QueryComponent extends SearchComponent
|
|||
.setMaxDocPerGroup(groupingSpec.getGroupOffset() + groupingSpec.getGroupLimit())
|
||||
.setNeedScores(needScores)
|
||||
.setNeedMaxScore(needScores)
|
||||
.setNeedGroupCount(groupingSpec.isIncludeGroupCount())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ public class ResponseBuilder
|
|||
|
||||
// Context fields for grouping
|
||||
public final Map<String, Collection<SearchGroup<BytesRef>>> mergedSearchGroups = new HashMap<String, Collection<SearchGroup<BytesRef>>>();
|
||||
public final Map<String, Integer> mergedGroupCounts = new HashMap<String, Integer>();
|
||||
public final Map<String, Map<SearchGroup<BytesRef>, Set<String>>> searchGroupToShards = new HashMap<String, Map<SearchGroup<BytesRef>, Set<String>>>();
|
||||
public final Map<String, TopGroups<BytesRef>> mergedTopGroups = new HashMap<String, TopGroups<BytesRef>>();
|
||||
public final Map<String, QueryCommandResult> mergedQueryCommandResults = new HashMap<String, QueryCommandResult>();
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package org.apache.solr.search.grouping.distributed.command;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple data structure to hold a pair of typed objects.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class Pair<A, B> {
|
||||
|
||||
private final A a;
|
||||
private final B b;
|
||||
|
||||
public Pair(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public A getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public B getB() {
|
||||
return b;
|
||||
}
|
||||
}
|
|
@ -20,27 +20,26 @@ package org.apache.solr.search.grouping.distributed.command;
|
|||
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.term.TermAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermFirstPassGroupingCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.grouping.Command;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates all the collectors needed for the first phase and how to handle the results.
|
||||
*/
|
||||
public class SearchGroupsFieldCommand implements Command<Collection<SearchGroup<BytesRef>>> {
|
||||
public class SearchGroupsFieldCommand implements Command<Pair<Integer, Collection<SearchGroup<BytesRef>>>> {
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private SchemaField field;
|
||||
private Sort groupSort;
|
||||
private Integer topNGroups;
|
||||
private boolean includeGroupCount = false;
|
||||
|
||||
public Builder setField(SchemaField field) {
|
||||
this.field = field;
|
||||
|
@ -57,12 +56,17 @@ public class SearchGroupsFieldCommand implements Command<Collection<SearchGroup<
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setIncludeGroupCount(boolean includeGroupCount) {
|
||||
this.includeGroupCount = includeGroupCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SearchGroupsFieldCommand build() {
|
||||
if (field == null || groupSort == null || topNGroups == null) {
|
||||
throw new IllegalStateException("All fields must be set");
|
||||
}
|
||||
|
||||
return new SearchGroupsFieldCommand(field, groupSort, topNGroups);
|
||||
return new SearchGroupsFieldCommand(field, groupSort, topNGroups, includeGroupCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,30 +74,45 @@ public class SearchGroupsFieldCommand implements Command<Collection<SearchGroup<
|
|||
private final SchemaField field;
|
||||
private final Sort groupSort;
|
||||
private final int topNGroups;
|
||||
private final boolean includeGroupCount;
|
||||
|
||||
private TermFirstPassGroupingCollector firstPassGroupingCollector;
|
||||
private TermAllGroupsCollector allGroupsCollector;
|
||||
|
||||
private SearchGroupsFieldCommand(SchemaField field, Sort groupSort, int topNGroups) {
|
||||
private SearchGroupsFieldCommand(SchemaField field, Sort groupSort, int topNGroups, boolean includeGroupCount) {
|
||||
this.field = field;
|
||||
this.groupSort = groupSort;
|
||||
this.topNGroups = topNGroups;
|
||||
this.includeGroupCount = includeGroupCount;
|
||||
}
|
||||
|
||||
public List<Collector> create() throws IOException {
|
||||
List<Collector> collectors = new ArrayList<Collector>();
|
||||
if (topNGroups > 0) {
|
||||
firstPassGroupingCollector = new TermFirstPassGroupingCollector(field.getName(), groupSort, topNGroups);
|
||||
return Arrays.asList((Collector) firstPassGroupingCollector);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
collectors.add(firstPassGroupingCollector);
|
||||
}
|
||||
if (includeGroupCount) {
|
||||
allGroupsCollector = new TermAllGroupsCollector(field.getName());
|
||||
collectors.add(allGroupsCollector);
|
||||
}
|
||||
return collectors;
|
||||
}
|
||||
|
||||
public Collection<SearchGroup<BytesRef>> result() {
|
||||
public Pair<Integer, Collection<SearchGroup<BytesRef>>> result() {
|
||||
final Collection<SearchGroup<BytesRef>> topGroups;
|
||||
if (topNGroups > 0) {
|
||||
return firstPassGroupingCollector.getTopGroups(0, true);
|
||||
topGroups = firstPassGroupingCollector.getTopGroups(0, true);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
topGroups = Collections.emptyList();
|
||||
}
|
||||
final Integer groupCount;
|
||||
if (includeGroupCount) {
|
||||
groupCount = allGroupsCollector.getGroupCount();
|
||||
} else {
|
||||
groupCount = null;
|
||||
}
|
||||
return new Pair<Integer, Collection<SearchGroup<BytesRef>>>(groupCount, topGroups);
|
||||
}
|
||||
|
||||
public Sort getSortWithinGroup() {
|
||||
|
|
|
@ -21,9 +21,8 @@ import org.apache.lucene.search.Collector;
|
|||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.GroupDocs;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.search.grouping.term.TermAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermSecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.TopGroups;
|
||||
import org.apache.lucene.search.grouping.term.TermSecondPassGroupingCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.grouping.Command;
|
||||
|
@ -35,7 +34,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Defines all collectors for retrieving the second phase and how to handle the collector result.
|
||||
*/
|
||||
public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
||||
|
||||
|
@ -48,7 +47,6 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
private Integer maxDocPerGroup;
|
||||
private boolean needScores = false;
|
||||
private boolean needMaxScore = false;
|
||||
private boolean needGroupCount = false;
|
||||
|
||||
public Builder setField(SchemaField field) {
|
||||
this.field = field;
|
||||
|
@ -85,18 +83,13 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setNeedGroupCount(Boolean needGroupCount) {
|
||||
this.needGroupCount = needGroupCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TopGroupsFieldCommand build() {
|
||||
if (field == null || groupSort == null || sortWithinGroup == null || firstPhaseGroups == null ||
|
||||
maxDocPerGroup == null) {
|
||||
throw new IllegalStateException("All required fields must be set");
|
||||
}
|
||||
|
||||
return new TopGroupsFieldCommand(field, groupSort, sortWithinGroup, firstPhaseGroups, maxDocPerGroup, needScores, needMaxScore, needGroupCount);
|
||||
return new TopGroupsFieldCommand(field, groupSort, sortWithinGroup, firstPhaseGroups, maxDocPerGroup, needScores, needMaxScore);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -108,10 +101,7 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
private final int maxDocPerGroup;
|
||||
private final boolean needScores;
|
||||
private final boolean needMaxScore;
|
||||
private final boolean needGroupCount;
|
||||
|
||||
private TermSecondPassGroupingCollector secondPassCollector;
|
||||
private TermAllGroupsCollector allGroupsCollector;
|
||||
|
||||
private TopGroupsFieldCommand(SchemaField field,
|
||||
Sort groupSort,
|
||||
|
@ -119,8 +109,7 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
Collection<SearchGroup<BytesRef>> firstPhaseGroups,
|
||||
int maxDocPerGroup,
|
||||
boolean needScores,
|
||||
boolean needMaxScore,
|
||||
boolean needGroupCount) {
|
||||
boolean needMaxScore) {
|
||||
this.field = field;
|
||||
this.groupSort = groupSort;
|
||||
this.sortWithinGroup = sortWithinGroup;
|
||||
|
@ -128,7 +117,6 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
this.maxDocPerGroup = maxDocPerGroup;
|
||||
this.needScores = needScores;
|
||||
this.needMaxScore = needMaxScore;
|
||||
this.needGroupCount = needGroupCount;
|
||||
}
|
||||
|
||||
public List<Collector> create() throws IOException {
|
||||
|
@ -141,11 +129,6 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
field.getName(), firstPhaseGroups, groupSort, sortWithinGroup, maxDocPerGroup, needScores, needMaxScore, true
|
||||
);
|
||||
collectors.add(secondPassCollector);
|
||||
if (!needGroupCount) {
|
||||
return collectors;
|
||||
}
|
||||
allGroupsCollector = new TermAllGroupsCollector(field.getName());
|
||||
collectors.add(allGroupsCollector);
|
||||
return collectors;
|
||||
}
|
||||
|
||||
|
@ -155,11 +138,7 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
return new TopGroups<BytesRef>(groupSort.getSort(), sortWithinGroup.getSort(), 0, 0, new GroupDocs[0]);
|
||||
}
|
||||
|
||||
TopGroups<BytesRef> result = secondPassCollector.getTopGroups(0);
|
||||
if (allGroupsCollector != null) {
|
||||
result = new TopGroups<BytesRef>(result, allGroupsCollector.getGroupCount());
|
||||
}
|
||||
return result;
|
||||
return secondPassCollector.getTopGroups(0);
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.solr.handler.component.ShardRequest;
|
|||
import org.apache.solr.handler.component.ShardResponse;
|
||||
import org.apache.solr.search.SortSpec;
|
||||
import org.apache.solr.search.grouping.distributed.ShardResponseProcessor;
|
||||
import org.apache.solr.search.grouping.distributed.command.Pair;
|
||||
import org.apache.solr.search.grouping.distributed.shardresultserializer.SearchGroupsResultTransformer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -63,9 +64,17 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
|
|||
maxElapsedTime = (int) Math.max(maxElapsedTime, srsp.getSolrResponse().getElapsedTime());
|
||||
@SuppressWarnings("unchecked")
|
||||
NamedList<NamedList> firstPhaseResult = (NamedList<NamedList>) srsp.getSolrResponse().getResponse().get("firstPhase");
|
||||
Map<String, Collection<SearchGroup<BytesRef>>> result = serializer.transformToNative(firstPhaseResult, groupSort, null, srsp.getShard());
|
||||
Map<String, Pair<Integer, Collection<SearchGroup<BytesRef>>>> result = serializer.transformToNative(firstPhaseResult, groupSort, null, srsp.getShard());
|
||||
for (String field : commandSearchGroups.keySet()) {
|
||||
Collection<SearchGroup<BytesRef>> searchGroups = result.get(field);
|
||||
Pair<Integer, Collection<SearchGroup<BytesRef>>> firstPhaseCommandResult = result.get(field);
|
||||
Integer groupCount = firstPhaseCommandResult.getA();
|
||||
if (groupCount != null) {
|
||||
Integer existingGroupCount = rb.mergedGroupCounts.get(field);
|
||||
// Assuming groups don't cross shard boundary...
|
||||
rb.mergedGroupCounts.put(field, existingGroupCount != null ? existingGroupCount + groupCount : groupCount);
|
||||
}
|
||||
|
||||
Collection<SearchGroup<BytesRef>> searchGroups = firstPhaseCommandResult.getB();
|
||||
if (searchGroups == null) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.solr.schema.FieldType;
|
|||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.search.grouping.Command;
|
||||
import org.apache.solr.search.grouping.distributed.command.Pair;
|
||||
import org.apache.solr.search.grouping.distributed.command.SearchGroupsFieldCommand;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -35,7 +36,7 @@ import java.util.*;
|
|||
/**
|
||||
* Implementation for transforming {@link SearchGroup} into a {@link NamedList} structure and visa versa.
|
||||
*/
|
||||
public class SearchGroupsResultTransformer implements ShardResultTransformer<List<Command>, Map<String, Collection<SearchGroup<BytesRef>>>> {
|
||||
public class SearchGroupsResultTransformer implements ShardResultTransformer<List<Command>, Map<String, Pair<Integer, Collection<SearchGroup<BytesRef>>>>> {
|
||||
|
||||
private final SolrIndexSearcher searcher;
|
||||
|
||||
|
@ -49,17 +50,20 @@ public class SearchGroupsResultTransformer implements ShardResultTransformer<Lis
|
|||
public NamedList transform(List<Command> data) throws IOException {
|
||||
NamedList<NamedList> result = new NamedList<NamedList>();
|
||||
for (Command command : data) {
|
||||
NamedList commandResult;
|
||||
final NamedList<Object> commandResult = new NamedList<Object>();
|
||||
if (SearchGroupsFieldCommand.class.isInstance(command)) {
|
||||
SearchGroupsFieldCommand fieldCommand = (SearchGroupsFieldCommand) command;
|
||||
Collection<SearchGroup<BytesRef>> searchGroups = fieldCommand.result();
|
||||
if (searchGroups == null) {
|
||||
continue;
|
||||
Pair<Integer, Collection<SearchGroup<BytesRef>>> pair = fieldCommand.result();
|
||||
Integer groupedCount = pair.getA();
|
||||
Collection<SearchGroup<BytesRef>> searchGroups = pair.getB();
|
||||
if (searchGroups != null) {
|
||||
commandResult.add("topGroups", serializeSearchGroup(searchGroups, fieldCommand.getGroupSort()));
|
||||
}
|
||||
if (groupedCount != null) {
|
||||
commandResult.add("groupCount", groupedCount);
|
||||
}
|
||||
|
||||
commandResult = serializeSearchGroup(searchGroups, fieldCommand.getGroupSort());
|
||||
} else {
|
||||
commandResult = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(command.getKey(), commandResult);
|
||||
|
@ -70,20 +74,24 @@ public class SearchGroupsResultTransformer implements ShardResultTransformer<Lis
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map<String, Collection<SearchGroup<BytesRef>>> transformToNative(NamedList<NamedList> shardResponse, Sort groupSort, Sort sortWithinGroup, String shard) throws IOException {
|
||||
Map<String, Collection<SearchGroup<BytesRef>>> result = new HashMap<String, Collection<SearchGroup<BytesRef>>>();
|
||||
public Map<String, Pair<Integer, Collection<SearchGroup<BytesRef>>>> transformToNative(NamedList<NamedList> shardResponse, Sort groupSort, Sort sortWithinGroup, String shard) throws IOException {
|
||||
Map<String, Pair<Integer, Collection<SearchGroup<BytesRef>>>> result = new HashMap<String, Pair<Integer, Collection<SearchGroup<BytesRef>>>>();
|
||||
for (Map.Entry<String, NamedList> command : shardResponse) {
|
||||
List<SearchGroup<BytesRef>> searchGroups = new ArrayList<SearchGroup<BytesRef>>();
|
||||
NamedList topGroupsAndGroupCount = command.getValue();
|
||||
@SuppressWarnings("unchecked")
|
||||
NamedList<List<Comparable>> rawSearchGroups = command.getValue();
|
||||
NamedList<List<Comparable>> rawSearchGroups = (NamedList<List<Comparable>>) topGroupsAndGroupCount.get("topGroups");
|
||||
if (rawSearchGroups != null) {
|
||||
for (Map.Entry<String, List<Comparable>> rawSearchGroup : rawSearchGroups){
|
||||
SearchGroup<BytesRef> searchGroup = new SearchGroup<BytesRef>();
|
||||
searchGroup.groupValue = rawSearchGroup.getKey() != null ? new BytesRef(rawSearchGroup.getKey()) : null;
|
||||
searchGroup.sortValues = rawSearchGroup.getValue().toArray(new Comparable[rawSearchGroup.getValue().size()]);
|
||||
searchGroups.add(searchGroup);
|
||||
}
|
||||
}
|
||||
|
||||
result.put(command.getKey(), searchGroups);
|
||||
Integer groupCount = (Integer) topGroupsAndGroupCount.get("groupCount");
|
||||
result.put(command.getKey(), new Pair<Integer, Collection<SearchGroup<BytesRef>>>(groupCount, searchGroups));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -115,10 +115,9 @@ public class TopGroupsResultTransformer implements ShardResultTransformer<List<C
|
|||
}
|
||||
|
||||
Integer totalHitCount = (Integer) commandResult.get("totalHitCount");
|
||||
Integer totalGroupCount = (Integer) commandResult.get("totalGroupCount");
|
||||
|
||||
List<GroupDocs<BytesRef>> groupDocs = new ArrayList<GroupDocs<BytesRef>>();
|
||||
for (int i = totalGroupCount == null ? 2 : 3; i < commandResult.size(); i++) {
|
||||
for (int i = 2; i < commandResult.size(); i++) {
|
||||
String groupValue = commandResult.getName(i);
|
||||
@SuppressWarnings("unchecked")
|
||||
NamedList<Object> groupResult = (NamedList<Object>) commandResult.getVal(i);
|
||||
|
@ -151,9 +150,6 @@ public class TopGroupsResultTransformer implements ShardResultTransformer<List<C
|
|||
TopGroups<BytesRef> topGroups = new TopGroups<BytesRef>(
|
||||
groupSort.getSort(), sortWithinGroup.getSort(), totalHitCount, totalGroupedHitCount, groupDocsArr
|
||||
);
|
||||
if (totalGroupCount != null) {
|
||||
topGroups = new TopGroups<BytesRef>(topGroups, totalGroupCount);
|
||||
}
|
||||
|
||||
result.put(key, topGroups);
|
||||
}
|
||||
|
|
|
@ -57,8 +57,9 @@ public class GroupedEndResultTransformer implements EndResultTransformer {
|
|||
TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value;
|
||||
NamedList<Object> command = new SimpleOrderedMap<Object>();
|
||||
command.add("matches", rb.totalHitCount);
|
||||
if (topGroups.totalGroupCount != null) {
|
||||
command.add("ngroups", topGroups.totalGroupCount);
|
||||
Integer totalGroupCount = rb.mergedGroupCounts.get(entry.getKey());
|
||||
if (totalGroupCount != null) {
|
||||
command.add("ngroups", totalGroupCount);
|
||||
}
|
||||
|
||||
List<NamedList> groups = new ArrayList<NamedList>();
|
||||
|
|
|
@ -169,11 +169,16 @@ public class TestDistributedGrouping extends BaseDistributedSearchTestCase {
|
|||
query("q", "*:*", "fq", s1 + ":a", "rows", 100, "fl", "id," + i1, "group", "true", "group.field", i1, "group.limit", 10, "sort", i1 + " asc, id asc", "group.truncate", "true");
|
||||
query("q", "*:*", "fq", s1 + ":a", "rows", 100, "fl", "id," + i1, "group", "true", "group.field", i1, "group.limit", 10, "sort", i1 + " asc, id asc", "group.truncate", "true", "facet", "true", "facet.field", t1);
|
||||
|
||||
// SOLR-3316
|
||||
query("q", "*:*", "fq", s1 + ":a", "rows", 0, "fl", "id," + i1, "group", "true", "group.field", i1, "group.limit", 10, "sort", i1 + " asc, id asc", "facet", "true", "facet.field", t1);
|
||||
query("q", "*:*", "fq", s1 + ":a", "rows", 0, "fl", "id," + i1, "group", "true", "group.field", i1, "group.limit", 10, "sort", i1 + " asc, id asc", "group.truncate", "true", "facet", "true", "facet.field", t1);
|
||||
|
||||
// SOLR-3436
|
||||
query("q", "*:*", "fq", s1 + ":a", "fl", "id," + i1, "group", "true", "group.field", i1, "sort", i1 + " asc, id asc", "group.ngroups", "true");
|
||||
query("q", "*:*", "fq", s1 + ":a", "rows", 0, "fl", "id," + i1, "group", "true", "group.field", i1, "sort", i1 + " asc, id asc", "group.ngroups", "true");
|
||||
|
||||
ModifiableSolrParams params = new ModifiableSolrParams();
|
||||
Object[] q = {"q", "*:*", "fq", s1 + ":a", "rows", 1, "fl", "id," + i1, "group", "true", "group.field", i1, "group.limit", 10};
|
||||
Object[] q = {"q", "*:*", "fq", s1 + ":a", "rows", 1, "fl", "id," + i1, "group", "true", "group.field", i1, "group.limit", 10, "group.ngroups", "true"};
|
||||
|
||||
for (int i = 0; i < q.length; i += 2) {
|
||||
params.add(q[i].toString(), q[i + 1].toString());
|
||||
|
@ -187,7 +192,9 @@ public class TestDistributedGrouping extends BaseDistributedSearchTestCase {
|
|||
NamedList nl = (NamedList<?>) rsp.getResponse().get("grouped");
|
||||
nl = (NamedList<?>) nl.getVal(0);
|
||||
int matches = (Integer) nl.getVal(0);
|
||||
int groupCount = (Integer) nl.get("ngroups");
|
||||
assertEquals(100 * shardsArr.length, matches);
|
||||
assertEquals(shardsArr.length, groupCount);
|
||||
|
||||
|
||||
// We cannot validate distributed grouping with scoring as first sort. since there is no global idf. We can check if no errors occur
|
||||
|
|
Loading…
Reference in New Issue