/*
* 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 java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.FloatPoint;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.SortedNumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.PointValues;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexOrDocValuesQuery;
import org.apache.lucene.search.PointRangeQuery;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.index.SlowCompositeReaderWrapper;
import org.apache.solr.schema.IndexSchema.DynamicField;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SolrQueryParser;
import org.apache.solr.util.DateMathParser;
import org.apache.solr.util.RefCounted;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
/**
* Tests for PointField functionality
*
*
*/
public class TestPointFields extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml","schema-point.xml");
}
@Override
@After
public void tearDown() throws Exception {
clearIndex();
assertU(commit());
super.tearDown();
}
@Test
public void testIntPointFieldExactQuery() throws Exception {
doTestIntPointFieldExactQuery("number_p_i", false);
doTestIntPointFieldExactQuery("number_p_i_mv", false);
doTestIntPointFieldExactQuery("number_p_i_dv", false);
doTestIntPointFieldExactQuery("number_p_i_mv_dv", false);
doTestIntPointFieldExactQuery("number_p_i_ni_dv", false);
doTestIntPointFieldExactQuery("number_p_i_ni_ns_dv", false);
doTestIntPointFieldExactQuery("number_p_i_ni_mv_dv", false);
}
@Test
public void testIntPointFieldNonSearchableExactQuery() throws Exception {
doTestIntPointFieldExactQuery("number_p_i_ni", false, false);
doTestIntPointFieldExactQuery("number_p_i_ni_ns", false, false);
}
@Test
public void testIntPointFieldReturn() throws Exception {
testPointFieldReturn("number_p_i", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
testPointFieldReturn("number_p_i_dv_ns", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
testPointFieldReturn("number_p_i_ni", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
}
@Test
public void testIntPointFieldRangeQuery() throws Exception {
doTestIntPointFieldRangeQuery("number_p_i", "int", false);
doTestIntPointFieldRangeQuery("number_p_i_ni_ns_dv", "int", false);
doTestIntPointFieldRangeQuery("number_p_i_dv", "int", false);
}
@Test
public void testIntPointFieldNonSearchableRangeQuery() throws Exception {
doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", "42");
doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", "42");
doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", "42", "666");
}
@Test
public void testIntPointFieldSortAndFunction() throws Exception {
final SortedSet<String> regexToTest = dynFieldRegexesForType(IntPointField.class);
final String[] sequential = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
for (String r : Arrays.asList("*_p_i", "*_p_i_dv", "*_p_i_dv_ns", "*_p_i_ni_dv",
"*_p_i_ni_dv_ns", "*_p_i_ni_ns_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSort(r.replace("*","number"), sequential);
// TODO: test some randomly generated (then sorted) arrays (with dups and/or missing values)
doTestIntPointFunctionQuery(r.replace("*","number"), "int");
}
for (String r : Arrays.asList("*_p_i_ni", "*_p_i_ni_ns")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "w/o docValues", "42");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "w/o docValues", "42");
}
for (String r : Arrays.asList("*_p_i_mv", "*_p_i_ni_mv", "*_p_i_ni_mv_dv", "*_p_i_ni_dv_ns_mv",
"*_p_i_ni_ns_mv", "*_p_i_dv_ns_mv", "*_p_i_mv_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "42");
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "42", "666");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "42");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "42", "666");
}
assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
}
@Test
public void testIntPointFieldFacetField() throws Exception {
testPointFieldFacetField("number_p_i", "number_p_i_dv", getSequentialStringArrayWithInts(10));
}
@Test
public void testIntPointFieldRangeFacet() throws Exception {
doTestIntPointFieldRangeFacet("number_p_i_dv", "number_p_i");
}
@Test
public void testIntPointStats() throws Exception {
testPointStats("number_p_i", "number_p_i_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
0D, 9D, "10", "1", 0D);
testPointStats("number_p_i", "number_p_i_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
0D, 9D, "10", "1", 0D);
}
@Test
public void testIntPointFieldMultiValuedExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_i_mv", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", getSequentialStringArrayWithInts(20));
}
@Test
public void testIntPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", getSequentialStringArrayWithInts(20), false);
testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
}
@Test
public void testIntPointFieldMultiValuedReturn() throws Exception {
testPointFieldMultiValuedReturn("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", getSequentialStringArrayWithInts(20));
}
@Test
public void testIntPointFieldMultiValuedRangeQuery() throws Exception {
testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
}
@Test
public void testIntPointFieldNotIndexed() throws Exception {
doTestFieldNotIndexed("number_p_i_ni", getSequentialStringArrayWithInts(10));
doTestFieldNotIndexed("number_p_i_ni_mv", getSequentialStringArrayWithInts(10));
}
//TODO MV SORT?
@Test
public void testIntPointFieldMultiValuedFacetField() throws Exception {
testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", getRandomStringArrayWithInts(20, false));
}
@Test
public void testIntPointFieldMultiValuedRangeFacet() throws Exception {
doTestIntPointFieldMultiValuedRangeFacet("number_p_i_mv_dv", "number_p_i_mv");
}
@Test
public void testIntPointMultiValuedFunctionQuery() throws Exception {
testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
}
@Test
public void testIntPointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testIntPointFieldsAtomicUpdates("number_p_i", "int");
testIntPointFieldsAtomicUpdates("number_p_i_dv", "int");
testIntPointFieldsAtomicUpdates("number_p_i_dv_ns", "int");
}
@Test
public void testMultiValuedIntPointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testMultiValuedIntPointFieldsAtomicUpdates("number_p_i_mv", "int");
testMultiValuedIntPointFieldsAtomicUpdates("number_p_i_ni_mv_dv", "int");
testMultiValuedIntPointFieldsAtomicUpdates("number_p_i_dv_ns_mv", "int");
}
@Test
public void testIntPointSetQuery() throws Exception {
doTestSetQueries("number_p_i", getRandomStringArrayWithInts(20, false), false);
doTestSetQueries("number_p_i_mv", getRandomStringArrayWithInts(20, false), true);
doTestSetQueries("number_p_i_ni_dv", getRandomStringArrayWithInts(20, false), false);
}
// DoublePointField
@Test
public void testDoublePointFieldExactQuery() throws Exception {
doTestFloatPointFieldExactQuery("number_d");
doTestFloatPointFieldExactQuery("number_p_d");
doTestFloatPointFieldExactQuery("number_p_d_mv");
doTestFloatPointFieldExactQuery("number_p_d_dv");
doTestFloatPointFieldExactQuery("number_p_d_mv_dv");
doTestFloatPointFieldExactQuery("number_p_d_ni_dv");
doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv");
doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns");
doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv");
}
@Test
public void testDoublePointFieldNonSearchableExactQuery() throws Exception {
doTestFloatPointFieldExactQuery("number_p_d_ni", false);
doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false);
}
@Test
public void testDoublePointFieldReturn() throws Exception {
testPointFieldReturn("number_p_d", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
testPointFieldReturn("number_p_d_dv_ns", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
String[] arr = new String[atLeast(10)];
for (int i = 0; i < arr.length; i++) {
double rand = random().nextDouble() * 10;
arr[i] = String.valueOf(rand);
}
testPointFieldReturn("number_p_d", "double", arr);
}
@Test
public void testDoublePointFieldRangeQuery() throws Exception {
doTestFloatPointFieldRangeQuery("number_p_d", "double", true);
doTestFloatPointFieldRangeQuery("number_p_d_ni_ns_dv", "double", true);
doTestFloatPointFieldRangeQuery("number_p_d_dv", "double", true);
}
@Test
public void testDoubleFieldNonSearchableRangeQuery() throws Exception {
doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", "42.3");
doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", "42.3");
doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", "42.3", "-66.6");
}
@Test
public void testDoublePointFieldSortAndFunction() throws Exception {
final SortedSet<String> regexToTest = dynFieldRegexesForType(DoublePointField.class);
final String[] sequential = new String[]{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0"};
final String[] randstrs = getRandomStringArrayWithDoubles(10, true);
for (String r : Arrays.asList("*_p_d", "*_p_d_dv", "*_p_d_dv_ns", "*_p_d_ni_dv",
"*_p_d_ni_dv_ns", "*_p_d_ni_ns_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSort(r.replace("*","number"), sequential);
doTestPointFieldSort(r.replace("*","number"), randstrs);
// TODO: test some randomly generated (then sorted) arrays (with dups and/or missing values)
doTestFloatPointFunctionQuery(r.replace("*","number"), "double");
}
for (String r : Arrays.asList("*_p_d_ni", "*_p_d_ni_ns")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "w/o docValues", "42.34");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "w/o docValues", "42.34");
}
for (String r : Arrays.asList("*_p_d_mv", "*_p_d_ni_mv", "*_p_d_ni_mv_dv", "*_p_d_ni_dv_ns_mv",
"*_p_d_ni_ns_mv", "*_p_d_dv_ns_mv", "*_p_d_mv_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "42.34");
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "42.34", "66.6");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "42.34");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "42.34", "66.6");
}
assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
}
@Test
public void testDoublePointFieldFacetField() throws Exception {
testPointFieldFacetField("number_p_d", "number_p_d_dv", getSequentialStringArrayWithDoubles(10));
clearIndex();
assertU(commit());
testPointFieldFacetField("number_p_d", "number_p_d_dv", getRandomStringArrayWithDoubles(10, false));
}
@Test
public void testDoublePointFieldRangeFacet() throws Exception {
doTestFloatPointFieldRangeFacet("number_p_d_dv", "number_p_d");
}
@Test
public void testDoublePointStats() throws Exception {
testPointStats("number_p_d", "number_p_d_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-10.0D, 9.9D, "10", "1", 1E-10D);
testPointStats("number_p_d_mv", "number_p_d_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-10.0D, 9.9D, "10", "1", 1E-10D);
}
@Test
public void testDoublePointFieldMultiValuedExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_d_mv", getRandomStringArrayWithDoubles(20, false));
testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", getRandomStringArrayWithDoubles(20, false));
}
@Test
public void testDoublePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", getRandomStringArrayWithDoubles(20, false), false);
testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", getRandomStringArrayWithDoubles(20, false), false);
}
@Test
public void testDoublePointFieldMultiValuedReturn() throws Exception {
testPointFieldMultiValuedReturn("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", getSequentialStringArrayWithDoubles(20));
}
@Test
public void testDoublePointFieldMultiValuedRangeQuery() throws Exception {
testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
}
@Test
public void testDoublePointFieldMultiValuedFacetField() throws Exception {
testPointFieldMultiValuedFacetField("number_p_d_mv", "number_p_d_mv_dv", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedFacetField("number_p_d_mv", "number_p_d_mv_dv", getRandomStringArrayWithDoubles(20, false));
}
@Test
public void testDoublePointFieldMultiValuedRangeFacet() throws Exception {
doTestDoublePointFieldMultiValuedRangeFacet("number_p_d_mv_dv", "number_p_d_mv");
}
@Test
public void testDoublePointMultiValuedFunctionQuery() throws Exception {
testPointMultiValuedFunctionQuery("number_p_d_mv", "number_p_d_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
testPointMultiValuedFunctionQuery("number_p_d_mv", "number_p_d_mv_dv", "double", getRandomStringArrayWithFloats(20, true));
}
@Test
public void testDoublePointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
doTestFloatPointFieldsAtomicUpdates("number_p_d", "double");
doTestFloatPointFieldsAtomicUpdates("number_p_d_dv", "double");
doTestFloatPointFieldsAtomicUpdates("number_p_d_dv_ns", "double");
}
@Test
public void testMultiValuedDoublePointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testMultiValuedFloatPointFieldsAtomicUpdates("number_p_d_mv", "double");
testMultiValuedFloatPointFieldsAtomicUpdates("number_p_d_ni_mv_dv", "double");
testMultiValuedFloatPointFieldsAtomicUpdates("number_p_d_dv_ns_mv", "double");
}
@Test
public void testDoublePointFieldNotIndexed() throws Exception {
doTestFieldNotIndexed("number_p_d_ni", getSequentialStringArrayWithDoubles(10));
doTestFieldNotIndexed("number_p_d_ni_mv", getSequentialStringArrayWithDoubles(10));
}
private void doTestFloatPointFieldsAtomicUpdates(String field, String type) throws Exception {
assertU(adoc(sdoc("id", "1", field, "1.1234")));
assertU(commit());
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("inc", 1.1F))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='2.2234']");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("inc", -1.1F))));
assertU(commit());
// TODO: can this test be better?
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.>'1.1233']",
"//result/doc[1]/" + type + "[@name='" + field + "'][.<'1.1235']");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", 3.123F))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='3.123']");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", 3.14F))));
assertU(commit());
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("inc", 1F))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.>'4.13']",
"//result/doc[1]/" + type + "[@name='" + field + "'][.<'4.15']");
}
@Test
public void testDoublePointSetQuery() throws Exception {
doTestSetQueries("number_p_d", getRandomStringArrayWithDoubles(20, false), false);
doTestSetQueries("number_p_d_mv", getRandomStringArrayWithDoubles(20, false), true);
doTestSetQueries("number_p_d_ni_dv", getRandomStringArrayWithDoubles(20, false), false);
}
// Float
@Test
public void testFloatPointFieldExactQuery() throws Exception {
doTestFloatPointFieldExactQuery("number_p_f");
doTestFloatPointFieldExactQuery("number_p_f_mv");
doTestFloatPointFieldExactQuery("number_p_f_dv");
doTestFloatPointFieldExactQuery("number_p_f_mv_dv");
doTestFloatPointFieldExactQuery("number_p_f_ni_dv");
doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv");
doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns");
doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv");
}
@Test
public void testFloatPointFieldNonSearchableExactQuery() throws Exception {
doTestFloatPointFieldExactQuery("number_p_f_ni", false);
doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false);
}
@Test
public void testFloatPointFieldReturn() throws Exception {
testPointFieldReturn("number_p_f", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
testPointFieldReturn("number_p_f_dv_ns", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
String[] arr = new String[atLeast(10)];
for (int i = 0; i < arr.length; i++) {
float rand = random().nextFloat() * 10;
arr[i] = String.valueOf(rand);
}
testPointFieldReturn("number_p_f", "float", arr);
}
@Test
public void testFloatPointFieldRangeQuery() throws Exception {
doTestFloatPointFieldRangeQuery("number_p_f", "float", false);
doTestFloatPointFieldRangeQuery("number_p_f_ni_ns_dv", "float", false);
doTestFloatPointFieldRangeQuery("number_p_f_dv", "float", false);
}
@Test
public void testFloatPointFieldNonSearchableRangeQuery() throws Exception {
doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", "42.3");
doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", "42.3");
doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", "42.3", "-66.6");
}
@Test
public void testFloatPointFieldSortAndFunction() throws Exception {
final SortedSet<String> regexToTest = dynFieldRegexesForType(FloatPointField.class);
final String[] sequential = new String[]{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0"};
final String[] randstrs = getRandomStringArrayWithFloats(10, true);
for (String r : Arrays.asList("*_p_f", "*_p_f_dv", "*_p_f_dv_ns", "*_p_f_ni_dv",
"*_p_f_ni_dv_ns", "*_p_f_ni_ns_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSort(r.replace("*","number"), sequential);
doTestPointFieldSort(r.replace("*","number"), randstrs);
// TODO: test some randomly generated (then sorted) arrays (with dups and/or missing values)
doTestFloatPointFunctionQuery(r.replace("*","number"), "float");
}
for (String r : Arrays.asList("*_p_f_ni", "*_p_f_ni_ns")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "w/o docValues", "42.34");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "w/o docValues", "42.34");
}
for (String r : Arrays.asList("*_p_f_mv", "*_p_f_ni_mv", "*_p_f_ni_mv_dv", "*_p_f_ni_dv_ns_mv",
"*_p_f_ni_ns_mv", "*_p_f_dv_ns_mv", "*_p_f_mv_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "42.34");
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "42.34", "66.6");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "42.34");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "42.34", "66.6");
}
assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
}
@Test
public void testFloatPointFieldFacetField() throws Exception {
testPointFieldFacetField("number_p_f", "number_p_f_dv", getSequentialStringArrayWithDoubles(10));
clearIndex();
assertU(commit());
testPointFieldFacetField("number_p_f", "number_p_f_dv", getRandomStringArrayWithFloats(10, false));
}
@Test
public void testFloatPointFieldRangeFacet() throws Exception {
doTestFloatPointFieldRangeFacet("number_p_f_dv", "number_p_f");
}
@Test
public void testFloatPointStats() throws Exception {
testPointStats("number_p_f", "number_p_f_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-10D, 9.9D, "10", "1", 1E-6D);
testPointStats("number_p_f_mv", "number_p_f_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-10D, 9.9D, "10", "1", 1E-6D);
}
@Test
public void testFloatPointFieldMultiValuedExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_f_mv", getRandomStringArrayWithFloats(20, false));
testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", getRandomStringArrayWithFloats(20, false));
}
@Test
public void testFloatPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", getRandomStringArrayWithFloats(20, false), false);
testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", getRandomStringArrayWithFloats(20, false), false);
}
@Test
public void testFloatPointFieldMultiValuedReturn() throws Exception {
testPointFieldMultiValuedReturn("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", getSequentialStringArrayWithDoubles(20));
}
@Test
public void testFloatPointFieldMultiValuedRangeQuery() throws Exception {
testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
}
@Test
public void testFloatPointFieldMultiValuedRangeFacet() throws Exception {
doTestDoublePointFieldMultiValuedRangeFacet("number_p_f_mv_dv", "number_p_f_mv");
}
@Test
public void testFloatPointFieldMultiValuedFacetField() throws Exception {
testPointFieldMultiValuedFacetField("number_p_f_mv", "number_p_f_mv_dv", getSequentialStringArrayWithDoubles(20));
testPointFieldMultiValuedFacetField("number_p_f_mv", "number_p_f_mv_dv", getRandomStringArrayWithFloats(20, false));
}
@Test
public void testFloatPointMultiValuedFunctionQuery() throws Exception {
testPointMultiValuedFunctionQuery("number_p_f_mv", "number_p_f_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
testPointMultiValuedFunctionQuery("number_p_f_mv", "number_p_f_mv_dv", "float", getRandomStringArrayWithFloats(20, true));
}
@Test
public void testFloatPointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
doTestFloatPointFieldsAtomicUpdates("number_p_f", "float");
doTestFloatPointFieldsAtomicUpdates("number_p_f_dv", "float");
doTestFloatPointFieldsAtomicUpdates("number_p_f_dv_ns", "float");
}
@Test
public void testMultiValuedFloatePointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testMultiValuedFloatPointFieldsAtomicUpdates("number_p_f_mv", "float");
testMultiValuedFloatPointFieldsAtomicUpdates("number_p_f_ni_mv_dv", "float");
testMultiValuedFloatPointFieldsAtomicUpdates("number_p_f_dv_ns_mv", "float");
}
@Test
public void testFloatPointSetQuery() throws Exception {
doTestSetQueries("number_p_f", getRandomStringArrayWithFloats(20, false), false);
doTestSetQueries("number_p_f_mv", getRandomStringArrayWithFloats(20, false), true);
doTestSetQueries("number_p_f_ni_dv", getRandomStringArrayWithFloats(20, false), false);
}
@Test
public void testFloatPointFieldNotIndexed() throws Exception {
doTestFieldNotIndexed("number_p_f_ni", getSequentialStringArrayWithDoubles(10));
doTestFieldNotIndexed("number_p_f_ni_mv", getSequentialStringArrayWithDoubles(10));
}
// Long
@Test
public void testLongPointFieldExactQuery() throws Exception {
doTestIntPointFieldExactQuery("number_p_l", true);
doTestIntPointFieldExactQuery("number_p_l_mv", true);
doTestIntPointFieldExactQuery("number_p_l_dv", true);
doTestIntPointFieldExactQuery("number_p_l_mv_dv", true);
doTestIntPointFieldExactQuery("number_p_l_ni_dv", true);
doTestIntPointFieldExactQuery("number_p_l_ni_ns_dv", true);
doTestIntPointFieldExactQuery("number_p_l_ni_dv_ns", true);
doTestIntPointFieldExactQuery("number_p_l_ni_mv_dv", true);
}
@Test
public void testLongPointFieldNonSearchableExactQuery() throws Exception {
doTestIntPointFieldExactQuery("number_p_l_ni", true, false);
doTestIntPointFieldExactQuery("number_p_l_ni_ns", true, false);
}
@Test
public void testLongPointFieldReturn() throws Exception {
testPointFieldReturn("number_p_l", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
testPointFieldReturn("number_p_l_dv_ns", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
}
@Test
public void testLongPointFieldRangeQuery() throws Exception {
doTestIntPointFieldRangeQuery("number_p_l", "long", true);
doTestIntPointFieldRangeQuery("number_p_l_ni_ns_dv", "long", true);
doTestIntPointFieldRangeQuery("number_p_l_dv", "long", true);
}
@Test
public void testLongPointFieldNonSearchableRangeQuery() throws Exception {
doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", "3333333333");
doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", "3333333333");
doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", "3333333333", "-4444444444");
}
@Test
public void testLongPointFieldSortAndFunction() throws Exception {
final SortedSet<String> regexToTest = dynFieldRegexesForType(LongPointField.class);
final String[] vals = new String[]{ String.valueOf(Integer.MIN_VALUE),
"1", "2", "3", "4", "5", "6", "7",
String.valueOf(Integer.MAX_VALUE), String.valueOf(Long.MAX_VALUE)};
for (String r : Arrays.asList("*_p_l", "*_p_l_dv", "*_p_l_dv_ns", "*_p_l_ni_dv",
"*_p_l_ni_dv_ns", "*_p_l_ni_ns_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSort(r.replace("*","number"), vals);
// TODO: test some randomly generated (then sorted) arrays (with dups and/or missing values)
doTestIntPointFunctionQuery(r.replace("*","number"), "long");
}
for (String r : Arrays.asList("*_p_l_ni", "*_p_l_ni_ns")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "w/o docValues", "4234");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "w/o docValues", "4234");
}
for (String r : Arrays.asList("*_p_l_mv", "*_p_l_ni_mv", "*_p_l_ni_mv_dv", "*_p_l_ni_dv_ns_mv",
"*_p_l_ni_ns_mv", "*_p_l_dv_ns_mv", "*_p_l_mv_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "4234");
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "4234", "66666666");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "4234");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "4234", "66666666");
}
assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
}
@Test
public void testLongPointFieldFacetField() throws Exception {
testPointFieldFacetField("number_p_l", "number_p_l_dv", getSequentialStringArrayWithInts(10));
clearIndex();
assertU(commit());
testPointFieldFacetField("number_p_l", "number_p_l_dv", getRandomStringArrayWithLongs(10, true));
}
@Test
public void testLongPointFieldRangeFacet() throws Exception {
doTestIntPointFieldRangeFacet("number_p_l_dv", "number_p_l");
}
@Test
public void testLongPointStats() throws Exception {
testPointStats("number_p_l", "number_p_l_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
0D, 9D, "10", "1", 0D);
testPointStats("number_p_l_mv", "number_p_l_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
0D, 9D, "10", "1", 0D);
}
@Test
public void testLongPointFieldMultiValuedExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_l_mv", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", getSequentialStringArrayWithInts(20));
}
@Test
public void testLongPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", getSequentialStringArrayWithInts(20), false);
testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
}
@Test
public void testLongPointFieldMultiValuedReturn() throws Exception {
testPointFieldMultiValuedReturn("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", getSequentialStringArrayWithInts(20));
}
@Test
public void testLongPointFieldMultiValuedRangeQuery() throws Exception {
testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", getSequentialStringArrayWithInts(20));
}
@Test
public void testLongPointFieldMultiValuedFacetField() throws Exception {
testPointFieldMultiValuedFacetField("number_p_l_mv", "number_p_l_mv_dv", getSequentialStringArrayWithInts(20));
testPointFieldMultiValuedFacetField("number_p_l_mv", "number_p_l_mv_dv", getRandomStringArrayWithLongs(20, false));
}
@Test
public void testLongPointFieldMultiValuedRangeFacet() throws Exception {
doTestIntPointFieldMultiValuedRangeFacet("number_p_l_mv_dv", "number_p_l_mv");
}
@Test
public void testLongPointMultiValuedFunctionQuery() throws Exception {
testPointMultiValuedFunctionQuery("number_p_l_mv", "number_p_l_mv_dv", "long", getSequentialStringArrayWithInts(20));
}
@Test
public void testLongPointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testIntPointFieldsAtomicUpdates("number_p_l", "long");
testIntPointFieldsAtomicUpdates("number_p_l_dv", "long");
testIntPointFieldsAtomicUpdates("number_p_l_dv_ns", "long");
}
@Test
public void testMultiValuedLongPointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testMultiValuedIntPointFieldsAtomicUpdates("number_p_l_mv", "long");
testMultiValuedIntPointFieldsAtomicUpdates("number_p_l_ni_mv_dv", "long");
testMultiValuedIntPointFieldsAtomicUpdates("number_p_l_dv_ns_mv", "long");
}
@Test
public void testLongPointSetQuery() throws Exception {
doTestSetQueries("number_p_l", getRandomStringArrayWithLongs(20, false), false);
doTestSetQueries("number_p_l_mv", getRandomStringArrayWithLongs(20, false), true);
doTestSetQueries("number_p_l_ni_dv", getRandomStringArrayWithLongs(20, false), false);
}
@Test
public void testLongPointFieldNotIndexed() throws Exception {
doTestFieldNotIndexed("number_p_l_ni", getSequentialStringArrayWithInts(10));
doTestFieldNotIndexed("number_p_l_ni_mv", getSequentialStringArrayWithInts(10));
}
// Date
@Test
public void testDatePointFieldExactQuery() throws Exception {
doTestDatePointFieldExactQuery("number_p_dt", "1995-12-31T23:59:59Z");
doTestDatePointFieldExactQuery("number_p_dt_mv", "2015-12-31T23:59:59Z-1DAY");
doTestDatePointFieldExactQuery("number_p_dt_dv", "2000-12-31T23:59:59Z+3DAYS");
doTestDatePointFieldExactQuery("number_p_dt_mv_dv", "2000-12-31T23:59:59Z+3DAYS");
doTestDatePointFieldExactQuery("number_p_dt_ni_dv", "2000-12-31T23:59:59Z+3DAYS");
doTestDatePointFieldExactQuery("number_p_dt_ni_ns_dv", "1995-12-31T23:59:59Z-1MONTH");
doTestDatePointFieldExactQuery("number_p_dt_ni_mv_dv", "1995-12-31T23:59:59Z+2MONTHS");
}
@Test
public void testDatePointFieldNonSearchableExactQuery() throws Exception {
doTestDatePointFieldExactQuery("number_p_dt_ni", "1995-12-31T23:59:59Z", false);
doTestDatePointFieldExactQuery("number_p_dt_ni_ns", "1995-12-31T23:59:59Z", false);
}
@Test
public void testDatePointFieldReturn() throws Exception {
testPointFieldReturn("number_p_dt", "date",
new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
"2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
testPointFieldReturn("number_p_dt_dv_ns", "date",
new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
"2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
}
@Test
public void testDatePointFieldRangeQuery() throws Exception {
doTestDatePointFieldRangeQuery("number_p_dt");
doTestDatePointFieldRangeQuery("number_p_dt_ni_ns_dv");
}
@Test
public void testDatePointFieldNonSearchableRangeQuery() throws Exception {
doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", "1995-12-31T23:59:59Z");
doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", "1995-12-31T23:59:59Z");
doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", "1995-12-31T23:59:59Z", "2000-10-31T23:59:59Z");
}
@Test
public void testDatePointFieldSortAndFunction() throws Exception {
final SortedSet<String> regexToTest = dynFieldRegexesForType(DatePointField.class);
final String[] sequential = getSequentialStringArrayWithDates(10);
for (String r : Arrays.asList("*_p_dt", "*_p_dt_dv", "*_p_dt_dv_ns", "*_p_dt_ni_dv",
"*_p_dt_ni_dv_ns", "*_p_dt_ni_ns_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSort(r.replace("*","number"), sequential);
// TODO: test some randomly generated (then sorted) arrays (with dups and/or missing values)
doTestDatePointFunctionQuery(r.replace("*","number"), "date");
}
for (String r : Arrays.asList("*_p_dt_ni", "*_p_dt_ni_ns")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "w/o docValues", "1995-12-31T23:59:59Z");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "w/o docValues", "1995-12-31T23:59:59Z");
}
for (String r : Arrays.asList("*_p_dt_mv", "*_p_dt_ni_mv", "*_p_dt_ni_mv_dv", "*_p_dt_ni_dv_ns_mv",
"*_p_dt_ni_ns_mv", "*_p_dt_dv_ns_mv", "*_p_dt_mv_dv")) {
assertTrue(r, regexToTest.remove(r));
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "1995-12-31T23:59:59Z");
doTestPointFieldSortError(r.replace("*","number"), "multivalued", "1995-12-31T23:59:59Z", "2000-12-31T23:59:59Z");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "1995-12-31T23:59:59Z");
doTestPointFieldFunctionQueryError(r.replace("*","number"), "multivalued", "1995-12-31T23:59:59Z", "2000-12-31T23:59:59Z");
}
assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
}
@Test
public void testDatePointFieldFacetField() throws Exception {
testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
clearIndex();
assertU(commit());
testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
}
@Test
public void testDatePointFieldRangeFacet() throws Exception {
doTestDatePointFieldRangeFacet("number_p_dt_dv", "number_p_dt");
}
@Test
public void testDatePointStats() throws Exception {
testDatePointStats("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
testDatePointStats("number_p_dt_mv", "number_p_dt_mv_dv", getSequentialStringArrayWithDates(10));
}
@Test
public void testDatePointFieldMultiValuedExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_dt_mv", getSequentialStringArrayWithDates(20));
testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", getSequentialStringArrayWithDates(20));
}
@Test
public void testDatePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", getSequentialStringArrayWithDates(20), false);
testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", getSequentialStringArrayWithDates(20), false);
}
@Test
public void testDatePointFieldMultiValuedReturn() throws Exception {
testPointFieldMultiValuedReturn("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", getSequentialStringArrayWithDates(20));
}
@Test
public void testDatePointFieldMultiValuedRangeQuery() throws Exception {
testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
}
@Test
public void testDatePointFieldMultiValuedFacetField() throws Exception {
testPointFieldMultiValuedFacetField("number_p_dt_mv", "number_p_dt_mv_dv", getSequentialStringArrayWithDates(20));
testPointFieldMultiValuedFacetField("number_p_dt_mv", "number_p_dt_mv_dv", getRandomStringArrayWithDates(20, false));
}
@Test
public void testDatePointFieldMultiValuedRangeFacet() throws Exception {
doTestDatePointFieldMultiValuedRangeFacet("number_p_dt_mv_dv", "number_p_dt_mv");
}
@Test
public void testDatePointMultiValuedFunctionQuery() throws Exception {
testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", getSequentialStringArrayWithDates(20));
}
@Test
public void testDatePointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testDatePointFieldsAtomicUpdates("number_p_dt", "date");
testDatePointFieldsAtomicUpdates("number_p_dt_dv", "date");
testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns", "date");
}
@Test
public void testMultiValuedDatePointFieldsAtomicUpdates() throws Exception {
if (!Boolean.getBoolean("enable.update.log")) {
return;
}
testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv", "date");
testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv", "date");
testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv", "date");
}
@Test
public void testDatePointSetQuery() throws Exception {
doTestSetQueries("number_p_dt", getRandomStringArrayWithDates(20, false), false);
doTestSetQueries("number_p_dt_mv", getRandomStringArrayWithDates(20, false), true);
doTestSetQueries("number_p_dt_ni_dv", getRandomStringArrayWithDates(20, false), false);
}
@Test
public void testDatePointFieldNotIndexed() throws Exception {
doTestFieldNotIndexed("number_p_dt_ni", getSequentialStringArrayWithDates(10));
doTestFieldNotIndexed("number_p_dt_ni_mv", getSequentialStringArrayWithDates(10));
}
@Test
public void testIndexOrDocValuesQuery() throws Exception {
String[] fieldTypeNames = new String[]{"_p_i", "_p_l", "_p_d", "_p_f"};
FieldType[] fieldTypes = new FieldType[]{new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField()};
assert fieldTypeNames.length == fieldTypes.length;
for (int i = 0; i < fieldTypeNames.length; i++) {
SchemaField fieldIndexed = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i]);
SchemaField fieldIndexedAndDv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_dv");
SchemaField fieldIndexedMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv");
SchemaField fieldIndexedAndDvMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv_dv");
assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, "0", "10", true, true) instanceof PointRangeQuery);
assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, "0", "10", true, true) instanceof PointRangeQuery);
assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, "0") instanceof PointRangeQuery);
assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, "0") instanceof IndexOrDocValuesQuery);
assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, "0") instanceof PointRangeQuery);
assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, "0") instanceof IndexOrDocValuesQuery);
}
}
public void testInternals() throws IOException {
String[] types = new String[]{"i", "l", "f", "d"};
String[] suffixes = new String[]{"", "_dv", "_mv", "_mv_dv", "_ni", "_ni_dv", "_ni_dv_ns", "_ni_dv_ns_mv", "_ni_mv", "_ni_mv_dv", "_ni_ns", "_ni_ns_mv", "_dv_ns", "_ni_ns_dv", "_dv_ns_mv"};
Set<String> typesTested = new HashSet<>();
for (String type:types) {
for (String suffix:suffixes) {
doTestInternals("number_p_" + type + suffix, getSequentialStringArrayWithInts(10));
typesTested.add("*_p_" + type + suffix);
}
}
for (String suffix:suffixes) {
doTestInternals("number_p_dt" + suffix, getSequentialStringArrayWithDates(10));
typesTested.add("*_p_dt" + suffix);
}
assertEquals("Missing types in the test", dynFieldRegexesForType(PointField.class), typesTested);
}
// Helper methods
/**
* Given a FieldType, return the list of DynamicField 'regexes' for all declared
* DynamicFields that use that FieldType.
*
* @see IndexSchema#getDynamicFields
* @see DynamicField#getRegex
*/
private static SortedSet<String> dynFieldRegexesForType(final Class<? extends FieldType> clazz) {
SortedSet<String> typesToTest = new TreeSet<>();
for (DynamicField dynField : h.getCore().getLatestSchema().getDynamicFields()) {
if (clazz.isInstance(dynField.getPrototype().getType())) {
typesToTest.add(dynField.getRegex());
}
}
return typesToTest;
}
private String[] getRandomStringArrayWithDoubles(int length, boolean sorted) {
Set<Double> set;
if (sorted) {
set = new TreeSet<>();
} else {
set = new HashSet<>();
}
while (set.size() < length) {
double f = random().nextDouble() * (Double.MAX_VALUE/2);
if (random().nextBoolean()) {
f = f * -1;
}
set.add(f);
}
String[] stringArr = new String[length];
int i = 0;
for (double val:set) {
stringArr[i] = String.valueOf(val);
i++;
}
return stringArr;
}
private String[] getRandomStringArrayWithFloats(int length, boolean sorted) {
Set<Float> set;
if (sorted) {
set = new TreeSet<>();
} else {
set = new HashSet<>();
}
while (set.size() < length) {
float f = random().nextFloat() * (Float.MAX_VALUE/2);
if (random().nextBoolean()) {
f = f * -1;
}
set.add(f);
}
String[] stringArr = new String[length];
int i = 0;
for (float val:set) {
stringArr[i] = String.valueOf(val);
i++;
}
return stringArr;
}
private String[] getSequentialStringArrayWithInts(int length) {
String[] arr = new String[length];
for (int i = 0; i < length; i++) {
arr[i] = String.valueOf(i);
}
return arr;
}
private String[] getSequentialStringArrayWithDates(int length) {
assert length < 60;
String[] arr = new String[length];
for (int i = 0; i < length; i++) {
arr[i] = String.format(Locale.ROOT, "1995-12-11T19:59:%02dZ", i);
}
return arr;
}
private String[] getSequentialStringArrayWithDoubles(int length) {
String[] arr = new String[length];
for (int i = 0; i < length; i++) {
arr[i] = String.format(Locale.ROOT, "%d.0", i);
}
return arr;
}
private String[] getRandomStringArrayWithInts(int length, boolean sorted) {
Set<Integer> set;
if (sorted) {
set = new TreeSet<>();
} else {
set = new HashSet<>();
}
while (set.size() < length) {
int number = random().nextInt(100);
if (random().nextBoolean()) {
number = number * -1;
}
set.add(number);
}
String[] stringArr = new String[length];
int i = 0;
for (int val:set) {
stringArr[i] = String.valueOf(val);
i++;
}
return stringArr;
}
private String[] getRandomStringArrayWithLongs(int length, boolean sorted) {
Set<Long> set;
if (sorted) {
set = new TreeSet<>();
} else {
set = new HashSet<>();
}
while (set.size() < length) {
long number = random().nextLong();
if (random().nextBoolean()) {
number = number * -1;
}
set.add(number);
}
String[] stringArr = new String[length];
int i = 0;
for (long val:set) {
stringArr[i] = String.valueOf(val);
i++;
}
return stringArr;
}
private String[] getRandomStringArrayWithDates(int length, boolean sorted) {
assert length < 60;
Set<Integer> set;
if (sorted) {
set = new TreeSet<>();
} else {
set = new HashSet<>();
}
while (set.size() < length) {
int number = random().nextInt(60);
set.add(number);
}
String[] stringArr = new String[length];
int i = 0;
for (int val:set) {
stringArr[i] = String.format(Locale.ROOT, "1995-12-11T19:59:%02dZ", val);
i++;
}
return stringArr;
}
private void doTestFieldNotIndexed(String field, String[] values) throws IOException {
assert values.length == 10;
// test preconditions
SchemaField sf = h.getCore().getLatestSchema().getField(field);
assertFalse("Field should be indexed=false", sf.indexed());
assertFalse("Field should be docValues=false", sf.hasDocValues());
for (int i=0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), field, values[i]));
}
assertU(commit());
assertQ(req("q", "*:*"), "//*[@numFound='10']");
assertQ("Can't search on index=false docValues=false field", req("q", field + ":[* TO *]"), "//*[@numFound='0']");
IndexReader ir;
RefCounted<SolrIndexSearcher> ref = null;
try {
ref = h.getCore().getSearcher();
ir = ref.get().getIndexReader();
assertEquals("Field " + field + " should have no point values", 0, PointValues.size(ir, field));
} finally {
ref.decref();
}
}
private void doTestIntPointFieldExactQuery(final String field, final boolean testLong) throws Exception {
doTestIntPointFieldExactQuery(field, testLong, true);
}
/**
* @param field the field to use for indexing and searching against
* @param testLong set to true if "field" is expected to support long values, false if only integers
* @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
*/
private void doTestIntPointFieldExactQuery(final String field, final boolean testLong, final boolean searchable) throws Exception {
final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
for (int i=0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
}
assertU(commit());
for (int i = 0; i < 10; i++) {
assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field),
MATCH_ONE);
}
for (int i = 0; i < 10; i++) {
assertQ(req("debug", "true", "q", field + ":" + (i+1) + " OR " + field + ":" + ((i+1)%10 + 1)), MATCH_TWO);
}
assertU(adoc("id", String.valueOf(Integer.MAX_VALUE), field, String.valueOf(Integer.MAX_VALUE)));
assertU(commit());
assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field),
MATCH_ONE);
if (testLong) {
for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
}
assertU(commit());
for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field),
MATCH_ONE);
}
assertU(adoc("id", String.valueOf(Long.MAX_VALUE), field, String.valueOf(Long.MAX_VALUE)));
assertU(commit());
assertQ(req("q", field + ":"+Long.MAX_VALUE, "fl", "id, " + field),
MATCH_ONE);
}
clearIndex();
assertU(commit());
}
private void testPointFieldReturn(String field, String type, String[] values) throws Exception {
SchemaField sf = h.getCore().getLatestSchema().getField(field);
assert sf.stored() || (sf.hasDocValues() && sf.useDocValuesAsStored()):
"Unexpected field definition for " + field;
for (int i=0; i < values.length; i++) {
assertU(adoc("id", String.valueOf(i), field, values[i]));
}
// Check using RTG
if (Boolean.getBoolean("enable.update.log")) {
for (int i = 0; i < values.length; i++) {
assertQ(req("qt", "/get", "id", String.valueOf(i)),
"//doc/" + type + "[@name='" + field + "'][.='" + values[i] + "']");
}
}
assertU(commit());
String[] expected = new String[values.length + 1];
expected[0] = "//*[@numFound='" + values.length + "']";
for (int i = 0; i < values.length; i++) {
expected[i + 1] = "//result/doc[str[@name='id']='" + i + "']/" + type + "[@name='" + field + "'][.='" + values[i] + "']";
}
assertQ(req("q", "*:*", "fl", "id, " + field, "rows", String.valueOf(values.length)), expected);
// Check using RTG
if (Boolean.getBoolean("enable.update.log")) {
for (int i = 0; i < values.length; i++) {
assertQ(req("qt", "/get", "id", String.valueOf(i)),
"//doc/" + type + "[@name='" + field + "'][.='" + values[i] + "']");
}
}
clearIndex();
assertU(commit());
}
private void doTestPointFieldNonSearchableRangeQuery(String fieldName, String... values) throws Exception {
for (int i = 9; i >= 0; i--) {
SolrInputDocument doc = sdoc("id", String.valueOf(i));
for (String value : values) {
doc.addField(fieldName, value);
}
assertU(adoc(doc));
}
assertU(commit());
assertQ(req("q", fieldName + ":[* TO *]", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='0']");
}
private void doTestIntPointFieldRangeQuery(String fieldName, String type, boolean testLong) throws Exception {
for (int i = 9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), fieldName, String.valueOf(i)));
}
assertU(commit());
assertQ(req("q", fieldName + ":[0 TO 3]", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='2']",
"//result/doc[4]/" + type + "[@name='" + fieldName + "'][.='3']");
assertQ(req("q", fieldName + ":{0 TO 3]", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='2']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='3']");
assertQ(req("q", fieldName + ":[0 TO 3}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='2']");
assertQ(req("q", fieldName + ":{0 TO 3}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='2']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='2']");
assertQ(req("q", fieldName + ":{0 TO *}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='9']",
"0=count(//result/doc/" + type + "[@name='" + fieldName + "'][.='0'])",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1']");
assertQ(req("q", fieldName + ":{* TO 3}", "fl", "id, " + fieldName, "sort", "id desc"),
"//*[@numFound='3']",
"0=count(//result/doc/" + type + "[@name='" + fieldName + "'][.='3'])",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='2']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='0']");
assertQ(req("q", fieldName + ":[* TO 3}", "fl", "id, " + fieldName, "sort", "id desc"),
"//*[@numFound='3']",
"0=count(//result/doc/" + type + "[@name='" + fieldName + "'][.='3'])",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='2']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='0']");
assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']",
"//result/doc[10]/" + type + "[@name='" + fieldName + "'][.='9']");
assertQ(req("q", fieldName + ":[0 TO 1] OR " + fieldName + ":[8 TO 9]" , "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='8']",
"//result/doc[4]/" + type + "[@name='" + fieldName + "'][.='9']");
assertQ(req("q", fieldName + ":[0 TO 1] AND " + fieldName + ":[1 TO 2]" , "fl", "id, " + fieldName),
"//*[@numFound='1']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1']");
assertQ(req("q", fieldName + ":[0 TO 1] AND NOT " + fieldName + ":[1 TO 2]" , "fl", "id, " + fieldName),
"//*[@numFound='1']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']");
clearIndex();
assertU(commit());
String[] arr;
if (testLong) {
arr = getRandomStringArrayWithLongs(100, true);
} else {
arr = getRandomStringArrayWithInts(100, true);
}
for (int i = 0; i < arr.length; i++) {
assertU(adoc("id", String.valueOf(i), fieldName, arr[i]));
}
assertU(commit());
for (int i = 0; i < arr.length; i++) {
assertQ(req("q", fieldName + ":[" + arr[0] + " TO " + arr[i] + "]", "fl", "id, " + fieldName),
"//*[@numFound='" + (i + 1) + "']");
assertQ(req("q", fieldName + ":{" + arr[0] + " TO " + arr[i] + "}", "fl", "id, " + fieldName),
"//*[@numFound='" + (Math.max(0, i-1)) + "']");
assertQ(req("q", fieldName + ":[" + arr[0] + " TO " + arr[i] + "] AND " + fieldName + ":" + arr[0].replace("-", "\\-"), "fl", "id, " + fieldName),
"//*[@numFound='1']");
}
}
private void testPointFieldFacetField(String nonDocValuesField, String docValuesField, String[] numbers) throws Exception {
assert numbers != null && numbers.length == 10;
assertFalse(h.getCore().getLatestSchema().getField(docValuesField).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), docValuesField, numbers[i], nonDocValuesField, numbers[i]));
}
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + docValuesField, "facet", "true", "facet.field", docValuesField),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[1] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[2] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[3] + "'][.='1']");
assertU(adoc("id", "10", docValuesField, numbers[1], nonDocValuesField, numbers[1]));
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + docValuesField, "facet", "true", "facet.field", docValuesField),
"//*[@numFound='11']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[1] + "'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[2] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[3] + "'][.='1']");
// assertU(commit());
// assertQ(req("q", "id:0", "fl", "id, " + docValuesField, "facet", "true", "facet.field", docValuesField, "facet.mincount", "0"),
// "//*[@numFound='1']",
// "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[0] + "'][.='1']",
// "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[1] + "'][.='0']",
// "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int[@name='" + numbers[2] + "'][.='0']",
// "count(//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + docValuesField +"']/int))==10");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
assertQEx("Expecting Exception",
"Can't facet on a PointField without docValues",
req("q", "*:*", "fl", "id, " + nonDocValuesField, "facet", "true", "facet.field", nonDocValuesField),
SolrException.ErrorCode.BAD_REQUEST);
}
private void doTestIntPointFieldRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(i), nonDocValuesField, String.valueOf(i)));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
// Range Faceting with method = filter should work
assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "filter"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
// this should actually use filter method instead of dv
assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
}
private void doTestIntPointFunctionQuery(String field, String type) throws Exception {
for (int i = 9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), field, String.valueOf(i)));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id, " + field, "sort", "product(-1," + field + ") asc"),
"//*[@numFound='10']",
"//result/doc[1]/" + type + "[@name='" + field + "'][.='9']",
"//result/doc[2]/" + type + "[@name='" + field + "'][.='8']",
"//result/doc[3]/" + type + "[@name='" + field + "'][.='7']",
"//result/doc[10]/" + type + "[@name='" + field + "'][.='0']");
assertQ(req("q", "*:*", "fl", "id, " + field + ", product(-1," + field + ")", "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/float[@name='product(-1," + field + ")'][.='-0.0']",
"//result/doc[2]/float[@name='product(-1," + field + ")'][.='-1.0']",
"//result/doc[3]/float[@name='product(-1," + field + ")'][.='-2.0']",
"//result/doc[10]/float[@name='product(-1," + field + ")'][.='-9.0']");
assertQ(req("q", "*:*", "fl", "id, " + field + ", field(" + field + ")", "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/" + type + "[@name='field(" + field + ")'][.='0']",
"//result/doc[2]/" + type + "[@name='field(" + field + ")'][.='1']",
"//result/doc[3]/" + type + "[@name='field(" + field + ")'][.='2']",
"//result/doc[10]/" + type + "[@name='field(" + field + ")'][.='9']");
}
/**
* Checks that the specified field can not be used as a value source, even if there are documents
* with (all) the specified values in the index.
*
* @param field the field name to try and sort on
* @param errSubStr substring to look for in the error msg
* @param values one or more values to put into the doc(s) in the index - may be more then one for multivalued fields
*/
private void doTestPointFieldFunctionQueryError(String field, String errSubStr, String...values) throws Exception {
final int numDocs = atLeast(random(), 10);
for (int i = 0; i < numDocs; i++) {
SolrInputDocument doc = sdoc("id", String.valueOf(i));
for (String v: values) {
doc.addField(field, v);
}
assertU(adoc(doc));
}
assertQEx("Should not be able to use field in function: " + field, errSubStr,
req("q", "*:*", "fl", "id", "fq", "{!frange l=0 h=100}product(-1, " + field + ")"),
SolrException.ErrorCode.BAD_REQUEST);
clearIndex();
assertU(commit());
// empty index should (also) give same error
assertQEx("Should not be able to use field in function: " + field, errSubStr,
req("q", "*:*", "fl", "id", "fq", "{!frange l=0 h=100}product(-1, " + field + ")"),
SolrException.ErrorCode.BAD_REQUEST);
}
private void testPointStats(String field, String dvField, String[] numbers, double min, double max, String count, String missing, double delta) {
String minMin = String.valueOf(min - Math.abs(delta*min));
String maxMin = String.valueOf(min + Math.abs(delta*min));
String minMax = String.valueOf(max - Math.abs(delta*max));
String maxMax = String.valueOf(max + Math.abs(delta*max));
for (int i = 0; i < numbers.length; i++) {
assertU(adoc("id", String.valueOf(i), dvField, numbers[i], field, numbers[i]));
}
assertU(adoc("id", String.valueOf(numbers.length)));
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(dvField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(dvField).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id, " + dvField, "stats", "true", "stats.field", dvField),
"//*[@numFound='11']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.>='" + minMin + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.<='" + maxMin+ "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='max'][.>='" + minMax + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='max'][.<='" + maxMax + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/long[@name='count'][.='" + count + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/long[@name='missing'][.='" + missing + "']");
assertFalse(h.getCore().getLatestSchema().getField(field).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
assertQEx("Expecting Exception",
"Can't calculate stats on a PointField without docValues",
req("q", "*:*", "fl", "id, " + field, "stats", "true", "stats.field", field),
SolrException.ErrorCode.BAD_REQUEST);
}
private void testPointFieldMultiValuedExactQuery(final String fieldName, final String[] numbers) throws Exception {
testPointFieldMultiValuedExactQuery(fieldName, numbers, true);
}
/**
* @param fieldName the field to use for indexing and searching against
* @param numbers list of 20 values to index in 10 docs (pairwise)
* @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
*/
private void testPointFieldMultiValuedExactQuery(final String fieldName, final String[] numbers,
final boolean searchable) throws Exception {
final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
assert numbers != null && numbers.length == 20;
assertTrue(h.getCore().getLatestSchema().getField(fieldName).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(fieldName).getType() instanceof PointField);
for (int i=0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), fieldName, numbers[i], fieldName, numbers[i+10]));
}
assertU(commit());
for (int i = 0; i < 20; i++) {
if (h.getCore().getLatestSchema().getField(fieldName).getType() instanceof DatePointField) {
assertQ(req("q", fieldName + ":\"" + numbers[i] + "\""),
MATCH_ONE);
} else {
assertQ(req("q", fieldName + ":" + numbers[i].replace("-", "\\-")),
MATCH_ONE);
}
}
for (int i = 0; i < 20; i++) {
if (h.getCore().getLatestSchema().getField(fieldName).getType() instanceof DatePointField) {
assertQ(req("q", fieldName + ":\"" + numbers[i] + "\"" + " OR " + fieldName + ":\"" + numbers[(i+1)%10]+"\""),
MATCH_TWO);
} else {
assertQ(req("q", fieldName + ":" + numbers[i].replace("-", "\\-") + " OR " + fieldName + ":" + numbers[(i+1)%10].replace("-", "\\-")),
MATCH_TWO);
}
}
}
private void testPointFieldMultiValuedReturn(String fieldName, String type, String[] numbers) throws Exception {
assert numbers != null && numbers.length == 20;
assertTrue(h.getCore().getLatestSchema().getField(fieldName).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(fieldName).getType() instanceof PointField);
for (int i=9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), fieldName, numbers[i], fieldName, numbers[i+10]));
}
// Check using RTG before commit
if (Boolean.getBoolean("enable.update.log")) {
for (int i = 0; i < 10; i++) {
assertQ(req("qt", "/get", "id", String.valueOf(i)),
"//doc/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[i] + "']",
"//doc/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[i+10] + "']",
"count(//doc/arr[@name='" + fieldName + "']/" + type + ")=2");
}
}
// Check using RTG after commit
assertU(commit());
if (Boolean.getBoolean("enable.update.log")) {
for (int i = 0; i < 10; i++) {
assertQ(req("qt", "/get", "id", String.valueOf(i)),
"//doc/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[i] + "']",
"//doc/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[i+10] + "']",
"count(//doc/arr[@name='" + fieldName + "']/" + type + ")=2");
}
}
String[] expected = new String[21];
expected[0] = "//*[@numFound='10']";
for (int i = 1; i <= 10; i++) {
// checks for each doc's two values aren't next to eachother in array, but that doesn't matter for correctness
expected[i] = "//result/doc[" + i + "]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[i-1] + "']";
expected[i+10] = "//result/doc[" + i + "]/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[i + 9] + "']";
}
assertQ(req("q", "*:*", "fl", "id, " + fieldName, "sort","id asc"), expected);
}
private void testPointFieldMultiValuedRangeQuery(String fieldName, String type, String[] numbers) throws Exception {
assert numbers != null && numbers.length == 20;
assertTrue(h.getCore().getLatestSchema().getField(fieldName).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(fieldName).getType() instanceof PointField);
for (int i=9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), fieldName, numbers[i], fieldName, numbers[i+10]));
}
assertU(commit());
assertQ(req("q", String.format(Locale.ROOT, "%s:[%s TO %s]", fieldName, numbers[0], numbers[3]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[10] + "']",
"//result/doc[2]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']",
"//result/doc[2]/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[11] + "']",
"//result/doc[3]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[2] + "']",
"//result/doc[3]/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[12] + "']",
"//result/doc[4]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[3] + "']",
"//result/doc[4]/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[13] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:{%s TO %s]", fieldName, numbers[0], numbers[3]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']",
"//result/doc[2]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[2] + "']",
"//result/doc[3]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[3] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:[%s TO %s}", fieldName, numbers[0], numbers[3]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']",
"//result/doc[2]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']",
"//result/doc[3]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[2] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:{%s TO %s}", fieldName, numbers[0], numbers[3]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='2']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']",
"//result/doc[2]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[2] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:{%s TO *}", fieldName, numbers[0]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:{%s TO *}", fieldName, numbers[10]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='9']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:{* TO %s}", fieldName, numbers[3]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:[* TO %s}", fieldName, numbers[3]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']",
"//result/doc[10]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[9] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:[%s TO %s] OR %s:[%s TO %s]", fieldName, numbers[0], numbers[1], fieldName, numbers[8], numbers[9]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']",
"//result/doc[2]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']",
"//result/doc[3]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[8] + "']",
"//result/doc[4]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[9] + "']");
assertQ(req("q", String.format(Locale.ROOT, "%s:[%s TO %s] OR %s:[%s TO %s]", fieldName, numbers[0], numbers[0], fieldName, numbers[10], numbers[10]),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='1']",
"//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
}
private void testPointFieldMultiValuedFacetField(String nonDocValuesField, String dvFieldName, String[] numbers) throws Exception {
assert numbers != null && numbers.length == 20;
assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).getType() instanceof PointField);
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), dvFieldName, numbers[i], dvFieldName, numbers[i + 10],
nonDocValuesField, numbers[i], nonDocValuesField, numbers[i + 10]));
if (rarely()) {
assertU(commit());
}
}
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[1] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[2] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[3] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[10] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[11] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[12] + "'][.='1']");
assertU(adoc("id", "10", dvFieldName, numbers[1], nonDocValuesField, numbers[1]));
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName),
"//*[@numFound='11']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[1] + "'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[2] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[3] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[10] + "'][.='1']");
assertU(adoc("id", "10", dvFieldName, numbers[1], nonDocValuesField, numbers[1], dvFieldName, numbers[1], nonDocValuesField, numbers[1]));
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName, "facet.missing", "true"),
"//*[@numFound='11']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[1] + "'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[2] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[3] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[10] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[not(@name)][.='0']"
);
assertU(adoc("id", "10")); // add missing values
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName, "facet.missing", "true"),
"//*[@numFound='11']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[1] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[2] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[3] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[10] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[not(@name)][.='1']"
);
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName, "facet.mincount", "3"),
"//*[@numFound='11']",
"count(//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int)=0");
assertQ(req("q", "id:0", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName),
"//*[@numFound='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[0] + "'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + numbers[10] + "'][.='1']",
"count(//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int)=2");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
assertQEx("Expecting Exception",
"Can't facet on a PointField without docValues",
req("q", "*:*", "fl", "id, " + nonDocValuesField, "facet", "true", "facet.field", nonDocValuesField),
SolrException.ErrorCode.BAD_REQUEST);
clearIndex();
assertU(commit());
String smaller, larger;
try {
if (Long.parseLong(numbers[1]) < Long.parseLong(numbers[2])) {
smaller = numbers[1];
larger = numbers[2];
} else {
smaller = numbers[2];
larger = numbers[1];
}
} catch (NumberFormatException e) {
try {
if (Double.valueOf(numbers[1]) < Double.valueOf(numbers[2])) {
smaller = numbers[1];
larger = numbers[2];
} else {
smaller = numbers[2];
larger = numbers[1];
}
} catch (NumberFormatException e2) {
if (DateMathParser.parseMath(null, numbers[1]).getTime() < DateMathParser.parseMath(null, numbers[2]).getTime()) {
smaller = numbers[1];
larger = numbers[2];
} else {
smaller = numbers[2];
larger = numbers[1];
}
}
}
assertU(adoc("id", "1", dvFieldName, smaller, dvFieldName, larger));
assertU(adoc("id", "2", dvFieldName, larger));
assertU(commit());
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName),
"//*[@numFound='2']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + larger + "'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + smaller + "'][.='1']",
"count(//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int)=2");
assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "facet", "true", "facet.field", dvFieldName, "facet.sort", "index"),
"//*[@numFound='2']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='" + smaller +"'][.='1']",
"//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int[@name='"+ larger + "'][.='2']",
"count(//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='" + dvFieldName +"']/int)=2");
clearIndex();
assertU(commit());
}
private void testPointMultiValuedFunctionQuery(String nonDocValuesField, String docValuesField, String type, String[] numbers) throws Exception {
assert numbers != null && numbers.length == 20;
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), docValuesField, numbers[i], docValuesField, numbers[i+10],
nonDocValuesField, numbers[i], nonDocValuesField, numbers[i+10]));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
String function = "field(" + docValuesField + ", min)";
// assertQ(req("q", "*:*", "fl", "id, " + function),
// "//*[@numFound='10']",
// "//result/doc[1]/" + type + "[@name='" + function + "'][.='" + numbers[0] + "']",
// "//result/doc[2]/" + type + "[@name='" + function + "'][.='" + numbers[1] + "']",
// "//result/doc[3]/" + type + "[@name='" + function + "'][.='" + numbers[2] + "']",
// "//result/doc[10]/" + type + "[@name='" + function + "'][.='" + numbers[9] + "']");
assertQ(req("q", "*:*", "fl", "id, " + docValuesField, "sort", function + " desc"),
"//*[@numFound='10']",
"//result/doc[1]/str[@name='id'][.='9']",
"//result/doc[2]/str[@name='id'][.='8']",
"//result/doc[3]/str[@name='id'][.='7']",
"//result/doc[10]/str[@name='id'][.='0']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
function = "field(" + nonDocValuesField + ",min)";
assertQEx("Expecting Exception",
"sort param could not be parsed as a query",
req("q", "*:*", "fl", "id", "sort", function + " desc"),
SolrException.ErrorCode.BAD_REQUEST);
assertQEx("Expecting Exception",
"docValues='true' is required to select 'min' value from multivalued field (" + nonDocValuesField + ") at query time",
req("q", "*:*", "fl", "id, " + function),
SolrException.ErrorCode.BAD_REQUEST);
function = "field(" + docValuesField + ",foo)";
assertQEx("Expecting Exception",
"Multi-Valued field selector 'foo' not supported",
req("q", "*:*", "fl", "id, " + function),
SolrException.ErrorCode.BAD_REQUEST);
}
private void testMultiValuedIntPointFieldsAtomicUpdates(String field, String type) throws Exception {
assertU(adoc(sdoc("id", "1", field, "1")));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='1']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=1");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("add", 2))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='1']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='2']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=2");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("remove", 1))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='2']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=1");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", ImmutableList.of(1, 2, 3)))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='1']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='2']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='3']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=3");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("removeregex", ".*"))));
assertU(commit());
assertQ(req("q", "id:1"),
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=0");
}
private void testMultiValuedFloatPointFieldsAtomicUpdates(String field, String type) throws Exception {
assertU(adoc(sdoc("id", "1", field, "1.0")));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='1.0']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=1");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("add", 2.1f))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='1.0']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='2.1']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=2");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("remove", 1f))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='2.1']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=1");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", ImmutableList.of(1f, 2f, 3f)))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='1.0']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='2.0']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='3.0']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=3");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("removeregex", ".*"))));
assertU(commit());
assertQ(req("q", "id:1"),
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=0");
}
private void testIntPointFieldsAtomicUpdates(String field, String type) throws Exception {
assertU(adoc(sdoc("id", "1", field, "1")));
assertU(commit());
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("inc", 1))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='2']");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("inc", -1))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='1']");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", 3))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='3']");
}
private void doTestFloatPointFieldExactQuery(final String field) throws Exception {
doTestFloatPointFieldExactQuery(field, true);
}
/**
* @param field the field to use for indexing and searching against
* @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
*/
private void doTestFloatPointFieldExactQuery(String field, final boolean searchable) throws Exception {
final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
for (int i=0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), field, String.valueOf(i + "." + i)));
}
assertU(commit());
for (int i = 0; i < 9; i++) {
assertQ(req("q", field + ":"+(i+1) + "." + (i+1), "fl", "id, " + field),
MATCH_ONE);
}
for (int i = 0; i < 9; i++) {
String num1 = (i+1) + "." + (i+1);
String num2 = ((i+1)%9 + 1) + "." + ((i+1)%9 + 1);
assertQ(req("q", field + ":" + num1 + " OR " + field + ":" + num2),
MATCH_TWO);
}
clearIndex();
assertU(commit());
for (int i = 0; i < atLeast(10); i++) {
float rand = random().nextFloat() * 10;
assertU(adoc("id", "random_number ", field, String.valueOf(rand))); //always the same id to override
assertU(commit());
assertQ(req("q", field + ":" + rand, "fl", "id, " + field),
MATCH_ONE);
}
clearIndex();
assertU(commit());
}
/**
* For each value, creates a doc with that value in the specified field and then asserts that
* asc/desc sorts on that field succeeds and that the docs are in the (relatively) expected order
*
* @param field name of field to sort on
* @param values list of values in ascending order
*/
private void doTestPointFieldSort(String field, String... values) throws Exception {
assert values != null && 2 <= values.length;
// TODO: need to add sort missing coverage...
//
// idea: accept "null" as possible value for sort missing tests ?
//
// need to account for possibility that multiple nulls will be in non deterministic order
// always using secondary sort on id seems prudent ... handles any "dups" in values[]
final List<SolrInputDocument> docs = new ArrayList<>(values.length);
final String[] ascXpathChecks = new String[values.length + 1];
final String[] descXpathChecks = new String[values.length + 1];
ascXpathChecks[values.length] = "//*[@numFound='" + values.length + "']";
descXpathChecks[values.length] = "//*[@numFound='" + values.length + "']";
for (int i = values.length-1; i >= 0; i--) {
docs.add(sdoc("id", String.valueOf(i), field, String.valueOf(values[i])));
// reminder: xpath array indexes start at 1
ascXpathChecks[i]= "//result/doc["+ (1 + i)+"]/str[@name='id'][.='"+i+"']";
descXpathChecks[i]= "//result/doc["+ (values.length - i) +"]/str[@name='id'][.='"+i+"']";
}
// ensure doc add order doesn't affect results
Collections.shuffle(docs, random());
for (SolrInputDocument doc : docs) {
assertU(adoc(doc));
}
assertU(commit());
assertQ(req("q", "*:*", "fl", "id", "sort", field + " asc"),
ascXpathChecks);
assertQ(req("q", "*:*", "fl", "id", "sort", field + " desc"),
descXpathChecks);
clearIndex();
assertU(commit());
}
/**
* Checks that the specified field can not be sorted on, even if there are documents
* with (all) the specified values in the index.
*
* @param field the field name to try and sort on
* @param errSubStr substring to look for in the error msg
* @param values one or more values to put into the doc(s) in the index - may be more then one for multivalued fields
*/
private void doTestPointFieldSortError(String field, String errSubStr, String... values) throws Exception {
final int numDocs = atLeast(random(), 10);
for (int i = 0; i < numDocs; i++) {
SolrInputDocument doc = sdoc("id", String.valueOf(i));
for (String v: values) {
doc.addField(field, v);
}
assertU(adoc(doc));
}
assertQEx("Should not be able to sort on field: " + field, errSubStr,
req("q", "*:*", "fl", "id", "sort", field + " desc"),
SolrException.ErrorCode.BAD_REQUEST);
clearIndex();
assertU(commit());
// empty index should (also) give same error
assertQEx("Should not be able to sort on field: " + field, errSubStr,
req("q", "*:*", "fl", "id", "sort", field + " desc"),
SolrException.ErrorCode.BAD_REQUEST);
}
private void doTestFloatPointFieldRangeQuery(String fieldName, String type, boolean testDouble) throws Exception {
for (int i = 9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), fieldName, String.valueOf(i)));
}
assertU(commit());
assertQ(req("q", fieldName + ":[0 TO 3]", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1.0']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='2.0']",
"//result/doc[4]/" + type + "[@name='" + fieldName + "'][.='3.0']");
assertQ(req("q", fieldName + ":{0 TO 3]", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1.0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='2.0']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='3.0']");
assertQ(req("q", fieldName + ":[0 TO 3}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1.0']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='2.0']");
assertQ(req("q", fieldName + ":{0 TO 3}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='2']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1.0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='2.0']");
assertQ(req("q", fieldName + ":{0 TO *}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='9']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1.0']");
assertQ(req("q", fieldName + ":{* TO 3}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1.0']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='2.0']");
assertQ(req("q", fieldName + ":[* TO 3}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']",
"//result/doc[2]/" + type + "[@name='" + fieldName + "'][.='1.0']",
"//result/doc[3]/" + type + "[@name='" + fieldName + "'][.='2.0']");
assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']",
"//result/doc[10]/" + type + "[@name='" + fieldName + "'][.='9.0']");
assertQ(req("q", fieldName + ":[0.9 TO 1.01]", "fl", "id, " + fieldName),
"//*[@numFound='1']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1.0']");
assertQ(req("q", fieldName + ":{0.9 TO 1.01}", "fl", "id, " + fieldName),
"//*[@numFound='1']",
"//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1.0']");
clearIndex();
assertU(commit());
String[] arr;
if (testDouble) {
arr = getRandomStringArrayWithDoubles(10, true);
} else {
arr = getRandomStringArrayWithFloats(10, true);
}
for (int i = 0; i < arr.length; i++) {
assertU(adoc("id", String.valueOf(i), fieldName, arr[i]));
}
assertU(commit());
for (int i = 0; i < arr.length; i++) {
assertQ(req("q", fieldName + ":[" + arr[0] + " TO " + arr[i] + "]", "fl", "id, " + fieldName),
"//*[@numFound='" + (i + 1) + "']");
assertQ(req("q", fieldName + ":{" + arr[0] + " TO " + arr[i] + "}", "fl", "id, " + fieldName),
"//*[@numFound='" + (Math.max(0, i-1)) + "']");
}
}
private void doTestFloatPointFieldRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), docValuesField, String.format(Locale.ROOT, "%f", (float)i*1.1), nonDocValuesField, String.format(Locale.ROOT, "%f", (float)i*1.1)));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
// Range Faceting with method = filter should work
assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "filter"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
// this should actually use filter method instead of dv
assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
}
private void doTestFloatPointFunctionQuery(String field, String type) throws Exception {
for (int i = 9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), field, String.format(Locale.ROOT, "%f", (float)i*1.1)));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id, " + field, "sort", "product(-1," + field + ") asc"),
"//*[@numFound='10']",
"//result/doc[1]/" + type + "[@name='" + field + "'][.='9.9']",
"//result/doc[2]/" + type + "[@name='" + field + "'][.='8.8']",
"//result/doc[3]/" + type + "[@name='" + field + "'][.='7.7']",
"//result/doc[10]/" + type + "[@name='" + field + "'][.='0.0']");
assertQ(req("q", "*:*", "fl", "id, " + field + ", product(-1," + field + ")", "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/float[@name='product(-1," + field + ")'][.='-0.0']",
"//result/doc[2]/float[@name='product(-1," + field + ")'][.='-1.1']",
"//result/doc[3]/float[@name='product(-1," + field + ")'][.='-2.2']",
"//result/doc[10]/float[@name='product(-1," + field + ")'][.='-9.9']");
assertQ(req("q", "*:*", "fl", "id, " + field + ", field(" + field + ")", "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/" + type + "[@name='field(" + field + ")'][.='0.0']",
"//result/doc[2]/" + type + "[@name='field(" + field + ")'][.='1.1']",
"//result/doc[3]/" + type + "[@name='field(" + field + ")'][.='2.2']",
"//result/doc[10]/" + type + "[@name='field(" + field + ")'][.='9.9']");
}
private void doTestSetQueries(String fieldName, String[] values, boolean multiValued) {
for (int i = 0; i < values.length; i++) {
assertU(adoc("id", String.valueOf(i), fieldName, values[i]));
}
assertU(commit());
SchemaField sf = h.getCore().getLatestSchema().getField(fieldName);
assertTrue(sf.getType() instanceof PointField);
for (int i = 0; i < values.length; i++) {
assertQ(req("q", "{!term f='" + fieldName + "'}" + values[i], "fl", "id," + fieldName),
"//*[@numFound='1']");
}
for (int i = 0; i < values.length; i++) {
assertQ(req("q", "{!terms f='" + fieldName + "'}" + values[i] + "," + values[(i + 1)%values.length], "fl", "id," + fieldName),
"//*[@numFound='2']");
}
assertTrue(values.length > SolrQueryParser.TERMS_QUERY_THRESHOLD);
int numTerms = SolrQueryParser.TERMS_QUERY_THRESHOLD + 1;
StringBuilder builder = new StringBuilder(fieldName + ":(");
for (int i = 0; i < numTerms; i++) {
if (sf.getType().getNumberType() == NumberType.DATE) {
builder.append(String.valueOf(values[i]).replace(":", "\\:") + ' ');
} else {
builder.append(String.valueOf(values[i]).replace("-", "\\-") + ' ');
}
}
builder.append(')');
if (sf.indexed()) { // SolrQueryParser should also be generating a PointInSetQuery if indexed
assertQ(req(CommonParams.DEBUG, CommonParams.QUERY, "q", "*:*", "fq", builder.toString(), "fl", "id," + fieldName),
"//*[@numFound='" + numTerms + "']",
"//*[@name='parsed_filter_queries']/str[.='(" + getSetQueryToString(fieldName, values, numTerms) + ")']");
} else {
// Won't use PointInSetQuery if the fiels is not indexed, but should match the same docs
assertQ(req(CommonParams.DEBUG, CommonParams.QUERY, "q", "*:*", "fq", builder.toString(), "fl", "id," + fieldName),
"//*[@numFound='" + numTerms + "']");
}
if (multiValued) {
clearIndex();
assertU(commit());
for (int i = 0; i < values.length; i++) {
assertU(adoc("id", String.valueOf(i), fieldName, values[i], fieldName, values[(i+1)%values.length]));
}
assertU(commit());
for (int i = 0; i < values.length; i++) {
assertQ(req("q", "{!term f='" + fieldName + "'}" + values[i], "fl", "id," + fieldName),
"//*[@numFound='2']");
}
for (int i = 0; i < values.length; i++) {
assertQ(req("q", "{!terms f='" + fieldName + "'}" + values[i] + "," + values[(i + 1)%values.length], "fl", "id," + fieldName),
"//*[@numFound='3']");
}
}
}
private String getSetQueryToString(String fieldName, String[] values, int numTerms) {
SchemaField sf = h.getCore().getLatestSchema().getField(fieldName);
return sf.getType().getSetQuery(null, sf, Arrays.asList(Arrays.copyOf(values, numTerms))).toString();
}
private void doTestDoublePointFieldMultiValuedRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(i), docValuesField, String.valueOf(i + 10),
nonDocValuesField, String.valueOf(i), nonDocValuesField, String.valueOf(i + 10)));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='10.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='12.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='14.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='16.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='18.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='10.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='12.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='14.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='16.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='18.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "0", "facet.range.end", "20", "facet.range.gap", "100"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='10']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).multiValued());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
// Range Faceting with method = filter should work
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2", "facet.range.method", "filter"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='10.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='12.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='14.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='16.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='18.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
// this should actually use filter method instead of dv
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='10.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='12.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='14.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='16.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='18.0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10.0'][.='0']");
}
private void doTestIntPointFieldMultiValuedRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
for (int i = 0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(i), docValuesField, String.valueOf(i + 10),
nonDocValuesField, String.valueOf(i), nonDocValuesField, String.valueOf(i + 10)));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='10'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='12'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='14'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='16'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='18'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='10'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='12'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='14'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='16'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='18'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "0", "facet.range.end", "20", "facet.range.gap", "100"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='10']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
// Range Faceting with method = filter should work
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2", "facet.range.method", "filter"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='10'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='12'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='14'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='16'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='18'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
// this should actually use filter method instead of dv
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "20", "facet.range.gap", "2", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='10'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='12'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='14'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='16'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='18'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
}
private void doTestDatePointFieldExactQuery(final String field, final String baseDate) throws Exception {
doTestDatePointFieldExactQuery(field, baseDate, true);
}
/**
* @param field the field to use for indexing and searching against
* @param baseDate basic value to use for indexing and searching
* @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
*/
private void doTestDatePointFieldExactQuery(final String field, final String baseDate, final boolean searchable) throws Exception {
final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
for (int i=0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), field, String.format(Locale.ROOT, "%s+%dMINUTES", baseDate, i+1)));
}
assertU(commit());
for (int i = 0; i < 10; i++) {
String date = String.format(Locale.ROOT, "%s+%dMINUTES", baseDate, i+1);
assertQ(req("q", field + ":\""+date+"\"", "fl", "id, " + field),
MATCH_ONE);
}
for (int i = 0; i < 10; i++) {
String date1 = String.format(Locale.ROOT, "%s+%dMINUTES", baseDate, i+1);
String date2 = String.format(Locale.ROOT, "%s+%dMINUTES", baseDate, ((i+1)%10 + 1));
assertQ(req("q", field + ":\"" + date1 + "\""
+ " OR " + field + ":\"" + date2 + "\""),
MATCH_TWO);
}
clearIndex();
assertU(commit());
}
private void doTestDatePointFieldRangeQuery(String fieldName) throws Exception {
String baseDate = "1995-12-31T10:59:59Z";
for (int i = 9; i >= 0; i--) {
assertU(adoc("id", String.valueOf(i), fieldName, String.format(Locale.ROOT, "%s+%dHOURS", baseDate, i)));
}
assertU(commit());
assertQ(req("q", fieldName + ":" + String.format(Locale.ROOT, "[%s+0HOURS TO %s+3HOURS]", baseDate, baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']",
"//result/doc[2]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']",
"//result/doc[3]/date[@name='" + fieldName + "'][.='1995-12-31T12:59:59Z']",
"//result/doc[4]/date[@name='" + fieldName + "'][.='1995-12-31T13:59:59Z']");
assertQ(req("q", fieldName + ":" + String.format(Locale.ROOT, "{%s+0HOURS TO %s+3HOURS]", baseDate, baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']",
"//result/doc[2]/date[@name='" + fieldName + "'][.='1995-12-31T12:59:59Z']",
"//result/doc[3]/date[@name='" + fieldName + "'][.='1995-12-31T13:59:59Z']");
assertQ(req("q", fieldName + ":"+ String.format(Locale.ROOT, "[%s+0HOURS TO %s+3HOURS}",baseDate,baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']",
"//result/doc[2]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']",
"//result/doc[3]/date[@name='" + fieldName + "'][.='1995-12-31T12:59:59Z']");
assertQ(req("q", fieldName + ":"+ String.format(Locale.ROOT, "{%s+0HOURS TO %s+3HOURS}",baseDate,baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='2']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']",
"//result/doc[2]/date[@name='" + fieldName + "'][.='1995-12-31T12:59:59Z']");
assertQ(req("q", fieldName + ":" + String.format(Locale.ROOT, "{%s+0HOURS TO *}",baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='9']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']");
assertQ(req("q", fieldName + ":" + String.format(Locale.ROOT, "{* TO %s+3HOURS}",baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']");
assertQ(req("q", fieldName + ":" + String.format(Locale.ROOT, "[* TO %s+3HOURS}",baseDate),
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='3']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']");
assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']",
"//result/doc[10]/date[@name='" + fieldName + "'][.='1995-12-31T19:59:59Z']");
assertQ(req("q", fieldName + ":" + String.format(Locale.ROOT, "[%s+0HOURS TO %s+1HOURS]",baseDate,baseDate)
+ " OR " + fieldName + ":" + String.format(Locale.ROOT, "[%s+8HOURS TO %s+9HOURS]",baseDate,baseDate) ,
"fl", "id, " + fieldName, "sort", "id asc"),
"//*[@numFound='4']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']",
"//result/doc[2]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']",
"//result/doc[3]/date[@name='" + fieldName + "'][.='1995-12-31T18:59:59Z']",
"//result/doc[4]/date[@name='" + fieldName + "'][.='1995-12-31T19:59:59Z']");
assertQ(req("q", fieldName + ":"+String.format(Locale.ROOT, "[%s+0HOURS TO %s+1HOURS]",baseDate,baseDate)
+" AND " + fieldName + ":"+String.format(Locale.ROOT, "[%s+1HOURS TO %s+2HOURS]",baseDate,baseDate) , "fl", "id, " + fieldName),
"//*[@numFound='1']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T11:59:59Z']");
assertQ(req("q", fieldName + ":"+String.format(Locale.ROOT, "[%s+0HOURS TO %s+1HOURS]",baseDate,baseDate)
+" AND NOT " + fieldName + ":"+String.format(Locale.ROOT, "[%s+1HOURS TO %s+2HOURS]",baseDate,baseDate) , "fl", "id, " + fieldName),
"//*[@numFound='1']",
"//result/doc[1]/date[@name='" + fieldName + "'][.='1995-12-31T10:59:59Z']");
clearIndex();
assertU(commit());
}
private void doTestDatePointFieldRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
String baseDate = "1995-01-10T10:59:59Z";
for (int i = 0; i < 10; i++) {
String date = String.format(Locale.ROOT, "%s+%dDAYS", baseDate, i);
assertU(adoc("id", String.valueOf(i), docValuesField, date, nonDocValuesField, date));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+10DAYS", "facet.range.gap", "+2DAYS"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-08T10:59:59Z'][.='0']");
assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+10DAYS", "facet.range.gap", "+2DAYS", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-08T10:59:59Z'][.='0']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
// Range Faceting with method = filter should work
assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+10DAYS", "facet.range.gap", "+2DAYS", "facet.range.method", "filter"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-08T10:59:59Z'][.='0']");
// this should actually use filter method instead of dv
assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+10DAYS", "facet.range.gap", "+2DAYS", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-08T10:59:59Z'][.='0']");
}
private void doTestDatePointFieldMultiValuedRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
String baseDate = "1995-01-10T10:59:59Z";
for (int i = 0; i < 10; i++) {
String date1 = String.format(Locale.ROOT, "%s+%dDAYS", baseDate, i);
String date2 = String.format(Locale.ROOT, "%s+%dDAYS", baseDate, i+10);
assertU(adoc("id", String.valueOf(i), docValuesField, date1, docValuesField, date2,
nonDocValuesField, date1, nonDocValuesField, date2));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+20DAYS", "facet.range.gap", "+2DAYS"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-20T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-22T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-24T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-26T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-28T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1994-12-31T10:59:59Z'][.='0']");
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+20DAYS", "facet.range.gap", "+2DAYS", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-20T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-22T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-24T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-26T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-28T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1994-12-31T10:59:59Z'][.='0']");
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", docValuesField, "facet.range.start", "1995-01-10T10:59:59Z",
"facet.range.end", "1995-01-10T10:59:59Z+20DAYS", "facet.range.gap", "+100DAYS"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='10']");
assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
// Range Faceting with method = filter should work
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+20DAYS", "facet.range.gap", "+2DAYS", "facet.range.method", "filter"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-20T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-22T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-24T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-26T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-28T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1994-12-31T10:59:59Z'][.='0']");
// this should actually use filter method instead of dv
assertQ(req("q", "*:*", "fl", "id", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "1995-01-10T10:59:59Z-10DAYS",
"facet.range.end", "1995-01-10T10:59:59Z+20DAYS", "facet.range.gap", "+2DAYS", "facet.range.method", "dv"),
"//*[@numFound='10']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-10T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-12T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-14T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-16T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-18T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-20T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-22T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-24T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-26T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1995-01-28T10:59:59Z'][.='2']",
"//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='1994-12-31T10:59:59Z'][.='0']");
}
private void doTestDatePointFunctionQuery(String field, String nonDvFieldName) throws Exception {
final String baseDate = "1995-01-10T10:59:10Z";
for (int i = 9; i >= 0; i--) {
String date = String.format(Locale.ROOT, "%s+%dSECONDS", baseDate, i+1);
assertU(adoc("id", String.valueOf(i), field, date));
}
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof DatePointField);
assertQ(req("q", "*:*", "fl", "id, " + field, "sort", "product(-1,ms(" + field + ")) asc"),
"//*[@numFound='10']",
"//result/doc[1]/date[@name='" + field + "'][.='1995-01-10T10:59:20Z']",
"//result/doc[2]/date[@name='" + field + "'][.='1995-01-10T10:59:19Z']",
"//result/doc[3]/date[@name='" + field + "'][.='1995-01-10T10:59:18Z']",
"//result/doc[10]/date[@name='" + field + "'][.='1995-01-10T10:59:11Z']");
assertQ(req("q", "*:*", "fl", "id, " + field + ", ms(" + field + ","+baseDate+")", "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/float[@name='ms(" + field + "," + baseDate + ")'][.='1000.0']",
"//result/doc[2]/float[@name='ms(" + field + "," + baseDate + ")'][.='2000.0']",
"//result/doc[3]/float[@name='ms(" + field + "," + baseDate + ")'][.='3000.0']",
"//result/doc[10]/float[@name='ms(" + field + "," + baseDate + ")'][.='10000.0']");
assertQ(req("q", "*:*", "fl", "id, " + field + ", field(" + field + ")", "sort", "id asc"),
"//*[@numFound='10']",
"//result/doc[1]/date[@name='field(" + field + ")'][.='1995-01-10T10:59:11Z']",
"//result/doc[2]/date[@name='field(" + field + ")'][.='1995-01-10T10:59:12Z']",
"//result/doc[3]/date[@name='field(" + field + ")'][.='1995-01-10T10:59:13Z']",
"//result/doc[10]/date[@name='field(" + field + ")'][.='1995-01-10T10:59:20Z']");
}
private void testDatePointStats(String field, String dvField, String[] dates) {
for (int i = 0; i < dates.length; i++) {
assertU(adoc("id", String.valueOf(i), dvField, dates[i], field, dates[i]));
}
assertU(adoc("id", String.valueOf(dates.length)));
assertU(commit());
assertTrue(h.getCore().getLatestSchema().getField(dvField).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(dvField).getType() instanceof PointField);
assertQ(req("q", "*:*", "fl", "id, " + dvField, "stats", "true", "stats.field", dvField),
"//*[@numFound='11']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/date[@name='min'][.='" + dates[0] + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/date[@name='max'][.='" + dates[dates.length-1] + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/long[@name='count'][.='" + dates.length + "']",
"//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/long[@name='missing'][.='1']");
assertFalse(h.getCore().getLatestSchema().getField(field).hasDocValues());
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
assertQEx("Expecting Exception",
"Can't calculate stats on a PointField without docValues",
req("q", "*:*", "fl", "id, " + field, "stats", "true", "stats.field", field),
SolrException.ErrorCode.BAD_REQUEST);
}
private void testDatePointFieldsAtomicUpdates(String field, String type) throws Exception {
String date = "1995-01-10T10:59:10Z";
assertU(adoc(sdoc("id", "1", field, date)));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='"+date+"']");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", date+"+2DAYS"))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/" + type + "[@name='" + field + "'][.='1995-01-12T10:59:10Z']");
}
private void testMultiValuedDatePointFieldsAtomicUpdates(String field, String type) throws Exception {
String date1 = "1995-01-10T10:59:10Z";
String date2 = "1995-01-11T10:59:10Z";
String date3 = "1995-01-12T10:59:10Z";
assertU(adoc(sdoc("id", "1", field, date1)));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date1+"']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=1");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("add", date2))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date1+"']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date2+"']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=2");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("remove", date1))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date2+"']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=1");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("set", ImmutableList.of(date1, date2, date3)))));
assertU(commit());
assertQ(req("q", "id:1"),
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date1+"']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date2+"']",
"//result/doc[1]/arr[@name='" + field + "']/" + type + "[.='"+date3+"']",
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=3");
assertU(adoc(sdoc("id", "1", field, ImmutableMap.of("removeregex", ".*"))));
assertU(commit());
assertQ(req("q", "id:1"),
"count(//result/doc[1]/arr[@name='" + field + "']/" + type + ")=0");
}
private void doTestInternals(String field, String[] values) throws IOException {
assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
for (int i=0; i < 10; i++) {
assertU(adoc("id", String.valueOf(i), field, values[i]));
}
assertU(commit());
IndexReader ir;
RefCounted<SolrIndexSearcher> ref = null;
SchemaField sf = h.getCore().getLatestSchema().getField(field);
boolean ignoredField = !(sf.indexed() || sf.stored() || sf.hasDocValues());
try {
ref = h.getCore().getSearcher();
SolrIndexSearcher searcher = ref.get();
ir = searcher.getIndexReader();
// our own SlowCompositeReader to check DocValues on disk w/o the UninvertingReader added by SolrIndexSearcher
final LeafReader leafReaderForCheckingDVs = SlowCompositeReaderWrapper.wrap(searcher.getRawReader());
if (sf.indexed()) {
assertEquals("Field " + field + " should have point values", 10, PointValues.size(ir, field));
} else {
assertEquals("Field " + field + " should have no point values", 0, PointValues.size(ir, field));
}
if (ignoredField) {
assertTrue("Field " + field + " should not have docValues",
DocValues.getSortedNumeric(leafReaderForCheckingDVs, field).nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
assertTrue("Field " + field + " should not have docValues",
DocValues.getNumeric(leafReaderForCheckingDVs, field).nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
assertTrue("Field " + field + " should not have docValues",
DocValues.getSorted(leafReaderForCheckingDVs, field).nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
assertTrue("Field " + field + " should not have docValues",
DocValues.getBinary(leafReaderForCheckingDVs, field).nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
} else {
if (sf.hasDocValues()) {
if (sf.multiValued()) {
assertFalse("Field " + field + " should have docValues",
DocValues.getSortedNumeric(leafReaderForCheckingDVs, field).nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
} else {
assertFalse("Field " + field + " should have docValues",
DocValues.getNumeric(leafReaderForCheckingDVs, field).nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
}
} else {
expectThrows(IllegalStateException.class, ()->DocValues.getSortedNumeric(leafReaderForCheckingDVs, field));
expectThrows(IllegalStateException.class, ()->DocValues.getNumeric(leafReaderForCheckingDVs, field));
}
expectThrows(IllegalStateException.class, ()->DocValues.getSorted(leafReaderForCheckingDVs, field));
expectThrows(IllegalStateException.class, ()->DocValues.getBinary(leafReaderForCheckingDVs, field));
}
for (LeafReaderContext leave:ir.leaves()) {
LeafReader reader = leave.reader();
for (int i = 0; i < reader.numDocs(); i++) {
Document doc = reader.document(i);
if (sf.stored()) {
assertNotNull("Field " + field + " not found. Doc: " + doc, doc.get(field));
} else {
assertNull(doc.get(field));
}
}
}
} finally {
ref.decref();
}
clearIndex();
assertU(commit());
}
public void testNonReturnable() throws Exception {
doTestReturnNonStored("foo_p_i_ni_ns", false, "42");
doTestReturnNonStored("foo_p_i_ni_dv_ns", true, "42");
doTestReturnNonStored("foo_p_i_ni_ns_mv", false, "42", "666");
doTestReturnNonStored("foo_p_i_ni_dv_ns_mv", true, "42", "666");
doTestReturnNonStored("foo_p_l_ni_ns", false, "3333333333");
doTestReturnNonStored("foo_p_l_ni_dv_ns", true, "3333333333");
doTestReturnNonStored("foo_p_l_ni_ns_mv", false, "3333333333", "-4444444444");
doTestReturnNonStored("foo_p_l_ni_dv_ns_mv", true, "3333333333", "-4444444444");
doTestReturnNonStored("foo_p_f_ni_ns", false, "42.3");
doTestReturnNonStored("foo_p_f_ni_dv_ns", true, "42.3");
doTestReturnNonStored("foo_p_f_ni_ns_mv", false, "42.3", "-66.6");
doTestReturnNonStored("foo_p_f_ni_dv_ns_mv", true, "42.3", "-66.6");
doTestReturnNonStored("foo_p_d_ni_ns", false, "42.3");
doTestReturnNonStored("foo_p_d_ni_dv_ns", true, "42.3");
doTestReturnNonStored("foo_p_d_ni_ns_mv", false, "42.3", "-66.6");
doTestReturnNonStored("foo_p_d_ni_dv_ns_mv", true, "42.3", "-66.6");
doTestReturnNonStored("foo_p_dt_ni_ns", false, "1995-12-31T23:59:59Z");
doTestReturnNonStored("foo_p_dt_ni_dv_ns", true, "1995-12-31T23:59:59Z");
doTestReturnNonStored("foo_p_dt_ni_ns_mv", false, "1995-12-31T23:59:59Z", "2000-12-31T23:59:59Z+3DAYS");
doTestReturnNonStored("foo_p_dt_ni_dv_ns_mv", true, "1995-12-31T23:59:59Z", "2000-12-31T23:59:59Z+3DAYS");
}
public void doTestReturnNonStored(final String fieldName, boolean shouldReturnFieldIfRequested, final String... values) throws Exception {
final String RETURN_FIELD = "count(//doc/*[@name='" + fieldName + "'])=10";
final String DONT_RETURN_FIELD = "count(//doc/*[@name='" + fieldName + "'])=0";
assertFalse(h.getCore().getLatestSchema().getField(fieldName).stored());
for (int i=0; i < 10; i++) {
SolrInputDocument doc = sdoc("id", String.valueOf(i));
for (String value : values) {
doc.addField(fieldName, value);
}
assertU(adoc(doc));
}
assertU(commit());
assertQ(req("q", "*:*", "rows", "100", "fl", "id," + fieldName),
"//*[@numFound='10']",
"count(//doc)=10", // exactly 10 docs in response
(shouldReturnFieldIfRequested?RETURN_FIELD:DONT_RETURN_FIELD)); // no field in any doc other then 'id'
assertQ(req("q", "*:*", "rows", "100", "fl", "*"),
"//*[@numFound='10']",
"count(//doc)=10", // exactly 10 docs in response
DONT_RETURN_FIELD); // no field in any doc other then 'id'
assertQ(req("q", "*:*", "rows", "100"),
"//*[@numFound='10']",
"count(//doc)=10", // exactly 10 docs in response
DONT_RETURN_FIELD); // no field in any doc other then 'id'
clearIndex();
assertU(commit());
}
public void testWhiteboxCreateFields() throws Exception {
String[] typeNames = new String[]{"i", "l", "f", "d", "dt"};
String[] suffixes = new String[]{"", "_dv", "_mv", "_mv_dv", "_ni", "_ni_dv", "_ni_dv_ns", "_ni_dv_ns_mv", "_ni_mv", "_ni_mv_dv", "_ni_ns", "_ni_ns_mv", "_dv_ns", "_ni_ns_dv", "_dv_ns_mv"};
Class<?>[] expectedClasses = new Class[]{IntPoint.class, LongPoint.class, FloatPoint.class, DoublePoint.class, LongPoint.class};
Date dateToTest = new Date();
Object[][] values = new Object[][] {
{42, "42"},
{42, "42"},
{42.123, "42.123"},
{12345.6789, "12345.6789"},
{dateToTest, new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT).format(dateToTest), "NOW"} // "NOW" won't be equal to the other dates
};
Set<String> typesTested = new HashSet<>();
for (int i = 0; i < typeNames.length; i++) {
for (String suffix:suffixes) {
doWhiteboxCreateFields("whitebox_p_" + typeNames[i] + suffix, expectedClasses[i], values[i]);
typesTested.add("*_p_" + typeNames[i] + suffix);
}
}
Set<String> typesToTest = new HashSet<>();
for (DynamicField dynField:h.getCore().getLatestSchema().getDynamicFields()) {
if (dynField.getPrototype().getType() instanceof PointField) {
typesToTest.add(dynField.getRegex());
}
}
assertEquals("Missing types in the test", typesTested, typesToTest);
}
/**
* Calls {@link #callAndCheckCreateFields} on each of the specified values.
* This is a convinience method for testing the same fieldname with multiple inputs.
*
* @see #callAndCheckCreateFields
*/
private void doWhiteboxCreateFields(final String fieldName, final Class<?> pointType, final Object... values) throws Exception {
for (Object value : values) {
// ideally we should require that all input values be diff forms of the same logical value
// (ie '"42"' vs 'new Integer(42)') and assert that each produces an equivilent list of IndexableField objects
// but that doesn't seem to work -- appears not all IndexableField classes override Object.equals?
final List<IndexableField> result = callAndCheckCreateFields(fieldName, pointType, value);
assertNotNull(value + " => null", result);
}
}
/**
* Calls {@link SchemaField#createFields} on the specified value for the specified field name, and asserts
* that the results match the SchemaField propeties, with an additional check that the <code>pointType</code>
* is included if and only if the SchemaField is "indexed"
*/
private List<IndexableField> callAndCheckCreateFields(final String fieldName, final Class<?> pointType, final Object value) throws Exception {
final SchemaField sf = h.getCore().getLatestSchema().getField(fieldName);
final List<IndexableField> results = sf.createFields(value);
final Set<IndexableField> resultSet = new LinkedHashSet<>(results);
assertEquals("duplicates found in results? " + results.toString(),
results.size(), resultSet.size());
final Set<Class<?>> resultClasses = new HashSet<>();
for (IndexableField f : results) {
resultClasses.add(f.getClass());
if (!sf.hasDocValues() ) {
assertFalse(f.toString(),
(f instanceof NumericDocValuesField) ||
(f instanceof SortedNumericDocValuesField));
}
}
assertEquals(fieldName + " stored? Result Fields: " + Arrays.toString(results.toArray()),
sf.stored(), resultClasses.contains(StoredField.class));
assertEquals(fieldName + " indexed? Result Fields: " + Arrays.toString(results.toArray()),
sf.indexed(), resultClasses.contains(pointType));
if (sf.multiValued()) {
assertEquals(fieldName + " docvalues? Result Fields: " + Arrays.toString(results.toArray()),
sf.hasDocValues(), resultClasses.contains(SortedNumericDocValuesField.class));
} else {
assertEquals(fieldName + " docvalues? Result Fields: " + Arrays.toString(results.toArray()),
sf.hasDocValues(), resultClasses.contains(NumericDocValuesField.class));
}
return results;
}
}