SOLR-236: refactoring - use Lucene's new MultiCollector, remove ours, move GroupCommand out of SolrIndexSearcher

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@998343 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yonik Seeley 2010-09-17 21:46:58 +00:00
parent 634cf215f1
commit 17376b0fe3
3 changed files with 26 additions and 79 deletions

View File

@ -33,10 +33,8 @@ import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.*;
import org.apache.solr.search.function.BoostedQuery;
import org.apache.solr.search.function.FunctionQuery;
import org.apache.solr.search.function.QueryValueSource;
import org.apache.solr.search.function.ValueSource;
import org.apache.solr.util.SolrPluginUtils;
import java.io.IOException;
@ -190,7 +188,7 @@ public class QueryComponent extends SearchComponent
boolean doGroup = params.getBool(GroupParams.GROUP, false);
if (doGroup) {
try {
cmd.groupCommands = new ArrayList<SolrIndexSearcher.GroupCommand>();
cmd.groupCommands = new ArrayList<Grouping.Command>();
String[] fields = params.getParams(GroupParams.GROUP_FIELD);
String[] funcs = params.getParams(GroupParams.GROUP_FUNC);
@ -217,7 +215,7 @@ public class QueryComponent extends SearchComponent
for (String groupByStr : funcs) {
QParser parser = QParser.getParser(groupByStr, "func", rb.req);
Query q = parser.getQuery();
SolrIndexSearcher.GroupCommandFunc gc = new SolrIndexSearcher.GroupCommandFunc();
Grouping.CommandFunc gc = new Grouping.CommandFunc();
gc.groupSort = groupSort;
if (q instanceof FunctionQuery) {

View File

@ -25,66 +25,30 @@ import org.apache.solr.search.function.ValueSource;
import java.io.IOException;
import java.util.*;
public class MultiCollector extends Collector {
final Collector[] collectors;
final boolean acceptsDocsOutOfOrder;
public class Grouping {
public static Collector wrap(List<? extends Collector> collectors) {
return collectors.size() == 1 ? collectors.get(0) : new MultiCollector(collectors);
public static class Command {
public String key; // the name to use for this group in the response
public Sort groupSort; // the sort of the documents *within* a single group.
public int groupLimit; // how many groups - defaults to the "rows" parameter
public int docsPerGroup; // how many docs in each group - from "group.limit" param, default=1
}
public static Collector[] subCollectors(Collector collector) {
if (collector instanceof MultiCollector)
return ((MultiCollector)collector).collectors;
return new Collector[]{collector};
public static class CommandQuery extends Command {
public Query query;
}
public MultiCollector(List<? extends Collector> collectors) {
this(collectors.toArray(new Collector[collectors.size()]));
}
public static class CommandFunc extends Command {
public ValueSource groupBy;
public MultiCollector(Collector[] collectors) {
this.collectors = collectors;
boolean acceptsDocsOutOfOrder = true;
for (Collector collector : collectors) {
if (collector.acceptsDocsOutOfOrder() == false) {
acceptsDocsOutOfOrder = false;
break;
}
}
this.acceptsDocsOutOfOrder = acceptsDocsOutOfOrder;
}
@Override
public void setScorer(Scorer scorer) throws IOException {
for (Collector collector : collectors)
collector.setScorer(scorer);
}
@Override
public void collect(int doc) throws IOException {
for (Collector collector : collectors)
collector.collect(doc);
}
@Override
public void setNextReader(IndexReader reader, int docBase) throws IOException {
for (Collector collector : collectors)
collector.setNextReader(reader, docBase);
}
@Override
public boolean acceptsDocsOutOfOrder() {
return acceptsDocsOutOfOrder;
// todo - find a better place to store these
transient Map context;
transient Collector collector;
}
}
class SearchGroup {
public MutableValue groupValue;
int matches;

View File

@ -923,10 +923,10 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
// TODO: make this a generic collector list
List<TopGroupCollector> collectors = new ArrayList<TopGroupCollector>(cmd.groupCommands.size());
for (GroupCommand groupCommand : cmd.groupCommands) {
for (Grouping.Command groupCommand : cmd.groupCommands) {
// TODO: perhaps use some methods rather than instanceof
if (groupCommand instanceof GroupCommandFunc) {
GroupCommandFunc gc = (GroupCommandFunc)groupCommand;
if (groupCommand instanceof Grouping.CommandFunc) {
Grouping.CommandFunc gc = (Grouping.CommandFunc)groupCommand;
Map context = ValueSource.newContext();
gc.groupBy.createWeight(context, this);
TopGroupCollector collector;
@ -943,7 +943,7 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
}
}
Collector allCollectors = MultiCollector.wrap(collectors);
Collector allCollectors = MultiCollector.wrap(collectors.toArray(new Collector[collectors.size()]));
DocSetCollector setCollector = null;
if (getDocSet) {
// TODO: can callCollectors be zero length?
@ -959,9 +959,9 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
// TODO: make this a generic collector list
List<Phase2GroupCollector> phase2Collectors = new ArrayList<Phase2GroupCollector>(cmd.groupCommands.size());
for (GroupCommand groupCommand : cmd.groupCommands) {
if (groupCommand instanceof GroupCommandFunc) {
GroupCommandFunc gc = (GroupCommandFunc)groupCommand;
for (Grouping.Command groupCommand : cmd.groupCommands) {
if (groupCommand instanceof Grouping.CommandFunc) {
Grouping.CommandFunc gc = (Grouping.CommandFunc)groupCommand;
Sort collectorSort = gc.groupSort == null ? sort : gc.groupSort;
Phase2GroupCollector collector = new Phase2GroupCollector((TopGroupCollector)gc.collector, gc.groupBy, gc.context, collectorSort, gc.docsPerGroup, needScores);
phase2Collectors.add(collector);
@ -969,7 +969,7 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
}
// TODO: optionally cache docs and feed them back through rather than re-searching
search(query, luceneFilter, MultiCollector.wrap(phase2Collectors));
search(query, luceneFilter, MultiCollector.wrap(phase2Collectors.toArray(new Collector[phase2Collectors.size()])));
Set<Integer> idSet = new LinkedHashSet<Integer>(); // used for tracking unique docs when we need a doclist
int maxMatches = 0;
@ -977,8 +977,8 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
NamedList grouped = new SimpleOrderedMap();
for (int cmdnum=0; cmdnum<cmd.groupCommands.size(); cmdnum++) {
GroupCommand groupCommand = cmd.groupCommands.get(cmdnum);
GroupCommandFunc groupCommandFunc = (GroupCommandFunc)groupCommand;
Grouping.Command groupCommand = cmd.groupCommands.get(cmdnum);
Grouping.CommandFunc groupCommandFunc = (Grouping.CommandFunc)groupCommand;
TopGroupCollector collector = collectors.get(cmdnum);
Phase2GroupCollector collector2 = phase2Collectors.get(cmdnum);
@ -1871,7 +1871,7 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
private int flags;
private long timeAllowed = -1;
public List<GroupCommand> groupCommands;
public List<Grouping.Command> groupCommands;
public Query getQuery() { return query; }
public QueryCommand setQuery(Query query) {
@ -1973,21 +1973,6 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
}
}
public static class GroupCommand {
public String key; // the name to use for this group in the response
public Sort groupSort; // the sort of the documents *within* a single group.
public int groupLimit; // how many groups - defaults to the "rows" parameter
public int docsPerGroup; // how many docs in each group - from "group.limit" param, default=1
}
public static class GroupCommandFunc extends GroupCommand {
public ValueSource groupBy;
// todo - find a better place to store these
transient Map context;
transient Collector collector;
}
/**
* The result of a search.