SOLR-15078: Fix ExpandComponent behavior when expanding on numeric fields to differentiate '0' group from null group

This commit is contained in:
Chris Hostetter 2021-01-25 11:33:57 -07:00
parent 166d39a12e
commit 47a89aca71
5 changed files with 301 additions and 263 deletions

View File

@ -212,7 +212,7 @@ Optimizations
Bug Fixes Bug Fixes
--------------------- ---------------------
(No changes) * SOLR-15078: Fix ExpandComponent behavior when expanding on numeric fields to differentiate '0' group from null group (hossman)
Other Changes Other Changes
--------------------- ---------------------

View File

@ -71,7 +71,6 @@ import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.FieldType; import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.NumberType;
import org.apache.solr.schema.SchemaField; import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField; import org.apache.solr.schema.StrField;
import org.apache.solr.search.CollapsingQParserPlugin; import org.apache.solr.search.CollapsingQParserPlugin;
@ -214,7 +213,6 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
FieldType fieldType = schemaField.getType(); FieldType fieldType = schemaField.getType();
SortedDocValues values = null; SortedDocValues values = null;
long nullValue = 0L;
if(fieldType instanceof StrField) { if(fieldType instanceof StrField) {
//Get The Top Level SortedDocValues //Get The Top Level SortedDocValues
@ -225,28 +223,7 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
} else { } else {
values = DocValues.getSorted(reader, field); values = DocValues.getSorted(reader, field);
} }
} else if (fieldType.getNumberType() != null) { } else if (fieldType.getNumberType() == null) {
//Get the nullValue for the numeric collapse field
String defaultValue = searcher.getSchema().getField(field).getDefaultValue();
final NumberType numType = fieldType.getNumberType();
// Since the expand component depends on the operation of the collapse component,
// which validates that numeric field types are 32-bit,
// we don't need to handle invalid 64-bit field types here.
// FIXME: what happens when expand.field specified?
// how would this work for date field?
// SOLR-10400: before this, long and double were explicitly handled
if (defaultValue != null) {
if (numType == NumberType.INTEGER) {
nullValue = Long.parseLong(defaultValue);
} else if (numType == NumberType.FLOAT) {
nullValue = Float.floatToIntBits(Float.parseFloat(defaultValue));
}
} else if (NumberType.FLOAT.equals(numType)) { // Integer case already handled by nullValue defaulting to 0
nullValue = Float.floatToIntBits(0.0f);
}
} else {
// possible if directly expand.field is specified // possible if directly expand.field is specified
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"Expand not supported for fieldType:'" + fieldType.getTypeName() +"'"); "Expand not supported for fieldType:'" + fieldType.getTypeName() +"'");
@ -358,13 +335,8 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
if (valueDocID < contextDoc) { if (valueDocID < contextDoc) {
valueDocID = collapseValues.advance(contextDoc); valueDocID = collapseValues.advance(contextDoc);
} }
long value;
if (valueDocID == contextDoc) { if (valueDocID == contextDoc) {
value = collapseValues.longValue(); final long value = collapseValues.longValue();
} else {
value = 0;
}
if(value != nullValue) {
groupSet.add(value); groupSet.add(value);
collapsedSet.add(globalDoc); collapsedSet.add(globalDoc);
} }
@ -399,7 +371,7 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
groupExpandCollector = new GroupExpandCollector(values, groupBits, collapsedSet, limit, sort); groupExpandCollector = new GroupExpandCollector(values, groupBits, collapsedSet, limit, sort);
} else { } else {
groupExpandCollector = new NumericGroupExpandCollector(field, nullValue, groupSet, collapsedSet, limit, sort); groupExpandCollector = new NumericGroupExpandCollector(field, groupSet, collapsedSet, limit, sort);
} }
if(groupQuery != null) { if(groupQuery != null) {
@ -628,11 +600,9 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
private LongObjectHashMap<Collector> groups; private LongObjectHashMap<Collector> groups;
private IntHashSet collapsedSet; private IntHashSet collapsedSet;
private long nullValue;
public NumericGroupExpandCollector(String field, long nullValue, LongHashSet groupSet, IntHashSet collapsedSet, int limit, Sort sort) throws IOException { public NumericGroupExpandCollector(String field, LongHashSet groupSet, IntHashSet collapsedSet, int limit, Sort sort) throws IOException {
int numGroups = collapsedSet.size(); int numGroups = collapsedSet.size();
this.nullValue = nullValue;
groups = new LongObjectHashMap<>(numGroups); groups = new LongObjectHashMap<>(numGroups);
for (LongCursor cursor : groupSet) { for (LongCursor cursor : groupSet) {
groups.put(cursor.value, getCollector(limit, sort)); groups.put(cursor.value, getCollector(limit, sort));
@ -663,17 +633,12 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
@Override @Override
public void collect(int docId) throws IOException { public void collect(int docId) throws IOException {
long value;
if (docValues.advanceExact(docId)) { if (docValues.advanceExact(docId)) {
value = docValues.longValue(); final long value = docValues.longValue();
} else { final int index = leafCollectors.indexOf(value);
value = 0; if (index >= 0 && !collapsedSet.contains(docId + docBase)) {
} leafCollectors.indexGet(index).collect(docId);
final int index; }
if (value != nullValue &&
(index = leafCollectors.indexOf(value)) >= 0 &&
!collapsedSet.contains(docId + docBase)) {
leafCollectors.indexGet(index).collect(docId);
} }
} }
}; };

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.solr.handler.component; package org.apache.solr.handler.component;
import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -26,7 +27,6 @@ import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ModifiableSolrParams;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test;
/** /**
* Test for distributed ExpandComponent * Test for distributed ExpandComponent
@ -44,25 +44,36 @@ public class DistributedExpandComponentTest extends BaseDistributedSearchTestCas
initCore("solrconfig-collapseqparser.xml", "schema11.xml"); initCore("solrconfig-collapseqparser.xml", "schema11.xml");
} }
@Test
@ShardsFixed(num = 3) @ShardsFixed(num = 3)
public void test() throws Exception { public void test() throws Exception {
final String group = (random().nextBoolean() ? "group_s" : "group_s_dv"); _test("group_s", "g1", "g2", "g3", "g4");
_test("group_s_dv", "g1", "g2", "g3", "g4");
_test("group_i", "1", "0", "3", "-1"); // NOTE: using 0 to explicitly confim we don't assume null
_test("group_ti_dv", "1", "-2", "0", "4"); // NOTE: using 0 to explicitly confim we don't assume null
}
private void _test(final String group,
final String aaa, final String bbb, final String ccc, final String ddd) throws Exception {
del("*:*"); del("*:*");
index_specific(0,"id","1", "term_s", "YYYY", group, "group1", "test_i", "5", "test_l", "10", "test_f", "2000"); index_specific(0,"id","1", "term_s", "YYYY", group, aaa, "test_i", "5", "test_l", "10", "test_f", "2000");
index_specific(0,"id","2", "term_s", "YYYY", group, "group1", "test_i", "50", "test_l", "100", "test_f", "200"); index_specific(0,"id","2", "term_s", "YYYY", group, aaa, "test_i", "50", "test_l", "100", "test_f", "200");
index_specific(1,"id","5", "term_s", "YYYY", group, "group2", "test_i", "4", "test_l", "10", "test_f", "2000"); index_specific(1,"id","5", "term_s", "YYYY", group, bbb, "test_i", "4", "test_l", "10", "test_f", "2000");
index_specific(1,"id","6", "term_s", "YYYY", group, "group2", "test_i", "10", "test_l", "100", "test_f", "200"); index_specific(1,"id","6", "term_s", "YYYY", group, bbb, "test_i", "10", "test_l", "100", "test_f", "200");
index_specific(0,"id","7", "term_s", "YYYY", group, "group1", "test_i", "1", "test_l", "100000", "test_f", "2000"); index_specific(0,"id","7", "term_s", "YYYY", group, aaa, "test_i", "1", "test_l", "100000", "test_f", "2000");
index_specific(1,"id","8", "term_s", "YYYY", group, "group2", "test_i", "2", "test_l", "100000", "test_f", "200"); index_specific(1,"id","8", "term_s", "YYYY", group, bbb, "test_i", "2", "test_l", "100000", "test_f", "200");
index_specific(2,"id","9", "term_s", "YYYY", group, "group3", "test_i", "1000", "test_l", "1005", "test_f", "3000"); index_specific(2,"id","9", "term_s", "YYYY", group, ccc, "test_i", "1000", "test_l", "1005", "test_f", "3000");
index_specific(2, "id", "10", "term_s", "YYYY", group, "group3", "test_i", "1500", "test_l", "1001", "test_f", "3200"); index_specific(2,"id","10","term_s", "YYYY", group, ccc, "test_i", "1500", "test_l", "1001", "test_f", "3200");
index_specific(2,"id", "11", "term_s", "YYYY", group, "group3", "test_i", "1300", "test_l", "1002", "test_f", "3300");
index_specific(1,"id","12", "term_s", "YYYY", group, "group4", "test_i", "15", "test_l", "10", "test_f", "2000"); // NOTE: nullPolicy=collapse will only be viable because all null docs are in collocated in shard #2
index_specific(1,"id","13", "term_s", "YYYY", group, "group4", "test_i", "16", "test_l", "9", "test_f", "2000"); index_specific(2,"id","88", "test_i", "1001", "test_l", "1001", "test_f", "3200");
index_specific(1,"id","14", "term_s", "YYYY", group, "group4", "test_i", "1", "test_l", "20", "test_f", "2000"); index_specific(2,"id","99", "test_i", "11", "test_l", "100", "test_f", "200");
index_specific(2,"id","11","term_s", "YYYY", group, ccc, "test_i", "1300", "test_l", "1002", "test_f", "3300");
index_specific(1,"id","12","term_s", "YYYY", group, ddd, "test_i", "15", "test_l", "10", "test_f", "2000");
index_specific(1,"id","13","term_s", "YYYY", group, ddd, "test_i", "16", "test_l", "9", "test_f", "2000");
index_specific(1,"id","14","term_s", "YYYY", group, ddd, "test_i", "1", "test_l", "20", "test_f", "2000");
commit(); commit();
@ -91,7 +102,7 @@ public class DistributedExpandComponentTest extends BaseDistributedSearchTestCas
query("q", "*:*", "start","1", "rows", "1", "fq", "{!collapse field="+group+"}", "defType", "edismax", "bf", "field(test_i)", "expand", "true", "fl","*,score"); query("q", "*:*", "start","1", "rows", "1", "fq", "{!collapse field="+group+"}", "defType", "edismax", "bf", "field(test_i)", "expand", "true", "fl","*,score");
// multiple collapse and equal cost // multiple collapse and equal cost
ModifiableSolrParams baseParams = params("q", "*:*", "defType", "edismax", "expand", "true", "fl", "*,score", ModifiableSolrParams baseParams = params("q", "term_s:YYYY", "defType", "edismax", "expand", "true", "fl", "*,score",
"bf", "field(test_i)", "expand.sort", "id asc"); "bf", "field(test_i)", "expand.sort", "id asc");
baseParams.set("fq", "{!collapse field="+group+"}", "{!collapse field=test_i}"); baseParams.set("fq", "{!collapse field="+group+"}", "{!collapse field=test_i}");
query(baseParams); query(baseParams);
@ -110,137 +121,185 @@ public class DistributedExpandComponentTest extends BaseDistributedSearchTestCas
assertTrue(e.getMessage().contains("missing expand field")); assertTrue(e.getMessage().contains("missing expand field"));
resetExceptionIgnores(); resetExceptionIgnores();
//First basic test case. // Since none of these queries will match any doc w/null in the group field, it shouldn't matter what nullPolicy is used...
ModifiableSolrParams params = new ModifiableSolrParams(); for (String np : Arrays.asList("", " nullPolicy=ignore", " nullPolicy=expand", " nullPolicy=collapse")) {
params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+"}"); //First basic test case.
params.add("defType", "edismax"); ModifiableSolrParams params = new ModifiableSolrParams();
params.add("bf", "field(test_i)"); params.add("q", "term_s:YYYY");
params.add("expand", "true"); params.add("fq", "{!collapse field="+group+np+"}");
params.add("defType", "edismax");
setDistributedParams(params); params.add("bf", "field(test_i)");
QueryResponse rsp = queryServer(params); params.add("expand", "true");
Map<String, SolrDocumentList> results = rsp.getExpandedResults();
assertExpandGroups(results, "group1","group2", "group3", "group4"); setDistributedParams(params);
assertExpandGroupCountAndOrder("group1", 2, results, "1", "7"); QueryResponse rsp = queryServer(params);
assertExpandGroupCountAndOrder("group2", 2, results, "5", "8"); assertCountAndOrder(4, rsp.getResults(), "10" /* c */, "2" /* a */, "13" /* d */, "6" /* b */);
assertExpandGroupCountAndOrder("group3", 2, results, "11", "9"); Map<String, SolrDocumentList> results = rsp.getExpandedResults();
assertExpandGroupCountAndOrder("group4", 2, results, "12", "14"); assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 2, results, "1", "7");
assertExpandGroupCountAndOrder(bbb, 2, results, "5", "8");
assertExpandGroupCountAndOrder(ccc, 2, results, "11", "9");
assertExpandGroupCountAndOrder(ddd, 2, results, "12", "14");
//Test expand.sort
params = new ModifiableSolrParams();
params.add("q", "term_s:YYYY");
params.add("fq", "{!collapse field="+group+np+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("expand.sort", "test_l desc");
setDistributedParams(params);
rsp = queryServer(params);
assertCountAndOrder(4, rsp.getResults(), "10" /* c */, "2" /* a */, "13" /* d */, "6" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 2, results, "7", "1");
assertExpandGroupCountAndOrder(bbb, 2, results, "8", "5");
assertExpandGroupCountAndOrder(ccc, 2, results, "9", "11");
assertExpandGroupCountAndOrder(ddd, 2, results, "14", "12");
//Test expand.sort //Test expand.rows
params = new ModifiableSolrParams();
params.add("q", "term_s:YYYY");
params.add("fq", "{!collapse field="+group+np+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("expand.sort", "test_l desc");
params.add("expand.rows", "1");
setDistributedParams(params);
rsp = queryServer(params);
assertCountAndOrder(4, rsp.getResults(), "10" /* c */, "2" /* a */, "13" /* d */, "6" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 1, results, "7");
assertExpandGroupCountAndOrder(bbb, 1, results, "8");
assertExpandGroupCountAndOrder(ccc, 1, results, "9");
assertExpandGroupCountAndOrder(ddd, 1, results, "14");
//Test expand.rows = 0 - no docs only expand count
params = new ModifiableSolrParams();
params.add("q", "term_s:YYYY");
params.add("fq", "{!collapse field="+group+np+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("expand.rows", "0");
params.add("fl", "id");
setDistributedParams(params);
rsp = queryServer(params);
assertCountAndOrder(4, rsp.getResults(), "10" /* c */, "2" /* a */, "13" /* d */, "6" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 0, results);
assertExpandGroupCountAndOrder(bbb, 0, results);
assertExpandGroupCountAndOrder(ccc, 0, results);
assertExpandGroupCountAndOrder(ddd, 0, results);
//Test expand.rows = 0 with expand.field
params = new ModifiableSolrParams();
params.add("q", "term_s:YYYY");
params.add("fq", "test_l:10");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("expand.fq", "test_f:2000");
params.add("expand.field", group);
params.add("expand.rows", "0");
params.add("fl", "id,score");
setDistributedParams(params);
rsp = queryServer(params);
assertCountAndOrder(3, rsp.getResults(), "12" /* d */, "1" /* a */, "5" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, ddd);
assertExpandGroupCountAndOrder(aaa, 0, results);
assertExpandGroupCountAndOrder(ddd, 0, results);
//Test key-only fl
params = new ModifiableSolrParams();
params.add("q", "term_s:YYYY");
params.add("fq", "{!collapse field="+group+np+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("fl", "id");
setDistributedParams(params);
rsp = queryServer(params);
assertCountAndOrder(4, rsp.getResults(), "10" /* c */, "2" /* a */, "13" /* d */, "6" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 2, results, "1", "7");
assertExpandGroupCountAndOrder(bbb, 2, results, "5", "8");
assertExpandGroupCountAndOrder(ccc, 2, results, "11", "9");
assertExpandGroupCountAndOrder(ddd, 2, results, "12", "14");
//Test distrib.singlePass true
params = new ModifiableSolrParams();
params.add("q", "term_s:YYYY");
params.add("fq", "{!collapse field="+group+np+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("distrib.singlePass", "true");
setDistributedParams(params);
rsp = queryServer(params);
assertCountAndOrder(4, rsp.getResults(), "10" /* c */, "2" /* a */, "13" /* d */, "6" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 2, results, "1", "7");
assertExpandGroupCountAndOrder(bbb, 2, results, "5", "8");
assertExpandGroupCountAndOrder(ccc, 2, results, "11", "9");
assertExpandGroupCountAndOrder(ddd, 2, results, "12", "14");
}
params = new ModifiableSolrParams(); { // queries matching all docs to test null groups from collapse and how it affects expand
params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+"}"); ModifiableSolrParams params = new ModifiableSolrParams();
params.add("defType", "edismax"); params.add("q", "*:*");
params.add("bf", "field(test_i)"); params.add("defType", "edismax");
params.add("expand", "true"); params.add("bf", "field(test_i)");
params.add("expand.sort", "test_l desc"); params.add("expand", "true");
setDistributedParams(params); setDistributedParams(params);
rsp = queryServer(params);
results = rsp.getExpandedResults(); // nullPolicy=expand
assertExpandGroups(results, "group1","group2", "group3", "group4"); params.add("fq", "{!collapse field="+group+" nullPolicy=expand}");
assertExpandGroupCountAndOrder("group1", 2, results, "7", "1");
assertExpandGroupCountAndOrder("group2", 2, results, "8", "5"); QueryResponse rsp = queryServer(params);
assertExpandGroupCountAndOrder("group3", 2, results, "9", "11"); assertCountAndOrder(6, rsp.getResults(), "10" /* c */, "88" /* null */, "2" /* a */, "13" /* d */, "99" /* null */, "6" /* b */);
assertExpandGroupCountAndOrder("group4", 2, results, "14", "12"); Map<String, SolrDocumentList> results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 2, results, "1", "7");
assertExpandGroupCountAndOrder(bbb, 2, results, "5", "8");
assertExpandGroupCountAndOrder(ccc, 2, results, "11", "9");
assertExpandGroupCountAndOrder(ddd, 2, results, "12", "14");
// nullPolicy=collapse
params.set("fq", "{!collapse field="+group+" nullPolicy=collapse}");
rsp = queryServer(params);
assertCountAndOrder(5, rsp.getResults(), "10" /* c */, "88" /* null */, "2" /* a */, "13" /* d */, "6" /* b */);
results = rsp.getExpandedResults();
assertExpandGroups(results, aaa, bbb, ccc, ddd);
assertExpandGroupCountAndOrder(aaa, 2, results, "1", "7");
assertExpandGroupCountAndOrder(bbb, 2, results, "5", "8");
assertExpandGroupCountAndOrder(ccc, 2, results, "11", "9");
assertExpandGroupCountAndOrder(ddd, 2, results, "12", "14");
//Test expand.rows }
params = new ModifiableSolrParams();
params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("expand.sort", "test_l desc");
params.add("expand.rows", "1");
setDistributedParams(params);
rsp = queryServer(params);
results = rsp.getExpandedResults();
assertExpandGroups(results, "group1","group2", "group3", "group4");
assertExpandGroupCountAndOrder("group1", 1, results, "7");
assertExpandGroupCountAndOrder("group2", 1, results, "8");
assertExpandGroupCountAndOrder("group3", 1, results, "9");
assertExpandGroupCountAndOrder("group4", 1, results, "14");
//Test expand.rows = 0 - no docs only expand count
params = new ModifiableSolrParams();
params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("expand.rows", "0");
params.add("fl", "id");
setDistributedParams(params);
rsp = queryServer(params);
results = rsp.getExpandedResults();
assertExpandGroups(results, "group1","group2", "group3", "group4");
assertExpandGroupCountAndOrder("group1", 0, results);
assertExpandGroupCountAndOrder("group2", 0, results);
assertExpandGroupCountAndOrder("group3", 0, results);
assertExpandGroupCountAndOrder("group4", 0, results);
//Test expand.rows = 0 with expand.field
params = new ModifiableSolrParams();
params.add("q", "*:*");
params.add("fq", "test_l:10");
params.add("defType", "edismax");
params.add("expand", "true");
params.add("expand.fq", "test_f:2000");
params.add("expand.field", group);
params.add("expand.rows", "0");
params.add("fl", "id,score");
setDistributedParams(params);
rsp = queryServer(params);
results = rsp.getExpandedResults();
assertExpandGroups(results, "group1", "group4");
assertExpandGroupCountAndOrder("group1", 0, results);
assertExpandGroupCountAndOrder("group4", 0, results);
//Test key-only fl
params = new ModifiableSolrParams();
params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("fl", "id");
setDistributedParams(params);
rsp = queryServer(params);
results = rsp.getExpandedResults();
assertExpandGroups(results, "group1","group2", "group3", "group4");
assertExpandGroupCountAndOrder("group1", 2, results, "1", "7");
assertExpandGroupCountAndOrder("group2", 2, results, "5", "8");
assertExpandGroupCountAndOrder("group3", 2, results, "11", "9");
assertExpandGroupCountAndOrder("group4", 2, results, "12", "14");
//Test distrib.singlePass true
params = new ModifiableSolrParams();
params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+"}");
params.add("defType", "edismax");
params.add("bf", "field(test_i)");
params.add("expand", "true");
params.add("distrib.singlePass", "true");
setDistributedParams(params);
rsp = queryServer(params);
results = rsp.getExpandedResults();
assertExpandGroups(results, "group1","group2", "group3", "group4");
assertExpandGroupCountAndOrder("group1", 2, results, "1", "7");
assertExpandGroupCountAndOrder("group2", 2, results, "5", "8");
assertExpandGroupCountAndOrder("group3", 2, results, "11", "9");
assertExpandGroupCountAndOrder("group4", 2, results, "12", "14");
} }
private void assertExpandGroups(Map<String, SolrDocumentList> expandedResults, String... groups) throws Exception { private void assertExpandGroups(Map<String, SolrDocumentList> expandedResults, String... groups) throws Exception {
@ -264,12 +323,17 @@ public class DistributedExpandComponentTest extends BaseDistributedSearchTestCas
return buf.toString(); return buf.toString();
} }
private void assertExpandGroupCountAndOrder(String group, int count, Map<String, SolrDocumentList>expandedResults, String... docs) throws Exception { private void assertExpandGroupCountAndOrder(final String group, final int count,
final Map<String, SolrDocumentList>expandedResults,
final String... docs) throws Exception {
SolrDocumentList results = expandedResults.get(group); SolrDocumentList results = expandedResults.get(group);
if(results == null) { if(results == null) {
throw new Exception("Group Not Found:"+group); throw new Exception("Group Not Found:"+group);
} }
assertCountAndOrder(count, results, docs);
}
private void assertCountAndOrder(final int count, final SolrDocumentList results,
final String... docs) throws Exception {
if(results.size() != count) { if(results.size() != count) {
throw new Exception("Expected Count "+results.size()+" Not Found:"+count); throw new Exception("Expected Count "+results.size()+" Not Found:"+count);
} }

View File

@ -16,10 +16,8 @@
*/ */
package org.apache.solr.handler.component; package org.apache.solr.handler.component;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
@ -46,50 +44,50 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
assertU(commit()); assertU(commit());
} }
@Test private static String maybeTopFc() {
public void testExpand() throws Exception { return (random().nextBoolean() ? " hint="+ CollapsingQParserPlugin.HINT_TOP_FC : "");
List<String> groups = new ArrayList<>();
groups.add("group_s");
groups.add("group_s_dv");
Collections.shuffle(groups, random());
String floatAppend = "";
String hint = (random().nextBoolean() ? " hint="+ CollapsingQParserPlugin.HINT_TOP_FC : "");
_testExpand(groups.get(0), floatAppend, hint);
} }
private static String floatAppend() {
@Test String floatAppend = "."+random().nextInt(100); //Append the float
public void testNumericExpand() throws Exception { floatAppend = Float.toString(Float.parseFloat(floatAppend)); //Create a proper float out of the string.
List<String> groups = new ArrayList<>(); floatAppend = floatAppend.substring(1); //Drop off the leading 0, leaving just the decimal
groups.add("group_i"); return floatAppend;
groups.add("group_ti_dv");
groups.add("group_f");
groups.add("group_tf_dv");
Collections.shuffle(groups, random());
String floatAppend = "";
if(groups.get(0).indexOf("f") > -1) {
floatAppend = "."+random().nextInt(100); //Append the float
floatAppend = Float.toString(Float.parseFloat(floatAppend)); //Create a proper float out of the string.
floatAppend = floatAppend.substring(1); //Drop off the leading 0, leaving just the decimal
}
String hint = "";
_testExpand(groups.get(0), floatAppend, hint);
} }
public void testString() throws Exception {
_testExpand("group_s", "", maybeTopFc());
}
public void testStringDv() throws Exception {
_testExpand("group_s_dv", "", maybeTopFc());
}
public void testInt() throws Exception {
_testExpand("group_i", "", "");
}
public void testIntDv() throws Exception {
_testExpand("group_ti_dv", "", "");
}
public void testFloat() throws Exception {
_testExpand("group_f", floatAppend(), "");
_testExpand("group_f", ".0", ""); // explicit 0 check for 0 vs null group
}
public void testFloatDv() throws Exception {
_testExpand("group_tf_dv", floatAppend(), "");
_testExpand("group_tf_dv", ".0", ""); // explicit 0 check for 0 vs null group
}
private void _testExpand(String group, String floatAppend, String hint) throws Exception { private void _testExpand(String group, String floatAppend, String hint) throws Exception {
// NOTE: one of our groups uses '0' as the group value to explicitly check numeric expand for 0 vs null group behavior
String[][] docs = { String[][] docs = {
{"id","1", "term_s", "YYYY", group, "1"+floatAppend, "test_i", "5", "test_l", "10", "test_f", "2000", "type_s", "parent"}, {"id","1", "term_s", "YYYY", group, "1"+floatAppend, "test_i", "5", "test_l", "10", "test_f", "2000", "type_s", "parent"},
{"id","2", "term_s","YYYY", group, "1"+floatAppend, "test_i", "50", "test_l", "100", "test_f", "200", "type_s", "child"}, {"id","2", "term_s","YYYY", group, "1"+floatAppend, "test_i", "50", "test_l", "100", "test_f", "200", "type_s", "child"},
{"id","3", "term_s", "YYYY", "test_i", "5000", "test_l", "100", "test_f", "200"}, {"id","3", "term_s", "YYYY", "test_i", "5000", "test_l", "100", "test_f", "200"},
{"id","4", "term_s", "YYYY", "test_i", "500", "test_l", "1000", "test_f", "2000"}, {"id","4", "term_s", "YYYY", "test_i", "500", "test_l", "1000", "test_f", "2000"},
{"id","5", "term_s", "YYYY", group, "2"+floatAppend, "test_i", "4", "test_l", "10", "test_f", "2000", "type_s", "parent"}, {"id","5", "term_s", "YYYY", group, "0"+floatAppend, "test_i", "4", "test_l", "10", "test_f", "2000", "type_s", "parent"},
{"id","6", "term_s","YYYY", group, "2"+floatAppend, "test_i", "10", "test_l", "100", "test_f", "200", "type_s", "child"}, {"id","6", "term_s","YYYY", group, "0"+floatAppend, "test_i", "10", "test_l", "100", "test_f", "200", "type_s", "child"},
{"id","7", "term_s", "YYYY", group, "1"+floatAppend, "test_i", "1", "test_l", "100000", "test_f", "2000", "type_s", "child"}, {"id","7", "term_s", "YYYY", group, "1"+floatAppend, "test_i", "1", "test_l", "100000", "test_f", "2000", "type_s", "child"},
{"id","8", "term_s","YYYY", group, "2"+floatAppend, "test_i", "2", "test_l", "100000", "test_f", "200", "type_s", "child"} {"id","8", "term_s","YYYY", group, "0"+floatAppend, "test_i", "2", "test_l", "100000", "test_f", "200", "type_s", "child"}
}; };
createIndex(docs); createIndex(docs);
@ -107,8 +105,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='6']", "/response/result/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='8']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='8']"
); );
//Basic test case page 2 //Basic test case page 2
@ -116,8 +114,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
assertQ(req(params, "rows", "1", "start", "1"), "*[count(/response/result/doc)=1]", assertQ(req(params, "rows", "1", "start", "1"), "*[count(/response/result/doc)=1]",
"*[count(/response/lst[@name='expanded']/result)=1]", "*[count(/response/lst[@name='expanded']/result)=1]",
"/response/result/doc[1]/str[@name='id'][.='6']", "/response/result/doc[1]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='8']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='8']"
); );
//Test expand.sort //Test expand.sort
@ -129,12 +127,12 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='6']", "/response/result/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='5']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='5']"
); );
//Test with nullPolicy, ExpandComponent should ignore docs with null values in the collapse fields. //Test with nullPolicy, ExpandComponent should ignore docs with null values in the collapse fields.
//Main result set should include the doc with null value in the collapse field. //Main result set should include the doc(s) with null value in the collapse field.
params = new ModifiableSolrParams(); params = new ModifiableSolrParams();
params.add("q", "*:*"); params.add("q", "*:*");
params.add("fq", "{!collapse field="+group+hint+" nullPolicy=collapse}"); params.add("fq", "{!collapse field="+group+hint+" nullPolicy=collapse}");
@ -149,8 +147,20 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[3]/str[@name='id'][.='6']", "/response/result/doc[3]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='5']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='5']"
);
params.set("fq", "{!collapse field="+group+hint+" nullPolicy=expand}");
assertQ(req(params), "*[count(/response/result/doc)=4]",
"*[count(/response/lst[@name='expanded']/result)=2]",
"/response/result/doc[1]/str[@name='id'][.='3']",
"/response/result/doc[2]/str[@name='id'][.='4']",
"/response/result/doc[3]/str[@name='id'][.='2']",
"/response/result/doc[4]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='5']"
); );
@ -169,8 +179,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='5']", "/response/result/doc[2]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='6']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='6']"
); );
@ -190,8 +200,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='5']", "/response/result/doc[2]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='6']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='6']"
); );
//Test override expand.fq and expand.q //Test override expand.fq and expand.q
@ -211,8 +221,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='5']", "/response/result/doc[2]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='6']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='6']"
); );
//Test expand.rows //Test expand.rows
@ -227,11 +237,11 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
assertQ(req(params), "*[count(/response/result/doc)=2]", assertQ(req(params), "*[count(/response/result/doc)=2]",
"*[count(/response/lst[@name='expanded']/result)=2]", "*[count(/response/lst[@name='expanded']/result)=2]",
"*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=1]", "*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=1]",
"*[count(/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc)=1]", "*[count(/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc)=1]",
"/response/result/doc[1]/str[@name='id'][.='2']", "/response/result/doc[1]/str[@name='id'][.='2']",
"/response/result/doc[2]/str[@name='id'][.='6']", "/response/result/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']"
); );
//Test expand.rows = 0 - no docs only expand count //Test expand.rows = 0 - no docs only expand count
@ -245,7 +255,7 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
assertQ(req(params), "*[count(/response/result/doc)=2]", assertQ(req(params), "*[count(/response/result/doc)=2]",
"*[count(/response/lst[@name='expanded']/result)=2]", "*[count(/response/lst[@name='expanded']/result)=2]",
"*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=0]", "*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=0]",
"*[count(/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc)=0]", "*[count(/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc)=0]",
"/response/result/doc[1]/str[@name='id'][.='2']", "/response/result/doc[1]/str[@name='id'][.='2']",
"/response/result/doc[2]/str[@name='id'][.='6']" "/response/result/doc[2]/str[@name='id'][.='6']"
); );
@ -263,7 +273,7 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
assertQ(req(params, "fl", "id"), "*[count(/response/result/doc)=2]", assertQ(req(params, "fl", "id"), "*[count(/response/result/doc)=2]",
"*[count(/response/lst[@name='expanded']/result)=2]", "*[count(/response/lst[@name='expanded']/result)=2]",
"*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=0]", "*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=0]",
"*[count(/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc)=0]", "*[count(/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc)=0]",
"/response/result/doc[1]/str[@name='id'][.='1']", "/response/result/doc[1]/str[@name='id'][.='1']",
"/response/result/doc[2]/str[@name='id'][.='5']" "/response/result/doc[2]/str[@name='id'][.='5']"
); );
@ -281,7 +291,7 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
assertQ(req(params, "fl", "id,score"), "*[count(/response/result/doc)=2]", assertQ(req(params, "fl", "id,score"), "*[count(/response/result/doc)=2]",
"*[count(/response/lst[@name='expanded']/result)=2]", "*[count(/response/lst[@name='expanded']/result)=2]",
"*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=0]", "*[count(/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc)=0]",
"*[count(/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc)=0]", "*[count(/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc)=0]",
"*[count(/response/lst[@name='expanded']/result[@maxScore])=0]", //maxScore should not be available "*[count(/response/lst[@name='expanded']/result[@maxScore])=0]", //maxScore should not be available
"/response/result/doc[1]/str[@name='id'][.='1']", "/response/result/doc[1]/str[@name='id'][.='1']",
"/response/result/doc[2]/str[@name='id'][.='5']", "/response/result/doc[2]/str[@name='id'][.='5']",
@ -330,8 +340,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='6']", "/response/result/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='8']",
"count(//*[@name='score'])=0" // score shouldn't be returned when not requested "count(//*[@name='score'])=0" // score shouldn't be returned when not requested
); );
@ -342,8 +352,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='6']", "/response/result/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='8']",
"count(//*[@name='score' and .='NaN'])=0" "count(//*[@name='score' and .='NaN'])=0"
); );
@ -356,8 +366,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[2]/str[@name='id'][.='6']", "/response/result/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='8']",
"count(//*[@name='score' and .='NaN'])=0" "count(//*[@name='score' and .='NaN'])=0"
); );
@ -370,8 +380,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
// note that the expanded docs are score descending order (score is 1 test_i) // note that the expanded docs are score descending order (score is 1 test_i)
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='5']",
"count(//*[@name='score' and .='NaN'])=0", "count(//*[@name='score' and .='NaN'])=0",
"count(/response/lst[@name='expanded']/result/doc[number(*/@name='score')!=number(*/@name='test_i')])=0" "count(/response/lst[@name='expanded']/result/doc[number(*/@name='score')!=number(*/@name='test_i')])=0"
); );
@ -385,8 +395,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
// note that the expanded docs are score descending order (score is 1 test_i) // note that the expanded docs are score descending order (score is 1 test_i)
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='8']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='8']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='5']",
"count(//*[@name='score' and .='NaN'])=0", "count(//*[@name='score' and .='NaN'])=0",
"count(/response/lst[@name='expanded']/result/doc[number(*/@name='score')!=number(*/@name='test_i')])=0" "count(/response/lst[@name='expanded']/result/doc[number(*/@name='score')!=number(*/@name='test_i')])=0"
); );
@ -408,7 +418,7 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
); );
// Support expand enabled without previous collapse // Support expand enabled without previous collapse
assertQ(req("q", "type_s:child", "sort", group+" asc, test_l desc", "defType", "edismax", assertQ(req("q", "type_s:child", "sort", group+" desc, test_l desc", "defType", "edismax",
"expand", "true", "expand.q", "type_s:parent", "expand.field", group), "expand", "true", "expand.q", "type_s:parent", "expand.field", group),
"*[count(/response/result/doc)=4]", "*[count(/response/result/doc)=4]",
"*[count(/response/lst[@name='expanded']/result)=2]", "*[count(/response/lst[@name='expanded']/result)=2]",
@ -417,7 +427,7 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"/response/result/doc[3]/str[@name='id'][.='8']", "/response/result/doc[3]/str[@name='id'][.='8']",
"/response/result/doc[4]/str[@name='id'][.='6']", "/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='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']" "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']"
); );
// With multiple collapse // With multiple collapse
@ -456,8 +466,8 @@ public class TestExpandComponent extends SolrTestCaseJ4 {
"*[count(/response/result/doc)=2]", "*[count(/response/result/doc)=2]",
"/response/result/doc[1]/str[@name='id'][.='8']", "/response/result/doc[1]/str[@name='id'][.='8']",
"/response/result/doc[2]/str[@name='id'][.='7']", "/response/result/doc[2]/str[@name='id'][.='7']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[1]/str[@name='id'][.='5']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[1]/str[@name='id'][.='5']",
"/response/lst[@name='expanded']/result[@name='2"+floatAppend+"']/doc[2]/str[@name='id'][.='6']", "/response/lst[@name='expanded']/result[@name='0"+floatAppend+"']/doc[2]/str[@name='id'][.='6']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']", "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[1]/str[@name='id'][.='1']",
"/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']" "/response/lst[@name='expanded']/result[@name='1"+floatAppend+"']/doc[2]/str[@name='id'][.='2']"
); );

