blob: 8697b264d618500aa25020785ec0a011d334cf1c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.schema;
import java.io.IOException;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.core.SolrCore;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.util.RefCounted;
import org.junit.BeforeClass;
import org.junit.Test;
public class DocValuesMultiTest extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeTests() throws Exception {
initCore("solrconfig-basic.xml", "schema-docValuesMulti.xml");
// sanity check our schema meets our expectations
final IndexSchema schema = h.getCore().getLatestSchema();
for (String f : new String[] {"floatdv", "intdv", "doubledv", "longdv", "datedv", "stringdv", "booldv"}) {
final SchemaField sf = schema.getField(f);
assertTrue(f + " is not multiValued, test is useless, who changed the schema?",
sf.multiValued());
assertFalse(f + " is indexed, test is useless, who changed the schema?",
sf.indexed());
assertTrue(f + " has no docValues, test is useless, who changed the schema?",
sf.hasDocValues());
}
}
public void setUp() throws Exception {
super.setUp();
assertU(delQ("*:*"));
}
@Test
public void testDocValues() throws IOException {
final DocValuesType expectedNumericDvType = Boolean.getBoolean(NUMERIC_POINTS_SYSPROP) ?
DocValuesType.SORTED_NUMERIC : DocValuesType.SORTED_SET;
assertU(adoc("id", "1", "floatdv", "4.5", "intdv", "-1", "intdv", "3",
"stringdv", "value1", "stringdv", "value2",
"booldv", "false", "booldv", "true"));
assertU(commit());
try (SolrCore core = h.getCoreInc()) {
final RefCounted<SolrIndexSearcher> searcherRef = core.openNewSearcher(true, true);
final SolrIndexSearcher searcher = searcherRef.get();
try {
final LeafReader reader = searcher.getSlowAtomicReader();
assertEquals(1, reader.numDocs());
final FieldInfos infos = reader.getFieldInfos();
assertEquals(DocValuesType.SORTED_SET, infos.fieldInfo("stringdv").getDocValuesType());
assertEquals(DocValuesType.SORTED_SET, infos.fieldInfo("booldv").getDocValuesType());
assertEquals(expectedNumericDvType, infos.fieldInfo("floatdv").getDocValuesType());
assertEquals(expectedNumericDvType, infos.fieldInfo("intdv").getDocValuesType());
SortedSetDocValues dv = reader.getSortedSetDocValues("stringdv");
assertEquals(0, dv.nextDoc());
assertEquals(0, dv.nextOrd());
assertEquals(1, dv.nextOrd());
assertEquals(SortedSetDocValues.NO_MORE_ORDS, dv.nextOrd());
dv = reader.getSortedSetDocValues("booldv");
assertEquals(0, dv.nextDoc());
assertEquals(0, dv.nextOrd());
assertEquals(1, dv.nextOrd());
assertEquals(SortedSetDocValues.NO_MORE_ORDS, dv.nextOrd());
} finally {
searcherRef.decref();
}
}
}
/** Tests the ability to do basic queries (without scoring, just match-only) on
* string docvalues fields that are not inverted (indexed "forward" only)
*/
@Test
public void testStringDocValuesMatch() throws Exception {
assertU(adoc("id", "1", "stringdv", "b"));
assertU(adoc("id", "2", "stringdv", "a"));
assertU(adoc("id", "3", "stringdv", "c"));
assertU(adoc("id", "4", "stringdv", "car"));
assertU(adoc("id", "5", "stringdv", "dog", "stringdv", "cat"));
assertU(commit());
// string: termquery
assertQ(req("q", "stringdv:car", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=4]"
);
// string: range query
assertQ(req("q", "stringdv:[b TO d]", "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/str[@name='id'][.=1]",
"//result/doc[2]/str[@name='id'][.=3]",
"//result/doc[3]/str[@name='id'][.=4]",
"//result/doc[4]/str[@name='id'][.=5]"
);
// string: prefix query
assertQ(req("q", "stringdv:c*", "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/str[@name='id'][.=3]",
"//result/doc[2]/str[@name='id'][.=4]",
"//result/doc[3]/str[@name='id'][.=5]"
);
// string: wildcard query
assertQ(req("q", "stringdv:c?r", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=4]"
);
// string: regexp query
assertQ(req("q", "stringdv:/c[a-b]r/", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=4]"
);
}
/** Tests the ability to do basic queries (without scoring, just match-only) on
* boolean docvalues fields that are not inverted (indexed "forward" only)
*/
@Test
public void testBoolDocValuesMatch() throws Exception {
assertU(adoc("id", "1", "booldv", "true"));
assertU(adoc("id", "2", "booldv", "false"));
assertU(adoc("id", "3", "booldv", "true"));
assertU(adoc("id", "4", "booldv", "false"));
assertU(adoc("id", "5", "booldv", "true", "booldv", "false"));
assertU(commit());
// string: termquery
assertQ(req("q", "booldv:true", "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/str[@name='id'][.=1]",
"//result/doc[2]/str[@name='id'][.=3]",
"//result/doc[3]/str[@name='id'][.=5]"
);
// boolean: range query,
assertQ(req("q", "booldv:[false TO false]", "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/str[@name='id'][.=2]",
"//result/doc[2]/str[@name='id'][.=4]",
"//result/doc[3]/str[@name='id'][.=5]");
assertQ(req("q", "*:*", "sort", "id asc", "rows", "10", "fl", "booldv"),
"//result/doc[1]/arr[@name='booldv']/bool[1][.='true']",
"//result/doc[2]/arr[@name='booldv']/bool[1][.='false']",
"//result/doc[3]/arr[@name='booldv']/bool[1][.='true']",
"//result/doc[4]/arr[@name='booldv']/bool[1][.='false']",
"//result/doc[5]/arr[@name='booldv']/bool[1][.='false']",
"//result/doc[5]/arr[@name='booldv']/bool[2][.='true']"
);
}
/** Tests the ability to do basic queries (without scoring, just match-only) on
* float docvalues fields that are not inverted (indexed "forward" only)
*/
@Test
public void testFloatDocValuesMatch() throws Exception {
assertU(adoc("id", "1", "floatdv", "2"));
assertU(adoc("id", "2", "floatdv", "-5"));
assertU(adoc("id", "3", "floatdv", "3.0", "floatdv", "-1.3", "floatdv", "2.2"));
assertU(adoc("id", "4", "floatdv", "3"));
assertU(adoc("id", "5", "floatdv", "-0.5"));
assertU(commit());
// float: termquery
assertQ(req("q", "floatdv:3", "sort", "id asc"),
"//*[@numFound='2']",
"//result/doc[1]/str[@name='id'][.=3]",
"//result/doc[2]/str[@name='id'][.=4]"
);
// float: rangequery
assertQ(req("q", "floatdv:[-1 TO 2.5]", "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/str[@name='id'][.=1]",
"//result/doc[2]/str[@name='id'][.=3]",
"//result/doc[3]/str[@name='id'][.=5]"
);
// (neg) float: rangequery
assertQ(req("q", "floatdv:[-6 TO -4]", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=2]"
);
// (neg) float: termquery
assertQ(req("q", "floatdv:\"-5\"", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=2]"
);
}
/** Tests the ability to do basic queries (without scoring, just match-only) on
* double docvalues fields that are not inverted (indexed "forward" only)
*/
@Test
public void testDoubleDocValuesMatch() throws Exception {
assertU(adoc("id", "1", "doubledv", "2"));
assertU(adoc("id", "2", "doubledv", "-5"));
assertU(adoc("id", "3", "doubledv", "3.0", "doubledv", "-1.3", "doubledv", "2.2"));
assertU(adoc("id", "4", "doubledv", "3"));
assertU(adoc("id", "5", "doubledv", "-0.5"));
assertU(commit());
// double: termquery
assertQ(req("q", "doubledv:3", "sort", "id asc"),
"//*[@numFound='2']",
"//result/doc[1]/str[@name='id'][.=3]",
"//result/doc[2]/str[@name='id'][.=4]"
);
// double: rangequery
assertQ(req("q", "doubledv:[-1 TO 2.5]", "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/str[@name='id'][.=1]",
"//result/doc[2]/str[@name='id'][.=3]",
"//result/doc[3]/str[@name='id'][.=5]"
);
// (neg) double: rangequery
assertQ(req("q", "doubledv:[-6 TO -4]", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=2]"
);
// (neg) double: termquery
assertQ(req("q", "doubledv:\"-5\"", "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/str[@name='id'][.=2]"
);
}
@Test
public void testDocValuesFacetingSimple() {
// this is the random test verbatim from DocValuesTest, so it populates with the default values defined in its schema.
for (int i = 0; i < 50; ++i) {
assertU(adoc("id", "" + i, "floatdv", "1", "intdv", "2", "doubledv", "3", "longdv", "4",
"datedv", "1995-12-31T23:59:59.999Z",
"stringdv", "abc", "booldv", "true"));
}
for (int i = 0; i < 50; ++i) {
if (rarely()) {
assertU(commit()); // to have several segments
}
switch (i % 3) {
case 0:
assertU(adoc("id", "1000" + i, "floatdv", "" + i, "intdv", "" + i, "doubledv", "" + i, "longdv", "" + i,
"datedv", (1900+i) + "-12-31T23:59:59.999Z", "stringdv", "abc" + i, "booldv", "true", "booldv", "true"));
break;
case 1:
assertU(adoc("id", "1000" + i, "floatdv", "" + i, "intdv", "" + i, "doubledv", "" + i, "longdv", "" + i,
"datedv", (1900+i) + "-12-31T23:59:59.999Z", "stringdv", "abc" + i, "booldv", "false", "booldv", "false"));
break;
case 2:
assertU(adoc("id", "1000" + i, "floatdv", "" + i, "intdv", "" + i, "doubledv", "" + i, "longdv", "" + i,
"datedv", (1900+i) + "-12-31T23:59:59.999Z", "stringdv", "abc" + i, "booldv", "true", "booldv", "false"));
break;
}
}
assertU(commit());
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "longdv", "facet.sort", "count", "facet.limit", "1"),
"//lst[@name='longdv']/int[@name='4'][.='51']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "longdv", "facet.sort", "count", "facet.offset", "1", "facet.limit", "1"),
"//lst[@name='longdv']/int[@name='0'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "longdv", "facet.sort", "index", "facet.offset", "33", "facet.limit", "1", "facet.mincount", "1"),
"//lst[@name='longdv']/int[@name='33'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "floatdv", "facet.sort", "count", "facet.limit", "1"),
"//lst[@name='floatdv']/int[@name='1.0'][.='51']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "floatdv", "facet.sort", "count", "facet.offset", "1", "facet.limit", "-1", "facet.mincount", "1"),
"//lst[@name='floatdv']/int[@name='0.0'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "floatdv", "facet.sort", "index", "facet.offset", "33", "facet.limit", "1", "facet.mincount", "1"),
"//lst[@name='floatdv']/int[@name='33.0'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "doubledv", "facet.sort", "count", "facet.limit", "1"),
"//lst[@name='doubledv']/int[@name='3.0'][.='51']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "doubledv", "facet.sort", "count", "facet.offset", "1", "facet.limit", "-1", "facet.mincount", "1"),
"//lst[@name='doubledv']/int[@name='0.0'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "doubledv", "facet.sort", "index", "facet.offset", "33", "facet.limit", "1", "facet.mincount", "1"),
"//lst[@name='doubledv']/int[@name='33.0'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "intdv", "facet.sort", "count", "facet.limit", "1"),
"//lst[@name='intdv']/int[@name='2'][.='51']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "intdv", "facet.sort", "count", "facet.offset", "1", "facet.limit", "-1", "facet.mincount", "1"),
"//lst[@name='intdv']/int[@name='0'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "intdv", "facet.sort", "index", "facet.offset", "33", "facet.limit", "1", "facet.mincount", "1"),
"//lst[@name='intdv']/int[@name='33'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "datedv", "facet.sort", "count", "facet.limit", "1"),
"//lst[@name='datedv']/int[@name='1995-12-31T23:59:59.999Z'][.='50']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "datedv", "facet.sort", "count", "facet.offset", "1", "facet.limit", "-1", "facet.mincount", "1"),
"//lst[@name='datedv']/int[@name='1900-12-31T23:59:59.999Z'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "datedv", "facet.sort", "index", "facet.offset", "33", "facet.limit", "1", "facet.mincount", "1"),
"//lst[@name='datedv']/int[@name='1933-12-31T23:59:59.999Z'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "stringdv", "facet.sort", "count", "facet.limit", "1"),
"//lst[@name='stringdv']/int[@name='abc'][.='50']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "stringdv", "facet.sort", "count", "facet.offset", "1", "facet.limit", "-1", "facet.mincount", "1"),
"//lst[@name='stringdv']/int[@name='abc1'][.='1']",
"//lst[@name='stringdv']/int[@name='abc13'][.='1']",
"//lst[@name='stringdv']/int[@name='abc19'][.='1']",
"//lst[@name='stringdv']/int[@name='abc49'][.='1']"
);
// Even though offseting by 33, the sort order is abc1 abc11....abc2 so it throws the position in the return list off.
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "stringdv", "facet.sort", "index", "facet.offset", "33", "facet.limit", "1", "facet.mincount", "1"),
"//lst[@name='stringdv']/int[@name='abc38'][.='1']");
assertQ(req("q", "*:*", "facet", "true", "rows", "0", "facet.field", "booldv", "facet.sort", "count"),
"//lst[@name='booldv']/int[@name='true'][.='83']",
"//lst[@name='booldv']/int[@name='false'][.='33']");
}
}