You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by yo...@apache.org on 2010/11/02 22:09:10 UTC
svn commit: r1030220 - in /lucene/dev/trunk/solr/src:
java/org/apache/solr/handler/component/QueryComponent.java
java/org/apache/solr/search/Grouping.java
java/org/apache/solr/search/SolrIndexSearcher.java
test/org/apache/solr/TestGroupingSearch.java
Author: yonik
Date: Tue Nov 2 21:09:10 2010
New Revision: 1030220
URL: http://svn.apache.org/viewvc?rev=1030220&view=rev
Log:
SOLR-236: refactor field collapsing, pull out of SolrIndexSearcher
Modified:
lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/Grouping.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java
lucene/dev/trunk/solr/src/test/org/apache/solr/TestGroupingSearch.java
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java?rev=1030220&r1=1030219&r2=1030220&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java Tue Nov 2 21:09:10 2010
@@ -300,8 +300,8 @@ public class QueryComponent extends Sear
boolean doGroup = params.getBool(GroupParams.GROUP, false);
if (doGroup) {
try {
- cmd.groupCommands = new ArrayList<Grouping.Command>();
-
+ Grouping grouping = new Grouping(searcher, result, cmd);
+
String[] fields = params.getParams(GroupParams.GROUP_FIELD);
String[] funcs = params.getParams(GroupParams.GROUP_FUNC);
String[] queries = params.getParams(GroupParams.GROUP_QUERY);
@@ -330,7 +330,7 @@ public class QueryComponent extends Sear
for (String groupByStr : funcs) {
QParser parser = QParser.getParser(groupByStr, "func", rb.req);
Query q = parser.getQuery();
- Grouping.CommandFunc gc = new Grouping.CommandFunc();
+ Grouping.CommandFunc gc = grouping.new CommandFunc();
gc.groupSort = groupSort;
if (q instanceof FunctionQuery) {
@@ -343,8 +343,9 @@ public class QueryComponent extends Sear
gc.docsPerGroup = docsPerGroupDefault;
gc.groupOffset = groupOffsetDefault;
gc.offset = cmd.getOffset();
+ gc.sort = cmd.getSort();
- cmd.groupCommands.add(gc);
+ grouping.add(gc);
}
}
@@ -352,7 +353,7 @@ public class QueryComponent extends Sear
for (String groupByStr : queries) {
QParser parser = QParser.getParser(groupByStr, null, rb.req);
Query gq = parser.getQuery();
- Grouping.CommandQuery gc = new Grouping.CommandQuery();
+ Grouping.CommandQuery gc = grouping.new CommandQuery();
gc.query = gq;
gc.groupSort = groupSort;
gc.key = groupByStr;
@@ -360,26 +361,23 @@ public class QueryComponent extends Sear
gc.docsPerGroup = docsPerGroupDefault;
gc.groupOffset = groupOffsetDefault;
- cmd.groupCommands.add(gc);
+ grouping.add(gc);
}
}
- if (cmd.groupCommands.size() == 0)
- cmd.groupCommands = null;
+ if (rb.doHighlights || rb.isDebug()) {
+ // we need a single list of the returned docs
+ cmd.setFlags(SolrIndexSearcher.GET_DOCLIST);
+ }
- if (cmd.groupCommands != null) {
- if (rb.doHighlights || rb.isDebug()) {
- // we need a single list of the returned docs
- cmd.setFlags(SolrIndexSearcher.GET_DOCLIST);
- }
+ // searcher.search(result,cmd);
+ grouping.execute();
+ rb.setResult( result );
+ rsp.add("grouped", result.groupedResults);
+ // TODO: get "hits" a different way to log
+ return;
- searcher.search(result,cmd);
- rb.setResult( result );
- rsp.add("grouped", result.groupedResults);
- // TODO: get "hits" a different way to log
- return;
- }
} catch (ParseException e) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/Grouping.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/Grouping.java?rev=1030220&r1=1030219&r2=1030220&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/Grouping.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/Grouping.java Tue Nov 2 21:09:10 2010
@@ -19,6 +19,8 @@ package org.apache.solr.search;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.*;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.search.function.DocValues;
import org.apache.solr.search.function.ValueSource;
@@ -27,27 +29,286 @@ import java.util.*;
public class Grouping {
- 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 abstract 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 Sort sort; // the sort between groups
public int docsPerGroup; // how many docs in each group - from "group.limit" param, default=1
- public int groupOffset; // the offset within each group (for paging within each group)
- public int numGroups; // how many groups - defaults to the "rows" parameter
- public int offset; // offset into the list of groups
+ public int groupOffset; // the offset within each group (for paging within each group)
+ public int numGroups; // how many groups - defaults to the "rows" parameter
+ public int offset; // offset into the list of groups
+
+
+ abstract void prepare() throws IOException;
+ abstract Collector createCollector() throws IOException;
+ Collector createNextCollector() throws IOException {
+ return null;
+ }
+ abstract void finish() throws IOException;
+
+ abstract int getMatches();
+
+ NamedList commonResponse() {
+ NamedList groupResult = new SimpleOrderedMap();
+ grouped.add(key, groupResult); // grouped={ key={
+
+ int this_matches = getMatches();
+ groupResult.add("matches", this_matches);
+ maxMatches = Math.max(maxMatches, this_matches);
+ return groupResult;
+ }
+
+ DocList getDocList(TopDocsCollector collector) {
+ int docsToCollect = getMax(groupOffset, docsPerGroup, maxDoc);
+
+ // TODO: implement a DocList impl that doesn't need to start at offset=0
+ TopDocs topDocs = collector.topDocs(0, docsToCollect);
+
+ int ids[] = new int[topDocs.scoreDocs.length];
+ float[] scores = needScores ? new float[topDocs.scoreDocs.length] : null;
+ for (int i=0; i<ids.length; i++) {
+ ids[i] = topDocs.scoreDocs[i].doc;
+ if (scores != null)
+ scores[i] = topDocs.scoreDocs[i].score;
+ }
+
+ float score = topDocs.getMaxScore();
+ maxScore = Math.max(maxScore, score);
+ DocSlice docs = new DocSlice(groupOffset, Math.max(0, ids.length - groupOffset), ids, scores, topDocs.totalHits, score);
+
+ if (getDocList) {
+ DocIterator iter = docs.iterator();
+ while (iter.hasNext())
+ idSet.add(iter.nextDoc());
+ }
+ return docs;
+ }
+
+ void addDocList(NamedList rsp, TopDocsCollector collector) {
+ rsp.add("doclist", getDocList(collector));
+ }
}
- public static class CommandQuery extends Command {
+ public class CommandQuery extends Command {
public Query query;
+
+ TopDocsCollector topCollector;
+ FilterCollector collector;
+
+ @Override
+ void prepare() throws IOException {
+ }
+
+ @Override
+ Collector createCollector() throws IOException {
+ int docsToCollect = getMax(groupOffset, docsPerGroup, maxDoc);
+ DocSet groupFilt = searcher.getDocSet(query);
+ topCollector = newCollector(groupSort, docsToCollect, false, needScores);
+ collector = new FilterCollector(groupFilt, topCollector);
+ return collector;
+ }
+
+ @Override
+ void finish() throws IOException {
+ NamedList rsp = commonResponse();
+ addDocList(rsp, (TopDocsCollector)collector.getCollector());
+ }
+
+ @Override
+ int getMatches() {
+ return collector.getMatches();
+ }
}
- public static class CommandFunc extends Command {
+
+ public class CommandFunc extends Command {
public ValueSource groupBy;
- // todo - find a better place to store these
- transient Map context;
- transient Collector collector;
+ int maxGroupToFind;
+ Map context;
+ TopGroupCollector collector = null;
+ Phase2GroupCollector collector2;
+
+ @Override
+ void prepare() throws IOException {
+ Map context = ValueSource.newContext();
+ groupBy.createWeight(context, searcher);
+ }
+
+ @Override
+ Collector createCollector() throws IOException {
+ maxGroupToFind = getMax(offset, numGroups, maxDoc);
+
+ if (compareSorts(sort, groupSort)) {
+ collector = new TopGroupSortCollector(groupBy, context, normalizeSort(sort), normalizeSort(groupSort), maxGroupToFind);
+ } else {
+ collector = new TopGroupCollector(groupBy, context, normalizeSort(sort), maxGroupToFind);
+ }
+ return collector;
+ }
+
+ @Override
+ Collector createNextCollector() throws IOException {
+ int docsToCollect = getMax(groupOffset, docsPerGroup, maxDoc);
+ if (docsToCollect < 0 || docsToCollect > maxDoc) docsToCollect = maxDoc;
+
+ collector2 = new Phase2GroupCollector(collector, groupBy, context, groupSort, docsToCollect, needScores, offset);
+ return collector2;
+ }
+
+ @Override
+ void finish() throws IOException {
+ NamedList groupResult = commonResponse();
+
+ if (collector.orderedGroups == null) collector.buildSet();
+
+ List groupList = new ArrayList();
+ groupResult.add("groups", groupList); // grouped={ key={ groups=[
+
+ int skipCount = offset;
+ for (SearchGroup group : collector.orderedGroups) {
+ if (skipCount > 0) {
+ skipCount--;
+ continue;
+ }
+ NamedList nl = new SimpleOrderedMap();
+ groupList.add(nl); // grouped={ key={ groups=[ {
+
+ nl.add("groupValue", group.groupValue.toObject());
+
+ SearchGroupDocs groupDocs = collector2.groupMap.get(group.groupValue);
+ addDocList(nl, groupDocs.collector);
+ }
+ }
+
+ @Override
+ int getMatches() {
+ return collector.getMatches();
+ }
+ }
+
+
+
+ static Sort byScoreDesc = new Sort();
+
+ static boolean compareSorts(Sort sort1, Sort sort2) {
+ return sort1 == sort2 || normalizeSort(sort1).equals(normalizeSort(sort2));
+ }
+
+ /** returns a sort by score desc if null */
+ static Sort normalizeSort(Sort sort) {
+ return sort==null ? byScoreDesc : sort;
+ }
+
+ static int getMax(int offset, int len, int max) {
+ int v = len<0 ? max : offset + len;
+ if (v < 0 || v > max) v = max;
+ return v;
}
+
+ static TopDocsCollector newCollector(Sort sort, int numHits, boolean fillFields, boolean needScores) throws IOException {
+ if (sort==null || sort==byScoreDesc) {
+ return TopScoreDocCollector.create(numHits, true);
+ } else {
+ return TopFieldCollector.create(sort, numHits, false, needScores, needScores, true);
+ }
+ }
+
+
+ final SolrIndexSearcher searcher;
+ final SolrIndexSearcher.QueryResult qr;
+ final SolrIndexSearcher.QueryCommand cmd;
+ final List<Command> commands = new ArrayList<Command>();
+
+ public Grouping(SolrIndexSearcher searcher, SolrIndexSearcher.QueryResult qr, SolrIndexSearcher.QueryCommand cmd) {
+ this.searcher = searcher;
+ this.qr = qr;
+ this.cmd = cmd;
+ }
+
+ public void add(Grouping.Command groupingCommand) {
+ commands.add(groupingCommand);
+ }
+
+ int maxDoc;
+ boolean needScores;
+ boolean getDocSet;
+ boolean getDocList; // doclist needed for debugging or highlighting
+ Query query;
+ DocSet filter;
+ Filter luceneFilter;
+ NamedList grouped = new SimpleOrderedMap();
+ Set<Integer> idSet = new LinkedHashSet<Integer>(); // used for tracking unique docs when we need a doclist
+ int maxMatches; // max number of matches from any grouping command
+ float maxScore = Float.NEGATIVE_INFINITY; // max score seen in any doclist
+
+ public void execute() throws IOException {
+ DocListAndSet out = new DocListAndSet();
+ qr.setDocListAndSet(out);
+
+ filter = cmd.getFilter()!=null ? cmd.getFilter() : searcher.getDocSet(cmd.getFilterList());
+
+ maxDoc = searcher.maxDoc();
+
+ needScores = (cmd.getFlags() & SolrIndexSearcher.GET_SCORES) != 0;
+ getDocSet = (cmd.getFlags() & SolrIndexSearcher.GET_DOCSET) != 0;
+ getDocList = (cmd.getFlags() & SolrIndexSearcher.GET_DOCLIST) != 0; // doclist needed for debugging or highlighting
+ query = QueryUtils.makeQueryable(cmd.getQuery());
+
+ for (Command cmd : commands) {
+ cmd.prepare();
+ }
+
+ List<Collector> collectors = new ArrayList<Collector>(commands.size());
+ for (Command cmd : commands) {
+ Collector collector = cmd.createCollector();
+ if (collector != null)
+ collectors.add(collector);
+ }
+
+ Collector allCollectors = MultiCollector.wrap(collectors.toArray(new Collector[collectors.size()]));
+ DocSetCollector setCollector = null;
+ if (getDocSet) {
+ setCollector = new DocSetDelegateCollector(maxDoc>>6, maxDoc, allCollectors);
+ allCollectors = setCollector;
+ }
+
+ searcher.search(query, luceneFilter, allCollectors);
+
+ if (getDocSet) {
+ qr.setDocSet(setCollector.getDocSet());
+ }
+
+ collectors.clear();
+ for (Command cmd : commands) {
+ Collector collector = cmd.createNextCollector();
+ if (collector != null)
+ collectors.add(collector);
+ }
+
+ if (collectors.size() > 0) {
+ searcher.search(query, luceneFilter, MultiCollector.wrap(collectors.toArray(new Collector[collectors.size()])));
+ }
+
+ for (Command cmd : commands) {
+ cmd.finish();
+ }
+
+ qr.groupedResults = grouped;
+
+ if (getDocList) {
+ int sz = idSet.size();
+ int[] ids = new int[sz];
+ int idx = 0;
+ for (int val : idSet) {
+ ids[idx++] = val;
+ }
+ qr.setDocList(new DocSlice(0, sz, ids, null, maxMatches, maxScore));
+ }
+ }
+
}
@@ -82,11 +343,11 @@ abstract class GroupCollector extends Co
class FilterCollector extends GroupCollector {
private final DocSet filter;
- private final TopFieldCollector collector;
+ private final Collector collector;
private int docBase;
private int matches;
- public FilterCollector(DocSet filter, TopFieldCollector collector) throws IOException {
+ public FilterCollector(DocSet filter, Collector collector) throws IOException {
this.filter = filter;
this.collector = collector;
}
@@ -119,7 +380,7 @@ class FilterCollector extends GroupColle
return matches;
}
- TopFieldCollector getTopFieldCollector() {
+ Collector getCollector() {
return collector;
}
}
@@ -527,7 +788,10 @@ class Phase2GroupCollector extends Colle
}
SearchGroupDocs groupDocs = new SearchGroupDocs();
groupDocs.groupValue = group.groupValue;
- groupDocs.collector = TopFieldCollector.create(sort, docsPerGroup, getSortFields, getScores, getScores, true);
+ if (sort==null)
+ groupDocs.collector = TopScoreDocCollector.create(docsPerGroup, true);
+ else
+ groupDocs.collector = TopFieldCollector.create(sort, docsPerGroup, getSortFields, getScores, getScores, true);
groupMap.put(groupDocs.groupValue, groupDocs);
}
@@ -571,6 +835,6 @@ class Phase2GroupCollector extends Colle
// disad: blows up the size of SearchGroup if we need many of them, and couples implementations
class SearchGroupDocs {
public MutableValue groupValue;
- TopFieldCollector collector;
+ TopDocsCollector collector;
}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java?rev=1030220&r1=1030219&r2=1030220&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java Tue Nov 2 21:09:10 2010
@@ -983,238 +983,19 @@ public class SolrIndexSearcher extends I
return qr.getDocList();
}
- private static final int NO_CHECK_QCACHE = 0x80000000;
- private static final int GET_DOCSET = 0x40000000;
- private static final int NO_CHECK_FILTERCACHE = 0x20000000;
+ static final int NO_CHECK_QCACHE = 0x80000000;
+ static final int GET_DOCSET = 0x40000000;
+ static final int NO_CHECK_FILTERCACHE = 0x20000000;
public static final int GET_DOCLIST = 0x02; // get the documents actually returned in a response
public static final int GET_SCORES = 0x01;
- private void groupBy(QueryResult qr, QueryCommand cmd) throws IOException {
- DocListAndSet out = new DocListAndSet();
- qr.setDocListAndSet(out);
-
- DocSet filter = cmd.getFilter()!=null ? cmd.getFilter() : getDocSet(cmd.getFilterList());
-
- int maxDoc = maxDoc();
-
- boolean needScores = (cmd.getFlags() & GET_SCORES) != 0;
- boolean getDocSet = (cmd.getFlags() & GET_DOCSET) != 0;
- boolean getDocList = (cmd.getFlags() & GET_DOCLIST) != 0; // doclist needed for debugging or highlighting
- Query query = QueryUtils.makeQueryable(cmd.getQuery());
-
- final Filter luceneFilter = filter==null ? null : filter.getTopFilter();
-
- Sort sort = cmd.getSort();
- if (sort == null) sort = new Sort();
-
- List<GroupCollector> collectors = new ArrayList<GroupCollector>(cmd.groupCommands.size());
- for (Grouping.Command groupCommand : cmd.groupCommands) {
- // TODO: perhaps use some methods rather than instanceof
- if (groupCommand instanceof Grouping.CommandFunc) {
- Grouping.CommandFunc gc = (Grouping.CommandFunc)groupCommand;
- Map context = ValueSource.newContext();
- gc.groupBy.createWeight(context, this);
- TopGroupCollector collector;
-
- int groupsToCollect = gc.numGroups<0 ? maxDoc : gc.offset + gc.numGroups;
- if (groupsToCollect < 0 || groupsToCollect > maxDoc) groupsToCollect = maxDoc;
-
- if (gc.groupSort != null && gc.groupSort != sort) {
- collector = new TopGroupSortCollector(gc.groupBy, context, sort, gc.groupSort, groupsToCollect);
- } else {
- collector = new TopGroupCollector(gc.groupBy, context, sort, groupsToCollect);
- }
- collectors.add(collector);
-
- // for next phase
- gc.context = context;
- gc.collector = collector;
- }
-
- if (groupCommand instanceof Grouping.CommandQuery) {
- int docsToCollect = groupCommand.docsPerGroup<0 ? maxDoc : groupCommand.groupOffset + groupCommand.docsPerGroup;
- if (docsToCollect < 0 || docsToCollect > maxDoc) docsToCollect = maxDoc;
-
- DocSet groupFilt = getDocSet(((Grouping.CommandQuery)groupCommand).query);
- TopFieldCollector collector = TopFieldCollector.create(groupCommand.groupSort==null ? sort : groupCommand.groupSort, docsToCollect, false, needScores, needScores, true);
- collectors.add(new FilterCollector(groupFilt, collector));
- }
- }
-
- Collector allCollectors = MultiCollector.wrap(collectors.toArray(new Collector[collectors.size()]));
- DocSetCollector setCollector = null;
- if (getDocSet) {
- // TODO: can callCollectors be zero length?
- setCollector = new DocSetDelegateCollector(maxDoc()>>6, maxDoc(), allCollectors);
- allCollectors = setCollector;
- }
-
- search(query, luceneFilter, allCollectors);
-
- if (getDocSet) {
- qr.docListAndSet.docSet = setCollector.getDocSet();
- }
-
- // TODO: make this a generic collector list
- int numPhase2 = 0;
- List<Phase2GroupCollector> phase2Collectors = new ArrayList<Phase2GroupCollector>(cmd.groupCommands.size());
- 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;
-
- int docsToCollect = groupCommand.docsPerGroup<0 ? maxDoc : groupCommand.groupOffset + groupCommand.docsPerGroup;
- if (docsToCollect < 0 || docsToCollect > maxDoc) docsToCollect = maxDoc;
-
- Phase2GroupCollector collector = new Phase2GroupCollector((TopGroupCollector)gc.collector, gc.groupBy, gc.context, collectorSort, docsToCollect, needScores, groupCommand.offset);
- phase2Collectors.add(collector);
- numPhase2++;
- } else if (groupCommand instanceof Grouping.CommandQuery) {
- phase2Collectors.add(null);
- } else {
- phase2Collectors.add(null);
- }
- }
-
- // TODO: optionally cache docs and feed them back through rather than re-searching
- if (numPhase2 > 0)
- 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;
- float maxScore = Float.NEGATIVE_INFINITY;
-
- NamedList grouped = new SimpleOrderedMap();
- for (int cmdnum=0; cmdnum<cmd.groupCommands.size(); cmdnum++) {
- Grouping.Command groupCommand = cmd.groupCommands.get(cmdnum);
- GroupCollector gcollector = collectors.get(cmdnum);
-
- NamedList groupResult = new SimpleOrderedMap();
- grouped.add(groupCommand.key, groupResult); // grouped={ key={
-
- int this_matches = gcollector.getMatches();
- groupResult.add("matches", this_matches);
- maxMatches = Math.max(maxMatches, this_matches);
-
- // TODO: refactor this
- if (groupCommand instanceof Grouping.CommandQuery) {
-
- int docsToCollect = groupCommand.docsPerGroup<0 ? maxDoc : groupCommand.groupOffset + groupCommand.docsPerGroup;
- if (docsToCollect < 0 || docsToCollect > maxDoc) docsToCollect = maxDoc;
-
- TopDocs topDocs = ((FilterCollector)gcollector).getTopFieldCollector().topDocs(0, docsToCollect);
-
- // TODO: refactor
-
- //topDocs.totalHits
- int ids[] = new int[topDocs.scoreDocs.length];
- float[] scores = needScores ? new float[topDocs.scoreDocs.length] : null;
- for (int i=0; i<ids.length; i++) {
- ids[i] = topDocs.scoreDocs[i].doc;
- if (scores != null)
- scores[i] = topDocs.scoreDocs[i].score;
- }
-
- float score = topDocs.getMaxScore();
- maxScore = Math.max(maxScore, score);
- DocSlice docs = new DocSlice(groupCommand.groupOffset, Math.max(0, ids.length - groupCommand.groupOffset), ids, scores, topDocs.totalHits, score);
- groupResult.add("doclist", docs);
-
- if (getDocList) {
- DocIterator iter = docs.iterator();
- while (iter.hasNext())
- idSet.add(iter.nextDoc());
- }
-
- continue;
- }
-
- Grouping.CommandFunc groupCommandFunc = (Grouping.CommandFunc)groupCommand;
- TopGroupCollector collector = (TopGroupCollector)gcollector;
- Phase2GroupCollector collector2 = phase2Collectors.get(cmdnum);
-
- if (collector.orderedGroups == null) collector.buildSet();
-
- List groupList = new ArrayList();
- groupResult.add("groups", groupList); // grouped={ key={ groups=[
-
- int skipCount = groupCommand.offset;
- for (SearchGroup group : collector.orderedGroups) {
- if (skipCount > 0) {
- skipCount--;
- continue;
- }
- NamedList nl = new SimpleOrderedMap();
- groupList.add(nl); // grouped={ key={ groups=[ {
-
- nl.add("groupValue", group.groupValue.toObject());
-
- SearchGroupDocs groupDocs = collector2.groupMap.get(group.groupValue);
- // nl.add("matches", groupDocs.matches); // redundant with doclist.numFound from the doc list
-
- int docsToCollect = groupCommand.docsPerGroup<0 ? maxDoc : groupCommand.groupOffset + groupCommand.docsPerGroup;
- if (docsToCollect < 0 || docsToCollect > maxDoc) docsToCollect = maxDoc;
-
- TopDocs topDocs = groupDocs.collector.topDocs(0, docsToCollect);
- //topDocs.totalHits
- int ids[] = new int[topDocs.scoreDocs.length];
- float[] scores = needScores ? new float[topDocs.scoreDocs.length] : null;
- for (int i=0; i<ids.length; i++) {
- ids[i] = topDocs.scoreDocs[i].doc;
- if (scores != null)
- scores[i] = topDocs.scoreDocs[i].score;
- }
-
- float score = topDocs.getMaxScore();
- maxScore = Math.max(maxScore, score);
- DocSlice docs = new DocSlice(groupCommand.groupOffset, Math.max(0, ids.length - groupCommand.groupOffset), ids, scores, topDocs.totalHits, score);
- nl.add("doclist", docs);
-
- if (getDocList) {
- DocIterator iter = docs.iterator();
- while (iter.hasNext())
- idSet.add(iter.nextDoc());
- }
- /*** values from stage 1
- DocSlice docs = new DocSlice(0, 1, new int[] {group.topDoc}, null, 1, 0);
- nl.add("docs", docs);
-
- Object[] vals = new Object[collector.comparators.length];
- for (int i=0; i<vals.length; i++) {
- vals[i] = collector.comparators[i].value(group.comparatorSlot);
- }
- nl.add("groupSortValue", vals);
- groupResult.add(nl);
- ***/
- }
- }
-
- qr.groupedResults = grouped;
-
- if (getDocList) {
- int sz = idSet.size();
- int[] ids = new int[sz];
- int idx = 0;
- for (int val : idSet) {
- ids[idx++] = val;
- }
- qr.docListAndSet.docList = new DocSlice(0, sz, ids, null, maxMatches, maxScore);
- }
-
- }
-
/**
* getDocList version that uses+populates query and filter caches.
* In the event of a timeout, the cache is not populated.
*/
private void getDocListC(QueryResult qr, QueryCommand cmd) throws IOException {
- if (cmd.groupCommands != null) {
- groupBy(qr, cmd);
- return;
- }
-
DocListAndSet out = new DocListAndSet();
qr.setDocListAndSet(out);
QueryResultKey key=null;
@@ -2025,7 +1806,7 @@ public class SolrIndexSearcher extends I
private int flags;
private long timeAllowed = -1;
- public List<Grouping.Command> groupCommands;
+ // public List<Grouping.Command> groupCommands;
public Query getQuery() { return query; }
public QueryCommand setQuery(Query query) {
Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/TestGroupingSearch.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/TestGroupingSearch.java?rev=1030220&r1=1030219&r2=1030220&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/TestGroupingSearch.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/TestGroupingSearch.java Tue Nov 2 21:09:10 2010
@@ -105,27 +105,6 @@ public class TestGroupingSearch extends
);
}
- @Test
- public void testGroupingGroupSortingName() {
- assertU(add(doc("id", "1","name", "author1", "title", "a book title")));
- assertU(add(doc("id", "2","name", "author1", "title", "the title")));
- assertU(add(doc("id", "3","name", "author2", "title", "book title")));
- assertU(add(doc("id", "4","name", "author2", "title", "the title")));
- assertU(commit());
-
- assertQ(req("q","title:title", "group", "true", "group.field","name", "group.sort", "title asc")
- ,"*[count(//arr[@name='groups']/lst) = 2]"
- ,"//arr[@name='groups']/lst[1]/str[@name='groupValue'][.='author2']"
- // ,"//arr[@name='groups']/lst[1]/int[@name='matches'][.='2']"
- ,"//arr[@name='groups']/lst[1]/result[@numFound='2']"
- ,"//arr[@name='groups']/lst[1]/result/doc/*[@name='id'][.='3']"
-
- ,"//arr[@name='groups']/lst[2]/str[@name='groupValue'][.='author1']"
- // ,"//arr[@name='groups']/lst[2]/int[@name='matches'][.='2']"
- ,"//arr[@name='groups']/lst[2]/result[@numFound='2']"
- ,"//arr[@name='groups']/lst[2]/result/doc/*[@name='id'][.='1']"
- );
- }
@Test
public void testGroupingGroupSortingWeight() {