mirror of https://github.com/apache/lucene.git
SOLR-7798: robust support for expand when used w/o collapsing (#325)
There are applications of ExpandComponent that intentionally do not involve prior collapsing of results on the expand field, which can lead to an NPE in expand component when expand.field (for matched docs) has fewer unique values than the number of matched docs. This commit refines the approach taken in SOLR-13877, which addressed the same underlying issue.
This commit is contained in:
parent
07e4d86207
commit
8e9876f516
|
@ -181,7 +181,7 @@ Bug Fixes
|
||||||
* SOLR-12393: Compute score if requested even when expanded docs not sorted by score in ExpandComponent.
|
* SOLR-12393: Compute score if requested even when expanded docs not sorted by score in ExpandComponent.
|
||||||
(David Smiley, Munendra S N)
|
(David Smiley, Munendra S N)
|
||||||
|
|
||||||
* SOLR-13877: Fix NPE in expand component when matched docs have fewer unique values. (Munendra S N)
|
* SOLR-13877, SOLR-7798: Robust support for ExpandComponent when used independently of CollapsingPostFilter. (Jörg Rathlev, Michael Gibney, Munendra S N)
|
||||||
|
|
||||||
* SOLR-13823: Fix ClassCastEx when score is requested with group.query. This also fixes score not being generated
|
* SOLR-13823: Fix ClassCastEx when score is requested with group.query. This also fixes score not being generated
|
||||||
for distributed group.query case. (Uwe Jäger, Munendra S N)
|
for distributed group.query case. (Uwe Jäger, Munendra S N)
|
||||||
|
|
|
@ -281,7 +281,6 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
currentValues = sortedDocValues[currentContext];
|
currentValues = sortedDocValues[currentContext];
|
||||||
segmentOrdinalMap = ordinalMap.getGlobalOrds(currentContext);
|
segmentOrdinalMap = ordinalMap.getGlobalOrds(currentContext);
|
||||||
}
|
}
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
ordBytes = new IntObjectHashMap<>();
|
ordBytes = new IntObjectHashMap<>();
|
||||||
|
|
||||||
|
@ -303,12 +302,12 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
currentValues.advance(contextDoc);
|
currentValues.advance(contextDoc);
|
||||||
}
|
}
|
||||||
if (contextDoc == currentValues.docID()) {
|
if (contextDoc == currentValues.docID()) {
|
||||||
int ord = currentValues.ordValue();
|
int contextOrd = currentValues.ordValue();
|
||||||
++count;
|
int ord = (int)segmentOrdinalMap.get(contextOrd);
|
||||||
BytesRef ref = currentValues.lookupOrd(ord);
|
if (!groupBits.getAndSet(ord)) {
|
||||||
ord = (int)segmentOrdinalMap.get(ord);
|
BytesRef ref = currentValues.lookupOrd(contextOrd);
|
||||||
ordBytes.put(ord, BytesRef.deepCopyOf(ref));
|
ordBytes.put(ord, BytesRef.deepCopyOf(ref));
|
||||||
groupBits.set(ord);
|
}
|
||||||
collapsedSet.add(globalDoc);
|
collapsedSet.add(globalDoc);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -317,22 +316,22 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
}
|
}
|
||||||
if (globalDoc == values.docID()) {
|
if (globalDoc == values.docID()) {
|
||||||
int ord = values.ordValue();
|
int ord = values.ordValue();
|
||||||
++count;
|
if (!groupBits.getAndSet(ord)) {
|
||||||
BytesRef ref = values.lookupOrd(ord);
|
BytesRef ref = values.lookupOrd(ord);
|
||||||
ordBytes.put(ord, BytesRef.deepCopyOf(ref));
|
ordBytes.put(ord, BytesRef.deepCopyOf(ref));
|
||||||
groupBits.set(ord);
|
}
|
||||||
collapsedSet.add(globalDoc);
|
collapsedSet.add(globalDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int count = ordBytes.size();
|
||||||
if(count > 0 && count < 200) {
|
if(count > 0 && count < 200) {
|
||||||
groupQuery = getGroupQuery(field, count, ordBytes);
|
groupQuery = getGroupQuery(field, count, ordBytes);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
groupSet = new LongHashSet(docList.size());
|
groupSet = new LongHashSet(docList.size());
|
||||||
NumericDocValues collapseValues = contexts.get(currentContext).reader().getNumericDocValues(field);
|
NumericDocValues collapseValues = contexts.get(currentContext).reader().getNumericDocValues(field);
|
||||||
int count = 0;
|
|
||||||
for(int i=0; i<globalDocs.length; i++) {
|
for(int i=0; i<globalDocs.length; i++) {
|
||||||
int globalDoc = globalDocs[i];
|
int globalDoc = globalDocs[i];
|
||||||
while(globalDoc >= nextDocBase) {
|
while(globalDoc >= nextDocBase) {
|
||||||
|
@ -353,12 +352,12 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
if(value != nullValue) {
|
if(value != nullValue) {
|
||||||
++count;
|
|
||||||
groupSet.add(value);
|
groupSet.add(value);
|
||||||
collapsedSet.add(globalDoc);
|
collapsedSet.add(globalDoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int count = groupSet.size();
|
||||||
if(count > 0 && count < 200) {
|
if(count > 0 && count < 200) {
|
||||||
if (fieldType.isPointField()) {
|
if (fieldType.isPointField()) {
|
||||||
groupQuery = getPointGroupQuery(schemaField, count, groupSet);
|
groupQuery = getPointGroupQuery(schemaField, count, groupSet);
|
||||||
|
@ -685,7 +684,8 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
int size,
|
int size,
|
||||||
LongHashSet groupSet) {
|
LongHashSet groupSet) {
|
||||||
|
|
||||||
List<BytesRef> bytesRefs = new ArrayList<>(size);
|
BytesRef[] bytesRefs = new BytesRef[size];
|
||||||
|
int index = -1;
|
||||||
BytesRefBuilder term = new BytesRefBuilder();
|
BytesRefBuilder term = new BytesRefBuilder();
|
||||||
Iterator<LongCursor> it = groupSet.iterator();
|
Iterator<LongCursor> it = groupSet.iterator();
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
LongCursor cursor = it.next();
|
LongCursor cursor = it.next();
|
||||||
String stringVal = numericToString(ft, cursor.value);
|
String stringVal = numericToString(ft, cursor.value);
|
||||||
ft.readableToIndexed(stringVal, term);
|
ft.readableToIndexed(stringVal, term);
|
||||||
bytesRefs.add(term.toBytesRef());
|
bytesRefs[++index] = term.toBytesRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TermInSetQuery(fname, bytesRefs);
|
return new TermInSetQuery(fname, bytesRefs);
|
||||||
|
@ -734,11 +734,12 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
|
||||||
private Query getGroupQuery(String fname,
|
private Query getGroupQuery(String fname,
|
||||||
int size,
|
int size,
|
||||||
IntObjectHashMap<BytesRef> ordBytes) {
|
IntObjectHashMap<BytesRef> ordBytes) {
|
||||||
List<BytesRef> bytesRefs = new ArrayList<>(size);
|
BytesRef[] bytesRefs = new BytesRef[size];
|
||||||
|
int index = -1;
|
||||||
Iterator<IntObjectCursor<BytesRef>>it = ordBytes.iterator();
|
Iterator<IntObjectCursor<BytesRef>>it = ordBytes.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
IntObjectCursor<BytesRef> cursor = it.next();
|
IntObjectCursor<BytesRef> cursor = it.next();
|
||||||
bytesRefs.add(cursor.value);
|
bytesRefs[++index] = cursor.value;
|
||||||
}
|
}
|
||||||
return new TermInSetQuery(fname, bytesRefs);
|
return new TermInSetQuery(fname, bytesRefs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,6 +352,19 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
|
||||||
"/response/lst[@name='expanded']/result[@name='2000.0']/doc[1]/str[@name='id'][.='7']",
|
"/response/lst[@name='expanded']/result[@name='2000.0']/doc[1]/str[@name='id'][.='7']",
|
||||||
"count(//*[@name='score'])=0"
|
"count(//*[@name='score'])=0"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Support expand enabled without previous collapse
|
||||||
|
assertQ(req("q", "type_s:child", "sort", group+" asc, test_l desc", "defType", "edismax",
|
||||||
|
"expand", "true", "expand.q", "type_s:parent", "expand.field", group),
|
||||||
|
"*[count(/response/result/doc)=4]",
|
||||||
|
"*[count(/response/lst[@name='expanded']/result)=2]",
|
||||||
|
"/response/result/doc[1]/str[@name='id'][.='7']",
|
||||||
|
"/response/result/doc[2]/str[@name='id'][.='2']",
|
||||||
|
"/response/result/doc[3]/str[@name='id'][.='8']",
|
||||||
|
"/response/result/doc[4]/str[@name='id'][.='6']",
|
||||||
|
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
|
||||||
|
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue