in solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java [2056:2250]
public DelegatingCollector getCollector(
String collapseField,
GroupHeadSelector groupHeadSelector,
SortSpec sortSpec,
int nullPolicy,
String hint,
boolean needsScores4Collapsing,
boolean needsScores,
int size,
IntIntHashMap boostDocs,
SolrIndexSearcher searcher)
throws IOException {
DocValuesProducer docValuesProducer = null;
FunctionQuery funcQuery = null;
// block collapsing logic is much simpler and uses less memory, but is only viable in specific
// situations
final boolean blockCollapse =
(("_root_".equals(collapseField) || HINT_BLOCK.equals(hint))
// because we currently handle all min/max cases using
// AbstractBlockSortSpecCollector, we can't handle functions wrapping cscore()
// (for the same reason cscore() isn't supported in 'sort' local param)
&& (!CollapseScore.wantsCScore(groupHeadSelector.selectorText))
//
&& NullPolicy.COLLAPSE.getCode() != nullPolicy);
if (HINT_BLOCK.equals(hint) && !blockCollapse) {
log.debug(
"Query specifies hint={} but other local params prevent the use block based collapse",
HINT_BLOCK);
}
FieldType collapseFieldType = searcher.getSchema().getField(collapseField).getType();
if (collapseFieldType instanceof StrField) {
// if we are using blockCollapse, then there is no need to bother with TOP_FC
if (HINT_TOP_FC.equals(hint) && !blockCollapse) {
@SuppressWarnings("resource")
final LeafReader uninvertingReader = getTopFieldCacheReader(searcher, collapseField);
docValuesProducer =
new EmptyDocValuesProducer() {
@Override
public SortedDocValues getSorted(FieldInfo ignored) throws IOException {
SortedDocValues values = uninvertingReader.getSortedDocValues(collapseField);
if (values != null) {
return values;
} else {
return DocValues.emptySorted();
}
}
};
} else {
docValuesProducer =
new EmptyDocValuesProducer() {
@Override
public SortedDocValues getSorted(FieldInfo ignored) throws IOException {
return DocValues.getSorted(searcher.getSlowAtomicReader(), collapseField);
}
};
}
} else {
if (HINT_TOP_FC.equals(hint)) {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
"top_fc hint is only supported when collapsing on String Fields");
}
}
FieldType minMaxFieldType = null;
if (GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type)) {
final String text = groupHeadSelector.selectorText;
if (!text.contains("(")) {
minMaxFieldType = searcher.getSchema().getField(text).getType();
} else {
SolrParams params = new ModifiableSolrParams();
try (SolrQueryRequest request = SolrQueryRequest.wrapSearcher(searcher, params)) {
FunctionQParser functionQParser = new FunctionQParser(text, null, params, request);
funcQuery = (FunctionQuery) functionQParser.parse();
} catch (SyntaxError e) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
}
}
}
int maxDoc = searcher.maxDoc();
int leafCount = searcher.getTopReaderContext().leaves().size();
SolrRequestInfo req = SolrRequestInfo.getRequestInfo();
boolean collectElevatedDocsWhenCollapsing =
req != null
&& req.getReq().getParams().getBool(COLLECT_ELEVATED_DOCS_WHEN_COLLAPSING, true);
if (GroupHeadSelectorType.SCORE.equals(groupHeadSelector.type)) {
if (collapseFieldType instanceof StrField) {
if (blockCollapse) {
return new BlockOrdScoreCollector(collapseField, nullPolicy, boostDocs);
}
return new OrdScoreCollector(
maxDoc,
leafCount,
docValuesProducer,
nullPolicy,
boostDocs,
searcher,
collectElevatedDocsWhenCollapsing);
} else if (isNumericCollapsible(collapseFieldType)) {
if (blockCollapse) {
return new BlockIntScoreCollector(collapseField, nullPolicy, boostDocs);
}
return new IntScoreCollector(
maxDoc,
leafCount,
nullPolicy,
size,
collapseField,
boostDocs,
searcher,
collectElevatedDocsWhenCollapsing);
} else {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
"Collapsing field should be of either String, Int or Float type");
}
} else { // min, max, sort, etc.. something other then just "score"
if (collapseFieldType instanceof StrField) {
if (blockCollapse) {
// NOTE: for now we don't worry about wether this is a sortSpec of min/max
// groupHeadSelector, we use a "sort spec' based block collector unless/until there is
// some (performance?) reason to specialize
return new BlockOrdSortSpecCollector(
collapseField,
nullPolicy,
boostDocs,
BlockOrdSortSpecCollector.getSort(groupHeadSelector, sortSpec, funcQuery, searcher),
needsScores || needsScores4Collapsing);
}
return new OrdFieldValueCollector(
maxDoc,
leafCount,
docValuesProducer,
nullPolicy,
groupHeadSelector,
sortSpec,
needsScores4Collapsing,
needsScores,
minMaxFieldType,
boostDocs,
funcQuery,
searcher,
collectElevatedDocsWhenCollapsing);
} else if (isNumericCollapsible(collapseFieldType)) {
if (blockCollapse) {
// NOTE: for now we don't worry about wether this is a sortSpec of min/max
// groupHeadSelector, we use a "sort spec' based block collector unless/until there is
// some (performance?) reason to specialize
return new BlockIntSortSpecCollector(
collapseField,
nullPolicy,
boostDocs,
BlockOrdSortSpecCollector.getSort(groupHeadSelector, sortSpec, funcQuery, searcher),
needsScores || needsScores4Collapsing);
}
return new IntFieldValueCollector(
maxDoc,
size,
leafCount,
nullPolicy,
collapseField,
groupHeadSelector,
sortSpec,
needsScores4Collapsing,
needsScores,
minMaxFieldType,
boostDocs,
funcQuery,
searcher,
collectElevatedDocsWhenCollapsing);
} else {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
"Collapsing field should be of either String, Int or Float type");
}
}
}