View File

@ -818,7 +818,6 @@ public class TestBlockCollapse extends SolrTestCaseJ4 {
* (and the other tests should adequeately prove that the block hueristics for _root_ collapsing work) * (and the other tests should adequeately prove that the block hueristics for _root_ collapsing work)
*/ */
public void testBlockCollapseWithExpandComponent() throws Exception { public void testBlockCollapseWithExpandComponent() throws Exception {
// NOTE: due to SOLR-15078 we don't bother trying to collapse/expand on int in this test
{ // convert our docs + some docs w/o collapse fields, along with some commits, to update commands { // convert our docs + some docs w/o collapse fields, along with some commits, to update commands
// in a shuffled order and process all of them... // in a shuffled order and process all of them...
@ -839,10 +838,10 @@ public class TestBlockCollapse extends SolrTestCaseJ4 {
// we don't bother testing _root_ field collapsing, since it contains different field values then block_s1 // we don't bother testing _root_ field collapsing, since it contains different field values then block_s1
for (String opt : Arrays.asList(// no block collapse logic used (sanity checks) for (String opt : Arrays.asList(// no block collapse logic used (sanity checks)
"field=block_s1", "field=block_s1",
// "field=block_i", // TODO: SOLR-15078 "field=block_i",
// block collapse used explicitly (int) // block collapse used explicitly (int)
// "field=block_i hint=block", // TODO: SOLR-15078 "field=block_i hint=block",
// block collapse used explicitly (ord) // block collapse used explicitly (ord)
"field=block_s1 hint=block" "field=block_s1 hint=block"