You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by tf...@apache.org on 2017/01/19 01:28:05 UTC
[1/4] lucene-solr:master: SOLR-8396: Add support for PointFields in
Solr
Repository: lucene-solr
Updated Branches:
refs/heads/master a89560bb7 -> 57934ba44
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
index d8f3ae5..95c403a 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
@@ -34,6 +34,7 @@ import org.apache.lucene.util.LuceneTestCase;
import org.apache.solr.JSONTestUtil;
import org.apache.solr.SolrTestCaseHS;
import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.request.macro.MacroExpander;
import org.junit.AfterClass;
@@ -41,6 +42,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
@LuceneTestCase.SuppressCodecs({"Lucene3x","Lucene40","Lucene41","Lucene42","Lucene45","Appending"})
+@SuppressPointFields
public class TestJsonFacets extends SolrTestCaseHS {
private static SolrInstances servers; // for distributed testing
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 61de56d..59e74d90 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -167,11 +167,18 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
public static final String SYSTEM_PROPERTY_SOLR_TESTS_USEMERGEPOLICYFACTORY = "solr.tests.useMergePolicyFactory";
@Deprecated // remove solr.tests.useMergePolicy use with SOLR-8668
public static final String SYSTEM_PROPERTY_SOLR_TESTS_USEMERGEPOLICY = "solr.tests.useMergePolicy";
+
+ /**
+ * The system property {@code "solr.tests.preferPointFields"} can be used to make tests use PointFields when possible.
+ * PointFields will only be used if the schema used by the tests uses "${solr.tests.TYPEClass}" when defining fields.
+ * If this environment variable is not set, those tests will use PointFields 50% of the times and TrieFields the rest.
+ */
+ public static final boolean PREFER_POINT_FIELDS = Boolean.getBoolean("solr.tests.preferPointFields");
private static String coreName = DEFAULT_TEST_CORENAME;
public static int DEFAULT_CONNECTION_TIMEOUT = 60000; // default socket connection timeout in ms
-
+
protected void writeCoreProperties(Path coreDirectory, String corename) throws IOException {
Properties props = new Properties();
props.setProperty("name", corename);
@@ -215,6 +222,19 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
public String bugUrl();
}
+ /**
+ * Annotation for test classes that want to disable PointFields.
+ * PointFields will otherwise randomly used by some schemas.
+ */
+ @Documented
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface SuppressPointFields {
+ /** Point to JIRA entry. */
+ public String bugUrl() default "None";
+ }
+
// these are meant to be accessed sequentially, but are volatile just to ensure any test
// thread will read the latest value
protected static volatile SSLTestConfig sslConfig;
@@ -419,10 +439,12 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
lrf = h.getRequestFactory("standard", 0, 20, CommonParams.VERSION, "2.2");
}
- /** sets system properties based on
+ /**
+ * Sets system properties to allow generation of random configurations of
+ * solrconfig.xml and schema.xml.
+ * Sets properties used on
* {@link #newIndexWriterConfig(org.apache.lucene.analysis.Analyzer)}
- *
- * configs can use these system properties to vary the indexwriter settings
+ * and base schema.xml (Point Fields)
*/
public static void newRandomConfig() {
IndexWriterConfig iwc = newIndexWriterConfig(new MockAnalyzer(random()));
@@ -438,6 +460,20 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
mergeSchedulerClass = "org.apache.lucene.index.ConcurrentMergeScheduler";
}
System.setProperty("solr.tests.mergeScheduler", mergeSchedulerClass);
+ if (RandomizedContext.current().getTargetClass().isAnnotationPresent(SuppressPointFields.class)
+ || (!PREFER_POINT_FIELDS && random().nextBoolean())) {
+ log.info("Using TrieFields");
+ System.setProperty("solr.tests.intClass", "int");
+ System.setProperty("solr.tests.longClass", "long");
+ System.setProperty("solr.tests.doubleClass", "double");
+ System.setProperty("solr.tests.floatClass", "float");
+ } else {
+ log.info("Using PointFields");
+ System.setProperty("solr.tests.intClass", "pint");
+ System.setProperty("solr.tests.longClass", "plong");
+ System.setProperty("solr.tests.doubleClass", "pdouble");
+ System.setProperty("solr.tests.floatClass", "pfloat");
+ }
}
public static Throwable getWrappedException(Throwable e) {
[2/4] lucene-solr:master: SOLR-8396: Add support for PointFields in
Solr
Posted by tf...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
new file mode 100644
index 0000000..12f1504
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
@@ -0,0 +1,1472 @@
+/*
+ * 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.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.schema.DoublePointField;
+import org.apache.solr.schema.IntPointField;
+import org.apache.solr.schema.PointField;
+import org.apache.solr.schema.SchemaField;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+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_ni_dv", false);
+ // uncomment once MultiValued docValues are supported in PointFields
+ // doTestIntPointFieldExactQuery("number_p_i_ni_mv_dv", false);
+ }
+
+ @Test
+ public void testIntPointFieldReturn() throws Exception {
+ testPointFieldReturn("number_p_i", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
+ clearIndex();
+ assertU(commit());
+ testPointFieldReturn("number_p_i_dv_ns", "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);
+ }
+
+ @Test
+ public void testIntPointFieldSort() throws Exception {
+ doTestPointFieldSort("number_p_i", "number_p_i_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"});
+ }
+
+ @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 testIntPointFunctionQuery() throws Exception {
+ doTestIntPointFunctionQuery("number_p_i_dv", "number_p_i", "int");
+ }
+
+
+ @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);
+ }
+
+ @Test
+ public void testIntPointFieldMultiValuedExactQuery() throws Exception {
+ testPointFieldMultiValuedExactQuery("number_p_i_mv", getSequentialStringArrayWithInts(20));
+ }
+
+ @Test
+ public void testIntPointFieldMultiValuedReturn() throws Exception {
+ testPointFieldMultiValuedReturn("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
+ }
+
+ @Test
+ public void testIntPointFieldMultiValuedRangeQuery() throws Exception {
+ testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
+ }
+
+ //TODO MV SORT?
+ @Test
+ @Ignore("Enable once MultiValued docValues are supported in PointFields")
+ public void testIntPointFieldMultiValuedFacetField() throws Exception {
+ testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", getSequentialStringArrayWithInts(20));
+ }
+
+ @Test
+ @Ignore("Enable once MultiValued docValues are supported in PointFields")
+ public void testIntPointFieldMultiValuedRangeFacet() throws Exception {
+ String docValuesField = "number_p_i_mv_dv";
+ String nonDocValuesField = "number_p_i_mv";
+
+ 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 IntPointField);
+ 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 IntPointField);
+ // 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']");
+ }
+
+ @Test
+ @Ignore("Enable once MultiValued docValues are supported in PointFields")
+ 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 testIntPointSetQuery() throws Exception {
+ doTestSetQueries("number_p_i", getRandomStringArrayWithInts(10, false), false);
+ doTestSetQueries("number_p_i_mv", getRandomStringArrayWithInts(10, false), true);
+ doTestSetQueries("number_p_i_ni_dv", getRandomStringArrayWithInts(10, 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_ni_dv");
+ // TODO enable once MuultiValued docValues are supported with PointFields
+// doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv");
+ }
+
+ @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"});
+ clearIndex();
+ assertU(commit());
+ 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"});
+ clearIndex();
+ assertU(commit());
+ 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);
+ }
+
+ @Test
+ public void testDoublePointFieldSort() throws Exception {
+ String[] arr = getRandomStringArrayWithDoubles(10, true);
+ doTestPointFieldSort("number_p_d", "number_p_d_dv", arr);
+ }
+
+ @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 testDoublePointFunctionQuery() throws Exception {
+ doTestFloatPointFunctionQuery("number_p_d_dv", "number_p_d", "double");
+ }
+
+ @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);
+ }
+
+ @Test
+ public void testDoublePointFieldMultiValuedExactQuery() throws Exception {
+ testPointFieldMultiValuedExactQuery("number_p_d_mv", getRandomStringArrayWithDoubles(20, false));
+ }
+
+ @Test
+ public void testDoublePointFieldMultiValuedReturn() throws Exception {
+ testPointFieldMultiValuedReturn("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
+ }
+
+ @Test
+ public void testDoublePointFieldMultiValuedRangeQuery() throws Exception {
+ testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
+ }
+
+ @Test
+ @Ignore("Enable once MultiValued docValues are supported in PointFields")
+ 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
+ @Ignore("Enable once MultiValued docValues are supported in PointFields")
+ public void testDoublePointFieldMultiValuedRangeFacet() throws Exception {
+ String docValuesField = "number_p_d_mv_dv";
+ String nonDocValuesField = "number_p_d_mv";
+
+ 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 DoublePointField);
+ 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 DoublePointField);
+ // 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']");
+ }
+
+ @Test
+ @Ignore("Enable once MultiValued docValues are supported in PointFields")
+ 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");
+ }
+
+ 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(10, false), false);
+ doTestSetQueries("number_p_d_mv", getRandomStringArrayWithDoubles(10, false), true);
+ doTestSetQueries("number_p_d_ni_dv", getRandomStringArrayWithDoubles(10, false), false);
+ }
+
+ // Float
+
+
+ @Test
+ public void testFloatPointFieldExactQuery() throws Exception {
+ doTestFloatPointFieldExactQuery("number_p_f");
+ doTestFloatPointFieldExactQuery("number_p_f_mv");
+ doTestFloatPointFieldExactQuery("number_p_f_ni_dv");
+// doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv");
+ }
+
+ @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"});
+ clearIndex();
+ assertU(commit());
+ 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"});
+ clearIndex();
+ assertU(commit());
+ 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);
+ }
+
+ @Test
+ public void testFloatPointFieldSort() throws Exception {
+ String[] arr = getRandomStringArrayWithFloats(10, true);
+ doTestPointFieldSort("number_p_f", "number_p_f_dv", arr);
+ }
+
+ @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 testFloatPointFunctionQuery() throws Exception {
+ doTestFloatPointFunctionQuery("number_p_f_dv", "number_p_f", "float");
+ }
+
+ @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);
+ }
+
+ @Test
+ public void testFloatPointFieldMultiValuedExactQuery() throws Exception {
+ testPointFieldMultiValuedExactQuery("number_p_f_mv", getRandomStringArrayWithFloats(20, false));
+ }
+
+ @Test
+ public void testFloatPointFieldMultiValuedReturn() throws Exception {
+ testPointFieldMultiValuedReturn("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
+ }
+
+ @Test
+ public void testFloatPointFieldMultiValuedRangeQuery() throws Exception {
+ testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
+ }
+
+ @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 testFloatPointSetQuery() throws Exception {
+ doTestSetQueries("number_p_f", getRandomStringArrayWithFloats(10, false), false);
+ doTestSetQueries("number_p_f_mv", getRandomStringArrayWithFloats(10, false), true);
+ doTestSetQueries("number_p_f_ni_dv", getRandomStringArrayWithFloats(10, false), false);
+ }
+
+ // Long
+
+ @Test
+ public void testLongPointFieldExactQuery() throws Exception {
+ doTestIntPointFieldExactQuery("number_p_l", true);
+ doTestIntPointFieldExactQuery("number_p_l_mv", true);
+ doTestIntPointFieldExactQuery("number_p_l_ni_dv", true);
+// doTestIntPointFieldExactQuery("number_p_i_ni_mv_dv", true);
+ }
+
+ @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)});
+ clearIndex();
+ assertU(commit());
+ 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);
+ }
+
+ @Test
+ public void testLongPointFieldSort() throws Exception {
+ doTestPointFieldSort("number_p_l", "number_p_l_dv", new String[]{String.valueOf(Integer.MIN_VALUE),
+ "1", "2", "3", "4", "5", "6", "7",
+ String.valueOf(Integer.MAX_VALUE), String.valueOf(Long.MAX_VALUE)});
+ }
+
+ @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 testLongPointFunctionQuery() throws Exception {
+ doTestIntPointFunctionQuery("number_p_l_dv", "number_p_l", "long");
+ }
+
+ @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);
+ }
+
+ @Test
+ public void testLongPointFieldMultiValuedExactQuery() throws Exception {
+ testPointFieldMultiValuedExactQuery("number_p_l_mv", getSequentialStringArrayWithInts(20));
+ }
+
+ @Test
+ public void testLongPointFieldMultiValuedReturn() throws Exception {
+ testPointFieldMultiValuedReturn("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
+ }
+
+ @Test
+ public void testLongPointFieldMultiValuedRangeQuery() throws Exception {
+ testPointFieldMultiValuedRangeQuery("number_p_l_mv", "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 testLongPointSetQuery() throws Exception {
+ doTestSetQueries("number_p_l", getRandomStringArrayWithLongs(10, false), false);
+ doTestSetQueries("number_p_l_mv", getRandomStringArrayWithLongs(10, false), true);
+ doTestSetQueries("number_p_l_ni_dv", getRandomStringArrayWithLongs(10, false), false);
+ }
+
+ // Helper methods
+
+ 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[] 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 void doTestIntPointFieldExactQuery(String field, boolean testLong) throws Exception {
+ 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),
+ "//*[@numFound='1']");
+ }
+
+ for (int i = 0; i < 10; i++) {
+ assertQ(req("q", field + ":" + (i+1) + " OR " + field + ":" + ((i+1)%10 + 1)), "//*[@numFound='2']");
+ }
+
+ 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),
+ "//*[@numFound='1']");
+
+ 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),
+ "//*[@numFound='1']");
+ }
+ 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),
+ "//*[@numFound='1']");
+ }
+
+ 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]));
+ }
+ assertU(commit());
+ String[] expected = new String[values.length + 1];
+ expected[0] = "//*[@numFound='" + values.length + "']";
+ for (int i = 1; i <= values.length; i++) {
+ expected[i] = "//result/doc[" + i + "]/" + type + "[@name='" + field + "'][.='" + values[i-1] + "']";
+ }
+ assertQ(req("q", "*:*", "fl", "id, " + field, "rows", String.valueOf(values.length)), expected);
+ }
+
+ private void doTestIntPointFieldRangeQuery(String fieldName, String type, boolean testLong) throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertU(adoc("id", String.valueOf(i), fieldName, String.valueOf(i)));
+ }
+ assertU(commit());
+ assertQ(req("q", fieldName + ":[0 TO 3]", "fl", "id, " + fieldName),
+ "//*[@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),
+ "//*[@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),
+ "//*[@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),
+ "//*[@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),
+ "//*[@numFound='9']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1']");
+
+ assertQ(req("q", fieldName + ":{* TO 3}", "fl", "id, " + fieldName),
+ "//*[@numFound='3']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']");
+
+ assertQ(req("q", fieldName + ":[* TO 3}", "fl", "id, " + fieldName),
+ "//*[@numFound='3']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']");
+
+ assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName),
+ "//*[@numFound='10']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0']",
+ "//result/doc[10]/" + type + "[@name='" + fieldName + "'][.='9']");
+
+ clearIndex();
+ assertU(commit());
+
+ String[] arr;
+ if (testLong) {
+ arr = getRandomStringArrayWithLongs(10, true);
+ } else {
+ arr = getRandomStringArrayWithInts(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 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']");
+
+ 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 dvFieldName, String nonDvFieldName, String type) throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertU(adoc("id", String.valueOf(i), dvFieldName, String.valueOf(i), nonDvFieldName, String.valueOf(i)));
+ }
+ assertU(commit());
+ assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).hasDocValues());
+ assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).getType() instanceof PointField);
+ assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "sort", "product(-1," + dvFieldName + ") asc"),
+ "//*[@numFound='10']",
+ "//result/doc[1]/" + type + "[@name='" + dvFieldName + "'][.='9']",
+ "//result/doc[2]/" + type + "[@name='" + dvFieldName + "'][.='8']",
+ "//result/doc[3]/" + type + "[@name='" + dvFieldName + "'][.='7']",
+ "//result/doc[10]/" + type + "[@name='" + dvFieldName + "'][.='0']");
+
+ assertQ(req("q", "*:*", "fl", "id, " + dvFieldName + ", product(-1," + dvFieldName + ")"),
+ "//*[@numFound='10']",
+ "//result/doc[1]/float[@name='product(-1," + dvFieldName + ")'][.='-0.0']",
+ "//result/doc[2]/float[@name='product(-1," + dvFieldName + ")'][.='-1.0']",
+ "//result/doc[3]/float[@name='product(-1," + dvFieldName + ")'][.='-2.0']",
+ "//result/doc[10]/float[@name='product(-1," + dvFieldName + ")'][.='-9.0']");
+
+ assertQ(req("q", "*:*", "fl", "id, " + dvFieldName + ", field(" + dvFieldName + ")"),
+ "//*[@numFound='10']",
+ "//result/doc[1]/" + type + "[@name='field(" + dvFieldName + ")'][.='0']",
+ "//result/doc[2]/" + type + "[@name='field(" + dvFieldName + ")'][.='1']",
+ "//result/doc[3]/" + type + "[@name='field(" + dvFieldName + ")'][.='2']",
+ "//result/doc[10]/" + type + "[@name='field(" + dvFieldName + ")'][.='9']");
+
+ assertFalse(h.getCore().getLatestSchema().getField(nonDvFieldName).hasDocValues());
+ assertTrue(h.getCore().getLatestSchema().getField(nonDvFieldName).getType() instanceof PointField);
+
+ assertQEx("Expecting Exception",
+ "sort param could not be parsed as a query",
+ req("q", "*:*", "fl", "id, " + nonDvFieldName, "sort", "product(-1," + nonDvFieldName + ") asc"),
+ 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(String fieldName, 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=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++) {
+ assertQ(req("q", fieldName + ":" + numbers[i].replace("-", "\\-")),
+ "//*[@numFound='1']");
+ }
+
+ for (int i = 0; i < 20; i++) {
+ assertQ(req("q", fieldName + ":" + numbers[i].replace("-", "\\-") + " OR " + fieldName + ":" + numbers[(i+1)%10].replace("-", "\\-")), "//*[@numFound='2']");
+ }
+ }
+
+ 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=0; i < 10; i++) {
+ assertU(adoc("id", String.valueOf(i), fieldName, numbers[i], fieldName, numbers[i+10]));
+ }
+ assertU(commit());
+ String[] expected = new String[11];
+ String[] expected2 = new String[11];
+ expected[0] = "//*[@numFound='10']";
+ expected2[0] = "//*[@numFound='10']";
+ for (int i = 1; i <= 10; i++) {
+ expected[i] = "//result/doc[" + i + "]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[i-1] + "']";
+ expected2[i] = "//result/doc[" + i + "]/arr[@name='" + fieldName + "']/" + type + "[2][.='" + numbers[i + 9] + "']";
+ }
+ assertQ(req("q", "*:*", "fl", "id, " + fieldName), expected);
+ assertQ(req("q", "*:*", "fl", "id, " + fieldName), expected2);
+ }
+
+ 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=0; i < 10; i++) {
+ assertU(adoc("id", String.valueOf(i), fieldName, String.valueOf(i), fieldName, String.valueOf(i+10)));
+ }
+ assertU(commit());
+ assertQ(req("q", fieldName + ":[0 TO 3]", "fl", "id, " + fieldName),
+ "//*[@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", fieldName + ":{0 TO 3]", "fl", "id, " + fieldName),
+ "//*[@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", fieldName + ":[0 TO 3}", "fl", "id, " + fieldName),
+ "//*[@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", fieldName + ":{0 TO 3}", "fl", "id, " + fieldName),
+ "//*[@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", fieldName + ":{0 TO *}", "fl", "id, " + fieldName),
+ "//*[@numFound='10']",
+ "//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
+
+ assertQ(req("q", fieldName + ":{10 TO *}", "fl", "id, " + fieldName),
+ "//*[@numFound='9']",
+ "//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[1] + "']");
+
+ assertQ(req("q", fieldName + ":{* TO 3}", "fl", "id, " + fieldName),
+ "//*[@numFound='3']",
+ "//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
+
+ assertQ(req("q", fieldName + ":[* TO 3}", "fl", "id, " + fieldName),
+ "//*[@numFound='3']",
+ "//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']");
+
+ assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName),
+ "//*[@numFound='10']",
+ "//result/doc[1]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[0] + "']",
+ "//result/doc[10]/arr[@name='" + fieldName + "']/" + type + "[1][.='" + numbers[9] + "']");
+ }
+
+ 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]));
+ }
+ 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']");
+
+ 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 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] + "']");
+
+// if (dvIsRandomAccessOrds(docValuesField)) {
+// function = "field(" + docValuesField + ", max)";
+// assertQ(req("q", "*:*", "fl", "id, " + function),
+// "//*[@numFound='10']",
+// "//result/doc[1]/int[@name='" + function + "'][.='10']",
+// "//result/doc[2]/int[@name='" + function + "'][.='11']",
+// "//result/doc[3]/int[@name='" + function + "'][.='12']",
+// "//result/doc[10]/int[@name='" + function + "'][.='19']");
+// }
+
+ 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 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(String field) throws Exception {
+ 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),
+ "//*[@numFound='1']");
+ }
+
+ 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), "//*[@numFound='2']");
+ }
+
+ 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),
+ "//*[@numFound='1']");
+ }
+ clearIndex();
+ assertU(commit());
+ }
+
+ private void doTestPointFieldSort(String field, String dvField, String[] arr) throws Exception {
+ assert arr != null && arr.length == 10;
+ for (int i = 0; i < arr.length; i++) {
+ assertU(adoc("id", String.valueOf(i), dvField, String.valueOf(arr[i]), field, String.valueOf(arr[i])));
+ }
+ assertU(commit());
+ assertTrue(h.getCore().getLatestSchema().getField(dvField).hasDocValues());
+ assertTrue(h.getCore().getLatestSchema().getField(dvField).getType() instanceof PointField);
+ assertQ(req("q", "*:*", "fl", "id", "sort", dvField + " 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(field).hasDocValues());
+ assertTrue(h.getCore().getLatestSchema().getField(field).getType() instanceof PointField);
+ assertQEx("Expecting Exception",
+ "can not sort on a PointField without doc values: " + field,
+ req("q", "*:*", "fl", "id", "sort", field + " desc"),
+ SolrException.ErrorCode.BAD_REQUEST);
+
+ //TODO: sort missing
+ }
+
+ private void doTestFloatPointFieldRangeQuery(String fieldName, String type, boolean testDouble) throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertU(adoc("id", String.valueOf(i), fieldName, String.valueOf(i)));
+ }
+ assertU(commit());
+ assertQ(req("q", fieldName + ":[0 TO 3]", "fl", "id, " + fieldName),
+ "//*[@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),
+ "//*[@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),
+ "//*[@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),
+ "//*[@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),
+ "//*[@numFound='9']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='1.0']");
+
+ assertQ(req("q", fieldName + ":{* TO 3}", "fl", "id, " + fieldName),
+ "//*[@numFound='3']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']");
+
+ assertQ(req("q", fieldName + ":[* TO 3}", "fl", "id, " + fieldName),
+ "//*[@numFound='3']",
+ "//result/doc[1]/" + type + "[@name='" + fieldName + "'][.='0.0']");
+
+ assertQ(req("q", fieldName + ":[* TO *}", "fl", "id, " + fieldName),
+ "//*[@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 dvFieldName, String nonDvFieldName, String type) throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertU(adoc("id", String.valueOf(i), dvFieldName, String.format(Locale.ROOT, "%f", (float)i*1.1), nonDvFieldName, String.format(Locale.ROOT, "%f", (float)i*1.1)));
+ }
+ assertU(commit());
+ assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).hasDocValues());
+ assertTrue(h.getCore().getLatestSchema().getField(dvFieldName).getType() instanceof PointField);
+ assertQ(req("q", "*:*", "fl", "id, " + dvFieldName, "sort", "product(-1," + dvFieldName + ") asc"),
+ "//*[@numFound='10']",
+ "//result/doc[1]/" + type + "[@name='" + dvFieldName + "'][.='9.9']",
+ "//result/doc[2]/" + type + "[@name='" + dvFieldName + "'][.='8.8']",
+ "//result/doc[3]/" + type + "[@name='" + dvFieldName + "'][.='7.7']",
+ "//result/doc[10]/" + type + "[@name='" + dvFieldName + "'][.='0.0']");
+
+ assertQ(req("q", "*:*", "fl", "id, " + dvFieldName + ", product(-1," + dvFieldName + ")"),
+ "//*[@numFound='10']",
+ "//result/doc[1]/float[@name='product(-1," + dvFieldName + ")'][.='-0.0']",
+ "//result/doc[2]/float[@name='product(-1," + dvFieldName + ")'][.='-1.1']",
+ "//result/doc[3]/float[@name='product(-1," + dvFieldName + ")'][.='-2.2']",
+ "//result/doc[10]/float[@name='product(-1," + dvFieldName + ")'][.='-9.9']");
+
+ assertQ(req("q", "*:*", "fl", "id, " + dvFieldName + ", field(" + dvFieldName + ")"),
+ "//*[@numFound='10']",
+ "//result/doc[1]/" + type + "[@name='field(" + dvFieldName + ")'][.='0.0']",
+ "//result/doc[2]/" + type + "[@name='field(" + dvFieldName + ")'][.='1.1']",
+ "//result/doc[3]/" + type + "[@name='field(" + dvFieldName + ")'][.='2.2']",
+ "//result/doc[10]/" + type + "[@name='field(" + dvFieldName + ")'][.='9.9']");
+
+ assertFalse(h.getCore().getLatestSchema().getField(nonDvFieldName).hasDocValues());
+ assertTrue(h.getCore().getLatestSchema().getField(nonDvFieldName).getType() instanceof PointField);
+
+ assertQEx("Expecting Exception",
+ "sort param could not be parsed as a query",
+ req("q", "*:*", "fl", "id, " + nonDvFieldName, "sort", "product(-1," + nonDvFieldName + ") asc"),
+ SolrException.ErrorCode.BAD_REQUEST);
+ }
+
+ 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());
+ assertTrue(h.getCore().getLatestSchema().getField(fieldName).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']");
+ }
+
+ 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']");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/search/TestCollapseQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestCollapseQParserPlugin.java b/solr/core/src/test/org/apache/solr/search/TestCollapseQParserPlugin.java
index 7c5fc4a..2fca452 100644
--- a/solr/core/src/test/org/apache/solr/search/TestCollapseQParserPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/TestCollapseQParserPlugin.java
@@ -25,6 +25,7 @@ import java.util.Iterator;
import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
@@ -36,8 +37,9 @@ import org.junit.Test;
//We want codecs that support DocValues, and ones supporting blank/empty values.
@SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42"})
+@SuppressPointFields
public class TestCollapseQParserPlugin extends SolrTestCaseJ4 {
-
+
@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig-collapseqparser.xml", "schema11.xml");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java b/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java
index 6059528..610e998 100644
--- a/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java
@@ -46,7 +46,7 @@ public class TestMaxScoreQueryParser extends AbstractSolrTestCase {
assertEquals(new BoostQuery(new TermQuery(new Term("text", "foo")), 3f), q);
q = parse("price:[0 TO 10]");
- assertTrue(q instanceof LegacyNumericRangeQuery);
+ assertTrue(q instanceof LegacyNumericRangeQuery || q instanceof PointRangeQuery);
}
@Test
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/search/TestRandomCollapseQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestRandomCollapseQParserPlugin.java b/solr/core/src/test/org/apache/solr/search/TestRandomCollapseQParserPlugin.java
index f4dd449..7d135e2 100644
--- a/solr/core/src/test/org/apache/solr/search/TestRandomCollapseQParserPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/TestRandomCollapseQParserPlugin.java
@@ -24,6 +24,7 @@ import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.CursorPagingTest;
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
@@ -38,6 +39,7 @@ import org.junit.BeforeClass;
//We want codecs that support DocValues, and ones supporting blank/empty values.
@SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42"})
+@SuppressPointFields
public class TestRandomCollapseQParserPlugin extends SolrTestCaseJ4 {
/** Full SolrServer instance for arbitrary introspection of response data and adding fqs */
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
index 20c1907..37462d9 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
@@ -23,6 +23,7 @@ import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.PointInSetQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.search.TermQuery;
@@ -231,6 +232,13 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
qParser.setIsFilter(true); // this may change in the future
q = qParser.getQuery();
assertEquals(20, ((TermInSetQuery)q).getTermData().size());
+
+ // for point fields large filter query should use PointInSetQuery
+ qParser = QParser.getParser("foo_pi:(1 2 3 4 5 6 7 8 9 10 20 19 18 17 16 15 14 13 12 11)", req);
+ qParser.setIsFilter(true); // this may change in the future
+ q = qParser.getQuery();
+ assertTrue(q instanceof PointInSetQuery);
+ assertEquals(20, ((PointInSetQuery)q).getPackedPoints().size());
// a filter() clause inside a relevancy query should be able to use a TermsQuery
qParser = QParser.getParser("foo_s:aaa filter(foo_s:(a b c d e f g h i j k l m n o p q r s t u v w x y z))", req);
[3/4] lucene-solr:master: SOLR-8396: Add support for PointFields in
Solr
Posted by tf...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema-point.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-point.xml b/solr/core/src/test-files/solr/collection1/conf/schema-point.xml
new file mode 100644
index 0000000..ca37ff5
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-point.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+
+<schema name="example" version="1.6">
+ <types>
+ <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
+
+ <fieldType name="pint" class="solr.IntPointField"/>
+ <fieldType name="plong" class="solr.LongPointField"/>
+ <fieldType name="pdouble" class="solr.DoublePointField"/>
+ <fieldType name="pfloat" class="solr.FloatPointField"/>
+
+ <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true" omitNorms="true"/>
+ </types>
+
+
+ <fields>
+ <field name="id" type="string"/>
+ <field name="text" type="string"/>
+ <field name="_version_" type="long" indexed="true" stored="true" multiValued="false" />
+ <field name="signatureField" type="string" indexed="true" stored="false"/>
+ <dynamicField name="*_s" type="string" indexed="true" stored="true"/>
+ <dynamicField name="*_sS" type="string" indexed="false" stored="true"/>
+ <dynamicField name="*_i" type="int" indexed="true" stored="true"/>
+ <dynamicField name="*_l" type="long" indexed="true" stored="true"/>
+ <dynamicField name="*_f" type="float" indexed="true" stored="true"/>
+ <dynamicField name="*_d" type="double" indexed="true" stored="true"/>
+ <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
+
+ <dynamicField name="*_p_i" type="pint" indexed="true" stored="true"/>
+ <dynamicField name="*_p_i_dv" type="pint" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_p_i_mv" type="pint" indexed="true" stored="true" multiValued="true"/>
+ <dynamicField name="*_p_i_mv_dv" type="pint" indexed="true" stored="true" docValues="true" multiValued="true"/>
+ <dynamicField name="*_p_i_ni_dv" type="pint" indexed="false" stored="true" docValues="true"/>
+ <dynamicField name="*_p_i_ni_mv_dv" type="pint" indexed="false" stored="true" docValues="true" multiValued="true"/>
+
+ <dynamicField name="*_p_l" type="plong" indexed="true" stored="true"/>
+ <dynamicField name="*_p_l_dv" type="plong" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_p_l_mv" type="plong" indexed="true" stored="true" multiValued="true"/>
+ <dynamicField name="*_p_l_mv_dv" type="plong" indexed="true" stored="true" docValues="true" multiValued="true"/>
+ <dynamicField name="*_p_l_ni_dv" type="plong" indexed="false" stored="true" docValues="true"/>
+ <dynamicField name="*_p_l_ni_mv_dv" type="plong" indexed="false" stored="true" docValues="true" multiValued="true"/>
+
+ <dynamicField name="*_p_d" type="pdouble" indexed="true" stored="true"/>
+ <dynamicField name="*_p_d_dv" type="pdouble" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_p_d_mv" type="pdouble" indexed="true" stored="true" multiValued="true"/>
+ <dynamicField name="*_p_d_mv_dv" type="pdouble" indexed="true" stored="true" docValues="true" multiValued="true"/>
+ <dynamicField name="*_p_d_ni_dv" type="pdouble" indexed="false" stored="true" docValues="true"/>
+ <dynamicField name="*_p_d_ni_mv_dv" type="pdouble" indexed="false" stored="true" docValues="true" multiValued="true"/>
+
+ <dynamicField name="*_p_f" type="pfloat" indexed="true" stored="true"/>
+ <dynamicField name="*_p_f_dv" type="pfloat" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_p_f_mv" type="pfloat" indexed="true" stored="true" multiValued="true"/>
+ <dynamicField name="*_p_f_mv_dv" type="pfloat" indexed="true" stored="true" docValues="true" multiValued="true"/>
+ <dynamicField name="*_p_f_ni_dv" type="pfloat" indexed="false" stored="true" docValues="true"/>
+ <dynamicField name="*_p_f_ni_mv_dv" type="pfloat" indexed="false" stored="true" docValues="true" multiValued="true"/>
+
+ <!-- return DV fields as -->
+ <dynamicField name="*_p_i_dv_ns" type="pint" indexed="true" stored="false" docValues="true" useDocValuesAsStored="true"/>
+ <dynamicField name="*_p_l_dv_ns" type="plong" indexed="true" stored="false" docValues="true" useDocValuesAsStored="true"/>
+ <dynamicField name="*_p_d_dv_ns" type="pdouble" indexed="true" stored="false" docValues="true" useDocValuesAsStored="true"/>
+ <dynamicField name="*_p_f_dv_ns" type="pfloat" indexed="true" stored="false" docValues="true" useDocValuesAsStored="true"/>
+
+ </fields>
+
+ <uniqueKey>id</uniqueKey>
+
+
+</schema>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema-sorts.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-sorts.xml b/solr/core/src/test-files/solr/collection1/conf/schema-sorts.xml
index c918017..f68841c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-sorts.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-sorts.xml
@@ -45,30 +45,30 @@ NOTE: Tests expect every field in this schema to be sortable.
<field name="int" type="int"/>
<field name="int_last" type="int_last"/>
<field name="int_first" type="int_first"/>
- <field name="int_dv" type="int_dv"/>
- <field name="int_dv_last" type="int_dv_last"/>
- <field name="int_dv_first" type="int_dv_first"/>
+ <field name="int_dv" type="${solr.tests.intClass:pint}_dv"/>
+ <field name="int_dv_last" type="${solr.tests.intClass:pint}_dv_last"/>
+ <field name="int_dv_first" type="${solr.tests.intClass:pint}_dv_first"/>
<field name="long" type="long"/>
<field name="long_last" type="long_last"/>
<field name="long_first" type="long_first"/>
- <field name="long_dv" type="long_dv"/>
- <field name="long_dv_last" type="long_dv_last"/>
- <field name="long_dv_first" type="long_dv_first"/>
+ <field name="long_dv" type="${solr.tests.longClass:plong}_dv"/>
+ <field name="long_dv_last" type="${solr.tests.longClass:plong}_dv_last"/>
+ <field name="long_dv_first" type="${solr.tests.longClass:plong}_dv_first"/>
<field name="float" type="float"/>
<field name="float_last" type="float_last"/>
<field name="float_first" type="float_first"/>
- <field name="float_dv" type="float_dv"/>
- <field name="float_dv_last" type="float_dv_last"/>
- <field name="float_dv_first" type="float_dv_first"/>
+ <field name="float_dv" type="${solr.tests.floatClass:pfloat}_dv"/>
+ <field name="float_dv_last" type="${solr.tests.floatClass:pfloat}_dv_last"/>
+ <field name="float_dv_first" type="${solr.tests.floatClass:pfloat}_dv_first"/>
<field name="double" type="double"/>
<field name="double_last" type="double_last"/>
<field name="double_first" type="double_first"/>
- <field name="double_dv" type="double_dv"/>
- <field name="double_dv_last" type="double_dv_last"/>
- <field name="double_dv_first" type="double_dv_first"/>
+ <field name="double_dv" type="${solr.tests.doubleClass:pdouble}_dv"/>
+ <field name="double_dv_last" type="${solr.tests.doubleClass:pdouble}_dv_last"/>
+ <field name="double_dv_first" type="${solr.tests.doubleClass:pdouble}_dv_first"/>
<field name="date" type="date"/>
<field name="date_last" type="date_last"/>
@@ -220,6 +220,11 @@ NOTE: Tests expect every field in this schema to be sortable.
sortMissingLast="true"/>
<fieldType name="int_dv_first" class="solr.TrieIntField" stored="true" indexed="false" docValues="true"
sortMissingFirst="true"/>
+ <fieldType name="pint_dv" class="solr.IntPointField" stored="true" indexed="false" docValues="true"/>
+ <fieldType name="pint_dv_last" class="solr.IntPointField" stored="true" indexed="false" docValues="true"
+ sortMissingLast="true"/>
+ <fieldType name="pint_dv_first" class="solr.IntPointField" stored="true" indexed="false" docValues="true"
+ sortMissingFirst="true"/>
<fieldType name="long" class="solr.TrieLongField" stored="true" indexed="true"/>
<fieldType name="long_last" class="solr.TrieLongField" stored="true" indexed="true" sortMissingLast="true"/>
@@ -229,6 +234,11 @@ NOTE: Tests expect every field in this schema to be sortable.
sortMissingLast="true"/>
<fieldType name="long_dv_first" class="solr.TrieLongField" stored="true" indexed="false" docValues="true"
sortMissingFirst="true"/>
+ <fieldType name="plong_dv" class="solr.LongPointField" stored="true" indexed="false" docValues="true"/>
+ <fieldType name="plong_dv_last" class="solr.LongPointField" stored="true" indexed="false" docValues="true"
+ sortMissingLast="true"/>
+ <fieldType name="plong_dv_first" class="solr.LongPointField" stored="true" indexed="false" docValues="true"
+ sortMissingFirst="true"/>
<fieldType name="float" class="solr.TrieFloatField" stored="true" indexed="true"/>
<fieldType name="float_last" class="solr.TrieFloatField" stored="true" indexed="true" sortMissingLast="true"/>
@@ -238,6 +248,11 @@ NOTE: Tests expect every field in this schema to be sortable.
sortMissingLast="true"/>
<fieldType name="float_dv_first" class="solr.TrieFloatField" stored="true" indexed="false" docValues="true"
sortMissingFirst="true"/>
+ <fieldType name="pfloat_dv" class="solr.FloatPointField" stored="true" indexed="false" docValues="true"/>
+ <fieldType name="pfloat_dv_last" class="solr.FloatPointField" stored="true" indexed="false" docValues="true"
+ sortMissingLast="true"/>
+ <fieldType name="pfloat_dv_first" class="solr.FloatPointField" stored="true" indexed="false" docValues="true"
+ sortMissingFirst="true"/>
<fieldType name="double" class="solr.TrieDoubleField" stored="true" indexed="true"/>
<fieldType name="double_last" class="solr.TrieDoubleField" stored="true" indexed="true" sortMissingLast="true"/>
@@ -247,6 +262,11 @@ NOTE: Tests expect every field in this schema to be sortable.
sortMissingLast="true"/>
<fieldType name="double_dv_first" class="solr.TrieDoubleField" stored="true" indexed="false" docValues="true"
sortMissingFirst="true"/>
+ <fieldType name="pdouble_dv" class="solr.DoublePointField" stored="true" indexed="false" docValues="true"/>
+ <fieldType name="pdouble_dv_last" class="solr.DoublePointField" stored="true" indexed="false" docValues="true"
+ sortMissingLast="true"/>
+ <fieldType name="pdouble_dv_first" class="solr.DoublePointField" stored="true" indexed="false" docValues="true"
+ sortMissingFirst="true"/>
<fieldType name="date" class="solr.TrieDateField" stored="true" indexed="true"/>
<fieldType name="date_last" class="solr.TrieDateField" stored="true" indexed="true" sortMissingLast="true"/>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema.xml b/solr/core/src/test-files/solr/collection1/conf/schema.xml
index 35de166..be1b6f5 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema.xml
@@ -43,6 +43,12 @@
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+
+ <!-- Point Fields -->
+ <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
+ <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+ <fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>
+ <fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
<!-- Field type demonstrating an Analyzer failure -->
<fieldType name="failtype1" class="solr.TextField">
@@ -550,7 +556,7 @@
<field name="dateRange" type="dateRange" multiValued="true"/>
<field name="cat" type="string" indexed="true" stored="true" multiValued="true"/>
- <field name="price" type="float" indexed="true" stored="true" multiValued="false"/>
+ <field name="price" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true" multiValued="false"/>
<field name="inStock" type="boolean" indexed="true" stored="true"/>
<field name="subword" type="subword" indexed="true" stored="true"/>
@@ -599,7 +605,7 @@
-->
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
<dynamicField name="*_i1" type="int" indexed="true" stored="true" multiValued="false" sortMissingLast="true"/>
- <dynamicField name="*_idv" type="int" indexed="true" stored="true" docValues="true" multiValued="false"/>
+ <dynamicField name="*_idv" type="${solr.tests.intClass:pint}" indexed="true" stored="true" docValues="true" multiValued="false"/>
<dynamicField name="*_s" type="string" indexed="true" stored="true"/>
@@ -610,9 +616,9 @@
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
<dynamicField name="*_b1" type="boolean" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_f" type="float" indexed="true" stored="true"/>
- <dynamicField name="*_f1" type="float" indexed="true" stored="true" multiValued="false"/>
+ <dynamicField name="*_f1" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_d" type="double" indexed="true" stored="true"/>
- <dynamicField name="*_d1" type="double" indexed="true" stored="true" multiValued="false"/>
+ <dynamicField name="*_d1" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
<dynamicField name="*_dt1" type="date" indexed="true" stored="true" multiValued="false"/>
@@ -662,7 +668,7 @@
<dynamicField name="*_mfacet" type="string" indexed="true" stored="false" multiValued="true"/>
<!-- Type used to index the lat and lon components for the "location" FieldType -->
- <dynamicField name="*_coordinate" type="tdouble" indexed="true" stored="false" omitNorms="true"/>
+ <dynamicField name="*_coordinate" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="false" omitNorms="true"/>
<dynamicField name="*_path" type="path" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
<dynamicField name="*_ancestor" type="ancestor_path" indexed="true" stored="true" omitNorms="true"
@@ -676,12 +682,12 @@
<dynamicField name="*_f_dv" type="float" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_d_dv" type="double" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_dt_dv" type="date" indexed="true" stored="true" docValues="true"/>
- <dynamicField name="*_f1_dv" type="float" indexed="true" stored="true" docValues="true" multiValued="false"/>
+ <dynamicField name="*_f1_dv" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true" docValues="true" multiValued="false"/>
<!-- Non-stored, DocValues=true -->
- <dynamicField name="*_i_dvo" multiValued="false" type="int" docValues="true" indexed="true" stored="false"
+ <dynamicField name="*_i_dvo" multiValued="false" type="${solr.tests.intClass:pint}" docValues="true" indexed="true" stored="false"
useDocValuesAsStored="true"/>
- <dynamicField name="*_d_dvo" multiValued="false" type="double" docValues="true" indexed="true" stored="false"
+ <dynamicField name="*_d_dvo" multiValued="false" type="${solr.tests.doubleClass:pdouble}" docValues="true" indexed="true" stored="false"
useDocValuesAsStored="true"/>
<dynamicField name="*_s_dvo" multiValued="false" type="string" docValues="true" indexed="true" stored="false"
useDocValuesAsStored="true"/>
@@ -691,8 +697,8 @@
useDocValuesAsStored="true"/>
<!-- Non-stored, DocValues=true, useDocValuesAsStored=false -->
- <field name="single_i_dvn" multiValued="false" type="int" indexed="true" stored="true"/>
- <field name="single_d_dvn" multiValued="false" type="double" indexed="true" stored="true"/>
+ <field name="single_i_dvn" multiValued="false" type="${solr.tests.intClass:pint}" indexed="true" stored="true"/>
+ <field name="single_d_dvn" multiValued="false" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="true"/>
<field name="single_s_dvn" multiValued="false" type="string" indexed="true" stored="true"/>
<field name="copy_single_i_dvn" multiValued="false" type="int" docValues="true" indexed="true" stored="false"
useDocValuesAsStored="false"/>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema11.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema11.xml b/solr/core/src/test-files/solr/collection1/conf/schema11.xml
index e5b9233..370f321 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema11.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema11.xml
@@ -77,7 +77,12 @@
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
+
+ <!-- Point Fields -->
+ <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
+ <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+ <fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>
+ <fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
<!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
is a more restricted form of the canonical representation of dateTime
@@ -340,15 +345,15 @@ valued. -->
<dynamicField name="*_s_dv" type="string" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="*_sS" type="string" indexed="false" stored="true"/>
- <dynamicField name="*_i" type="int" indexed="true" stored="true"/>
+ <dynamicField name="*_i" type="${solr.tests.intClass:pint}" indexed="true" stored="true"/>
<dynamicField name="*_ii" type="int" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_l" type="long" indexed="true" stored="true"/>
- <dynamicField name="*_f" type="float" indexed="true" stored="true"/>
- <dynamicField name="*_d" type="double" indexed="true" stored="true"/>
+ <dynamicField name="*_l" type="${solr.tests.longClass:plong}" indexed="true" stored="true"/>
+ <dynamicField name="*_f" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true"/>
+ <dynamicField name="*_d" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="true"/>
<dynamicField name="*_ti" type="tint" indexed="true" stored="true"/>
- <dynamicField name="*_ti_dv" type="int" indexed="true" stored="true" docValues="true"/>
- <dynamicField name="*_ti_ni_dv" type="int" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_ti_dv" type="tint" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_ti_ni_dv" type="tint" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_tl" type="tlong" indexed="true" stored="true"/>
<dynamicField name="*_tl_dv" type="tlong" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_tl_ni_dv" type="tlong" indexed="false" stored="true" docValues="true"/>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema12.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema12.xml b/solr/core/src/test-files/solr/collection1/conf/schema12.xml
index 0de219a..206cd9e 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema12.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema12.xml
@@ -42,6 +42,12 @@
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+
+ <!-- Point Fields -->
+ <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
+ <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+ <fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>
+ <fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
<!-- Field type demonstrating an Analyzer failure -->
<fieldType name="failtype1" class="solr.TextField">
@@ -432,7 +438,7 @@
<field name="text" type="text" indexed="true" stored="false"/>
<field name="subject" type="text" indexed="true" stored="true"/>
<field name="title" type="nametext" indexed="true" stored="true"/>
- <field name="weight" type="float" indexed="true" stored="true"/>
+ <field name="weight" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true"/>
<field name="bday" type="date" indexed="true" stored="true"/>
<field name="text_np" type="text_np" indexed="true" stored="false"/>
@@ -550,7 +556,8 @@
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_idv" type="int" indexed="true" stored="true" docValues="true" multiValued="false"/>
+ <dynamicField name="*_i_dv" type="${solr.tests.intClass:pint}" indexed="true" stored="true" docValues="true" multiValued="false"/>
+ <dynamicField name="*_is_dv" type="${solr.tests.intClass:pint}" indexed="true" stored="true" docValues="true" multiValued="false"/>
<dynamicField name="*_s1" type="string" indexed="true" stored="true" multiValued="false"/>
<!-- :TODO: why are these identical?!?!?! -->
<dynamicField name="*_s" type="string" indexed="true" stored="true" multiValued="true"/>
@@ -559,9 +566,11 @@
<dynamicField name="*_t" type="text" indexed="true" stored="true"/>
<dynamicField name="*_tt" type="text" indexed="true" stored="true"/>
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
- <dynamicField name="*_f" type="float" indexed="true" stored="true"/>
+ <dynamicField name="*_f" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true"/>
<dynamicField name="*_d" type="double" indexed="true" stored="true"/>
<dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
+
+ <dynamicField name="*_pi" type="pint" indexed="true" stored="true" docValues="false" multiValued="false"/>
<!-- some trie-coded dynamic fields for faster range queries -->
<dynamicField name="*_ti" type="tint" indexed="true" stored="true"/>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml b/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml
index 280fd34..c6491eb 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml
@@ -202,7 +202,7 @@
<!-- docvalues and stored are exclusive -->
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_id" type="int" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_id" type="${solr.tests.intClass:pint}" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_ids" type="int" indexed="true" stored="false" multiValued="true" docValues="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="true"/>
<dynamicField name="*_s1" type="string" indexed="true" stored="true"/>
@@ -215,11 +215,11 @@
<dynamicField name="*_lds" type="long" indexed="true" stored="false" multiValued="true" docValues="true"/>
<dynamicField name="*_f" type="float" indexed="true" stored="true"/>
<dynamicField name="*_fs" type="float" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_fd" type="float" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_fd" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_fds" type="float" indexed="true" stored="false" multiValued="true" docValues="true"/>
<dynamicField name="*_d" type="double" indexed="true" stored="true"/>
<dynamicField name="*_ds" type="double" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_dd" type="double" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_dd" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_dds" type="double" indexed="true" stored="false" multiValued="true" docValues="true"/>
<dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
<dynamicField name="*_dts" type="date" indexed="true" stored="true" multiValued="true"/>
@@ -227,15 +227,15 @@
<dynamicField name="*_dtds" type="date" indexed="true" stored="false" multiValued="true" docValues="true"/>
<!-- docvalues and stored (S suffix) -->
- <dynamicField name="*_idS" type="int" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_idS" type="${solr.tests.intClass:pint}" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_idsS" type="int" indexed="true" stored="true" multiValued="true" docValues="true"/>
<dynamicField name="*_sdS" type="string" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_sdsS" type="string" indexed="true" stored="true" multiValued="true" docValues="true"/>
- <dynamicField name="*_ldS" type="long" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_ldS" type="${solr.tests.longClass:plong}" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_ldsS" type="long" indexed="true" stored="true" multiValued="true" docValues="true"/>
- <dynamicField name="*_fdS" type="float" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_fdS" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_fdsS" type="float" indexed="true" stored="true" multiValued="true" docValues="true"/>
- <dynamicField name="*_ddS" type="double" indexed="true" stored="true" docValues="true"/>
+ <dynamicField name="*_ddS" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_ddsS" type="double" indexed="true" stored="true" multiValued="true" docValues="true"/>
<dynamicField name="*_dtdS" type="date" indexed="true" stored="true" docValues="true"/>
<dynamicField name="*_dtdsS" type="date" indexed="true" stored="true" multiValued="true" docValues="true"/>
@@ -394,6 +394,13 @@
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+
+ <!-- Point Fields -->
+ <fieldType name="pint" class="solr.IntPointField"/>
+ <fieldType name="plong" class="solr.LongPointField"/>
+ <fieldType name="pdouble" class="solr.DoublePointField"/>
+ <fieldType name="pfloat" class="solr.FloatPointField"/>
+
<!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
is a more restricted form of the canonical representation of dateTime
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java b/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
index ad62fcc..d0c4f36 100644
--- a/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
+++ b/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
@@ -16,19 +16,20 @@
*/
package org.apache.solr;
+import java.io.IOException;
+import java.util.List;
+
import org.apache.lucene.util.LuceneTestCase.Slow;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.SolrDocumentList;
import org.junit.Test;
-import java.io.IOException;
-import java.util.List;
-
/**
* TODO? perhaps use:
* http://docs.codehaus.org/display/JETTY/ServletTester
@@ -37,6 +38,7 @@ import java.util.List;
* @since solr 4.0
*/
@Slow
+@SuppressPointFields
public class TestDistributedGrouping extends BaseDistributedSearchTestCase {
String t1="a_t";
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/TestJoin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestJoin.java b/solr/core/src/test/org/apache/solr/TestJoin.java
index 419275c..f4b2cf5 100644
--- a/solr/core/src/test/org/apache/solr/TestJoin.java
+++ b/solr/core/src/test/org/apache/solr/TestJoin.java
@@ -16,6 +16,7 @@
*/
package org.apache.solr;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.noggit.JSONUtil;
import org.noggit.ObjectBuilder;
@@ -36,6 +37,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+@SuppressPointFields
public class TestJoin extends SolrTestCaseJ4 {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -151,7 +153,7 @@ public class TestJoin extends SolrTestCaseJ4 {
// increase test effectiveness by avoiding 0 resultsets much of the time.
String[][] compat = new String[][] {
{"small_s","small2_s","small2_ss","small3_ss"},
- {"small_i","small2_i","small2_is","small3_is"}
+ {"small_i","small2_i","small2_is","small3_is", "small_i_dv", "small_is_dv"}
};
@@ -169,6 +171,8 @@ public class TestJoin extends SolrTestCaseJ4 {
types.add(new FldType("small2_i",ZERO_ONE, new IRange(0,5+indexSize/3)));
types.add(new FldType("small2_is",ZERO_TWO, new IRange(0,5+indexSize/3)));
types.add(new FldType("small3_is",new IRange(0,25), new IRange(0,100)));
+ types.add(new FldType("small_i_dv",ZERO_ONE, new IRange(0,5+indexSize/3)));
+ types.add(new FldType("small_is_dv",ZERO_ONE, new IRange(0,5+indexSize/3)));
clearIndex();
Map<Comparable, Doc> model = indexDocs(types, null, indexSize);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java b/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
index 90c2394..d088924 100644
--- a/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
+++ b/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
@@ -62,7 +62,9 @@ public class TestRandomDVFaceting extends SolrTestCaseJ4 {
types = new ArrayList<>();
types.add(new FldType("id",ONE_ONE, new SVal('A','Z',4,4)));
types.add(new FldType("score_f",ONE_ONE, new FVal(1,100)));
+ types.add(new FldType("score_d",ONE_ONE, new FVal(1,100)));
types.add(new FldType("foo_i",ZERO_ONE, new IRange(0,indexSize)));
+ types.add(new FldType("foo_l",ZERO_ONE, new IRange(0,indexSize)));
types.add(new FldType("small_s",ZERO_ONE, new SVal('a',(char)('c'+indexSize/3),1,1)));
types.add(new FldType("small2_s",ZERO_ONE, new SVal('a',(char)('c'+indexSize/3),1,1)));
types.add(new FldType("small2_ss",ZERO_TWO, new SVal('a',(char)('c'+indexSize/3),1,1)));
@@ -231,6 +233,12 @@ public class TestRandomDVFaceting extends SolrTestCaseJ4 {
responses.add(strResponse);
}
+ // If there is a PointField option for this test, also test it
+ if (h.getCore().getLatestSchema().getFieldOrNull(facet_field + "_p") != null) {
+ params.set("facet.field", "{!key="+facet_field+"}"+facet_field+"_p");
+ String strResponse = h.query(req(params));
+ responses.add(strResponse);
+ }
/**
String strResponse = h.query(req(params));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/TestRandomFaceting.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestRandomFaceting.java b/solr/core/src/test/org/apache/solr/TestRandomFaceting.java
index 2ffefdc..c3a3e02 100644
--- a/solr/core/src/test/org/apache/solr/TestRandomFaceting.java
+++ b/solr/core/src/test/org/apache/solr/TestRandomFaceting.java
@@ -184,7 +184,6 @@ public class TestRandomFaceting extends SolrTestCaseJ4 {
SolrQueryRequest req = req();
try {
Random rand = random();
- boolean validate = validateResponses;
ModifiableSolrParams params = params("facet","true", "wt","json", "indent","true", "omitHeader","true");
params.add("q","*:*"); // TODO: select subsets
params.add("rows","0");
@@ -244,8 +243,9 @@ public class TestRandomFaceting extends SolrTestCaseJ4 {
List<String> methods = multiValued ? multiValuedMethods : singleValuedMethods;
List<String> responses = new ArrayList<>(methods.size());
+
for (String method : methods) {
- for (boolean exists : new boolean [] {false, true}) {
+ for (boolean exists : new boolean[]{false, true}) {
// params.add("facet.field", "{!key="+method+"}" + ftype.fname);
// TODO: allow method to be passed on local params?
if (method!=null) {
@@ -253,7 +253,6 @@ public class TestRandomFaceting extends SolrTestCaseJ4 {
} else {
params.remove("facet.method");
}
-
params.set("facet.exists", ""+exists);
if (!exists && rand.nextBoolean()) {
params.remove("facet.exists");
@@ -275,6 +274,13 @@ public class TestRandomFaceting extends SolrTestCaseJ4 {
"facet.exists", req(params), ErrorCode.BAD_REQUEST);
continue;
}
+ if (exists && sf.getType().isPointField()) {
+ // PointFields don't yet support "enum" method or the "facet.exists" parameter
+ assertQEx("Expecting failure, since ",
+ "facet.exists=true is requested, but facet.method=enum can't be used with " + sf.getName(),
+ req(params), ErrorCode.BAD_REQUEST);
+ continue;
+ }
}
String strResponse = h.query(req(params));
responses.add(strResponse);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
index 460c501..b13cb78 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
@@ -29,6 +29,7 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.FieldStatsInfo;
import org.apache.solr.client.solrj.response.PivotField;
@@ -78,6 +79,7 @@ import static org.apache.solr.common.params.FacetParams.FACET_DISTRIB_MCO;
*
*/
@SuppressSSL // Too Slow
+@SuppressPointFields
public class TestCloudPivotFacet extends AbstractFullDistribZkTestBase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java
index a7fb774..7062b43 100644
--- a/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/XsltUpdateRequestHandlerTest.java
@@ -40,7 +40,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
public class XsltUpdateRequestHandlerTest extends SolrTestCaseJ4 {
-
+
@BeforeClass
public static void beforeTests() throws Exception {
initCore("solrconfig.xml","schema.xml");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
index 66c378d..92b4943 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
@@ -16,19 +16,19 @@
*/
package org.apache.solr.handler.admin;
+import java.util.Arrays;
+import java.util.EnumSet;
+
import org.apache.solr.common.luke.FieldFlag;
import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.CustomAnalyzerStrField; // jdoc
+import org.apache.solr.schema.IndexSchema;
import org.apache.solr.util.AbstractSolrTestCase;
import org.apache.solr.util.TestHarness;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import java.util.Arrays;
-import java.util.EnumSet;
-
/**
* :TODO: currently only tests some of the utilities in the LukeRequestHandler
*/
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/handler/component/TestExpandComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/TestExpandComponent.java b/solr/core/src/test/org/apache/solr/handler/component/TestExpandComponent.java
index f7fc13a..7baa5a9 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/TestExpandComponent.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/TestExpandComponent.java
@@ -16,15 +16,19 @@
*/
package org.apache.solr.handler.component;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.SolrTestCaseJ4.SuppressPointFields;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.search.CollapsingQParserPlugin;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import java.util.*;
-
+@SuppressPointFields
public class TestExpandComponent extends SolrTestCaseJ4 {
@BeforeClass
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test/org/apache/solr/request/TestFacetMethods.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/request/TestFacetMethods.java b/solr/core/src/test/org/apache/solr/request/TestFacetMethods.java
index 1da41f5..ea7c001 100644
--- a/solr/core/src/test/org/apache/solr/request/TestFacetMethods.java
+++ b/solr/core/src/test/org/apache/solr/request/TestFacetMethods.java
@@ -17,7 +17,9 @@
package org.apache.solr.request;
+import org.apache.solr.request.SimpleFacets.FacetMethod;
import org.apache.solr.schema.BoolField;
+import org.apache.solr.schema.IntPointField;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.apache.solr.schema.TrieIntField;
@@ -203,5 +205,15 @@ public class TestFacetMethods {
assertEquals(SimpleFacets.FacetMethod.ENUM, SimpleFacets.selectFacetMethod(field, null, 1));
}
+
+ @Test
+ public void testPointFields() {
+ // Methods other than FCS are not currently supported for PointFields
+ SchemaField field = new SchemaField("foo", new IntPointField());
+ assertEquals(SimpleFacets.FacetMethod.FCS, SimpleFacets.selectFacetMethod(field, null, 0));
+ assertEquals(SimpleFacets.FacetMethod.FCS, SimpleFacets.selectFacetMethod(field, FacetMethod.ENUM, 0));
+ assertEquals(SimpleFacets.FacetMethod.FCS, SimpleFacets.selectFacetMethod(field, FacetMethod.FC, 0));
+ assertEquals(SimpleFacets.FacetMethod.FCS, SimpleFacets.selectFacetMethod(field, FacetMethod.FCS, 0));
+ }
}
[4/4] lucene-solr:master: SOLR-8396: Add support for PointFields in
Solr
Posted by tf...@apache.org.
SOLR-8396: Add support for PointFields in Solr
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/57934ba4
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/57934ba4
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/57934ba4
Branch: refs/heads/master
Commit: 57934ba4480d71218c7f60d0417dbae9d26188d0
Parents: a89560b
Author: Tomas Fernandez Lobbe <tf...@apache.org>
Authored: Wed Jan 18 17:27:21 2017 -0800
Committer: Tomas Fernandez Lobbe <tf...@apache.org>
Committed: Wed Jan 18 17:27:21 2017 -0800
----------------------------------------------------------------------
lucene/common-build.xml | 1 +
solr/CHANGES.txt | 4 +
.../solr/handler/admin/LukeRequestHandler.java | 7 +-
.../solr/handler/component/FacetComponent.java | 12 +-
.../solr/handler/component/QueryComponent.java | 25 +-
.../handler/component/RangeFacetProcessor.java | 3 +-
.../handler/component/RangeFacetRequest.java | 31 +-
.../solr/handler/component/StatsComponent.java | 6 +
.../handler/component/StatsValuesFactory.java | 2 +-
.../solr/index/SlowCompositeReaderWrapper.java | 3 -
.../org/apache/solr/request/IntervalFacets.java | 4 +
.../org/apache/solr/request/SimpleFacets.java | 37 +-
.../org/apache/solr/response/DocsStreamer.java | 8 +
.../apache/solr/schema/DoublePointField.java | 187 +++
.../java/org/apache/solr/schema/FieldType.java | 9 +-
.../org/apache/solr/schema/FloatPointField.java | 187 +++
.../org/apache/solr/schema/IntPointField.java | 186 +++
.../org/apache/solr/schema/LongPointField.java | 186 +++
.../java/org/apache/solr/schema/PointField.java | 233 +++
.../org/apache/solr/schema/SchemaField.java | 10 +
.../apache/solr/search/SolrIndexSearcher.java | 44 +-
.../apache/solr/search/TermQParserPlugin.java | 10 +-
.../apache/solr/search/TermsQParserPlugin.java | 10 +
.../apache/solr/search/facet/FacetRange.java | 28 +-
.../DocumentExpressionDictionaryFactory.java | 12 +-
.../conf/schema-distrib-interval-faceting.xml | 14 +-
.../conf/schema-docValuesFaceting.xml | 12 +
.../solr/collection1/conf/schema-point.xml | 88 ++
.../solr/collection1/conf/schema-sorts.xml | 44 +-
.../test-files/solr/collection1/conf/schema.xml | 26 +-
.../solr/collection1/conf/schema11.xml | 19 +-
.../solr/collection1/conf/schema12.xml | 15 +-
.../solr/collection1/conf/schema_latest.xml | 21 +-
.../apache/solr/TestDistributedGrouping.java | 10 +-
.../core/src/test/org/apache/solr/TestJoin.java | 6 +-
.../org/apache/solr/TestRandomDVFaceting.java | 8 +
.../org/apache/solr/TestRandomFaceting.java | 12 +-
.../apache/solr/cloud/TestCloudPivotFacet.java | 2 +
.../handler/XsltUpdateRequestHandlerTest.java | 2 +-
.../handler/admin/LukeRequestHandlerTest.java | 8 +-
.../handler/component/TestExpandComponent.java | 8 +-
.../apache/solr/request/TestFacetMethods.java | 12 +
.../org/apache/solr/schema/TestPointFields.java | 1472 ++++++++++++++++++
.../solr/search/TestCollapseQParserPlugin.java | 4 +-
.../solr/search/TestMaxScoreQueryParser.java | 2 +-
.../search/TestRandomCollapseQParserPlugin.java | 2 +
.../apache/solr/search/TestSolrQueryParser.java | 8 +
.../solr/search/facet/TestJsonFacets.java | 2 +
.../java/org/apache/solr/SolrTestCaseJ4.java | 44 +-
49 files changed, 2979 insertions(+), 107 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/lucene/common-build.xml
----------------------------------------------------------------------
diff --git a/lucene/common-build.xml b/lucene/common-build.xml
index 87d2e0a..48cf457 100644
--- a/lucene/common-build.xml
+++ b/lucene/common-build.xml
@@ -1073,6 +1073,7 @@
<propertyref prefix="tests.leaveTemporary" />
<propertyref prefix="tests.leavetemporary" />
<propertyref prefix="solr.test.leavetmpdir" />
+ <propertyref prefix="solr.tests.preferPointFields"/>
</syspropertyset>
<!-- Pass randomized settings to the forked JVM. -->
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 205c7bc..82c3d2b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -74,6 +74,10 @@ Optimizations
* SOLR-9584: Support Solr being proxied with another endpoint than default /solr, by using relative links
in AdminUI javascripts (Yun Jie Zhou via janhoy)
+Other Changes
+----------------------
+* SOLR-8396: Add support for PointFields in Solr (Ishan Chattopadhyaya, Tom�s Fern�ndez L�bbe)
+
================== 6.5.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
index 50f46ef..7f08684 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
@@ -289,8 +289,6 @@ public class LukeRequestHandler extends RequestHandlerBase
f.add( "schema", getFieldFlags( sfield ) );
f.add( "flags", getFieldFlags( field ) );
- Term t = new Term(field.name(), ftype!=null ? ftype.storedToIndexed(field) : field.stringValue());
-
f.add( "value", (ftype==null)?null:ftype.toExternal( field ) );
// TODO: this really should be "stored"
@@ -301,7 +299,10 @@ public class LukeRequestHandler extends RequestHandlerBase
f.add( "binary", Base64.byteArrayToBase64(bytes.bytes, bytes.offset, bytes.length));
}
f.add( "boost", field.boost() );
- f.add( "docFreq", t.text()==null ? 0 : reader.docFreq( t ) ); // this can be 0 for non-indexed fields
+ if (!ftype.isPointField()) {
+ Term t = new Term(field.name(), ftype!=null ? ftype.storedToIndexed(field) : field.stringValue());
+ f.add( "docFreq", t.text()==null ? 0 : reader.docFreq( t ) ); // this can be 0 for non-indexed fields
+ }// TODO: Calculate docFreq for point fields
// If we have a term vector, return that
if( field.fieldType().storeTermVectors() ) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java b/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
index 1cc05ab..bcff0c2 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
@@ -33,6 +33,7 @@ import java.util.Map.Entry;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.FixedBitSet;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
@@ -47,6 +48,7 @@ import org.apache.solr.common.util.StrUtils;
import org.apache.solr.request.SimpleFacets;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.PointField;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.facet.FacetDebugInfo;
@@ -1477,7 +1479,13 @@ public class FacetComponent extends SearchComponent {
if (sfc == null) {
sfc = new ShardFacetCount();
sfc.name = name;
- sfc.indexed = ftype == null ? sfc.name : ftype.toInternal(sfc.name);
+ if (ftype == null) {
+ sfc.indexed = null;
+ } else if (ftype.isPointField()) {
+ sfc.indexed = ((PointField)ftype).toInternalByteRef(sfc.name);
+ } else {
+ sfc.indexed = new BytesRef(ftype.toInternal(sfc.name));
+ }
sfc.termNum = termNum++;
counts.put(name, sfc);
}
@@ -1553,7 +1561,7 @@ public class FacetComponent extends SearchComponent {
public static class ShardFacetCount {
public String name;
// the indexed form of the name... used for comparisons
- public String indexed;
+ public BytesRef indexed;
public long count;
public int termNum; // term number starting at 0 (used in bit arrays)
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java b/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
index 88ff731..c357202 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
@@ -185,6 +185,11 @@ public class QueryComponent extends SearchComponent
}
rb.setSortSpec( parser.getSortSpec(true) );
+ for (SchemaField sf:rb.getSortSpec().getSchemaFields()) {
+ if (sf != null && sf.getType().isPointField() && !sf.hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"Can't sort on a point field without docValues");
+ }
+ }
rb.setQparser(parser);
final String cursorStr = rb.req.getParams().get(CursorMarkParams.CURSOR_MARK_PARAM);
@@ -335,11 +340,21 @@ public class QueryComponent extends SearchComponent
List<String> idArr = StrUtils.splitSmart(ids, ",", true);
int[] luceneIds = new int[idArr.size()];
int docs = 0;
- for (int i=0; i<idArr.size(); i++) {
- int id = searcher.getFirstMatch(
- new Term(idField.getName(), idField.getType().toInternal(idArr.get(i))));
- if (id >= 0)
- luceneIds[docs++] = id;
+ if (idField.getType().isPointField()) {
+ for (int i=0; i<idArr.size(); i++) {
+ int id = searcher.search(
+ idField.getType().getFieldQuery(null, idField, idArr.get(i)), 1).scoreDocs[0].doc;
+ if (id >= 0) {
+ luceneIds[docs++] = id;
+ }
+ }
+ } else {
+ for (int i=0; i<idArr.size(); i++) {
+ int id = searcher.getFirstMatch(
+ new Term(idField.getName(), idField.getType().toInternal(idArr.get(i))));
+ if (id >= 0)
+ luceneIds[docs++] = id;
+ }
}
DocListAndSet res = new DocListAndSet();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/component/RangeFacetProcessor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/RangeFacetProcessor.java b/solr/core/src/java/org/apache/solr/handler/component/RangeFacetProcessor.java
index 731d224..f8ab7b7 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/RangeFacetProcessor.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/RangeFacetProcessor.java
@@ -55,7 +55,6 @@ public class RangeFacetProcessor extends SimpleFacets {
*
* @see org.apache.solr.common.params.FacetParams#FACET_RANGE
*/
- @SuppressWarnings("unchecked")
public NamedList<Object> getFacetRangeCounts() throws IOException, SyntaxError {
final NamedList<Object> resOuter = new SimpleOrderedMap<>();
@@ -92,7 +91,7 @@ public class RangeFacetProcessor extends SimpleFacets {
final FieldType ft = sf.getType();
if (method.equals(FacetRangeMethod.DV)) {
- assert ft instanceof TrieField;
+ assert ft instanceof TrieField || ft.isPointField();
resOuter.add(key, getFacetRangeCountsDocValues(rangeFacetRequest));
} else {
resOuter.add(key, getFacetRangeCounts(rangeFacetRequest));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java b/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
index 8c0c381..f129e73 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
@@ -34,6 +34,7 @@ import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.schema.DateRangeField;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.PointField;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieDateField;
import org.apache.solr.schema.TrieField;
@@ -91,6 +92,11 @@ public class RangeFacetRequest extends FacetComponent.FacetBase {
DateRangeField.class + "'. Will use method '" + FacetParams.FacetRangeMethod.FILTER + "' instead");
method = FacetParams.FacetRangeMethod.FILTER;
}
+ if (method.equals(FacetParams.FacetRangeMethod.DV) && !schemaField.hasDocValues() && (schemaField.getType().isPointField())) {
+ log.warn("Range facet method '" + FacetParams.FacetRangeMethod.DV + "' is not supported on PointFields without docValues." +
+ "Will use method '" + FacetParams.FacetRangeMethod.FILTER + "' instead");
+ method = FacetParams.FacetRangeMethod.FILTER;
+ }
this.start = required.getFieldParam(facetOn, FacetParams.FACET_RANGE_START);
this.end = required.getFieldParam(facetOn, FacetParams.FACET_RANGE_END);
@@ -159,10 +165,33 @@ public class RangeFacetRequest extends FacetComponent.FacetBase {
default:
throw new SolrException
(SolrException.ErrorCode.BAD_REQUEST,
- "Unable to range facet on tried field of unexpected type:" + this.facetOn);
+ "Unable to range facet on Trie field of unexpected type:" + this.facetOn);
}
} else if (ft instanceof DateRangeField) {
calc = new DateRangeEndpointCalculator(this, null);
+ } else if (ft.isPointField()) {
+ final PointField pointField = (PointField) ft;
+ switch (pointField.getType()) {
+ case FLOAT:
+ calc = new FloatRangeEndpointCalculator(this);
+ break;
+ case DOUBLE:
+ calc = new DoubleRangeEndpointCalculator(this);
+ break;
+ case INTEGER:
+ calc = new IntegerRangeEndpointCalculator(this);
+ break;
+ case LONG:
+ calc = new LongRangeEndpointCalculator(this);
+ break;
+ case DATE:
+ calc = new DateRangeEndpointCalculator(this, null);
+ break;
+ default:
+ throw new SolrException
+ (SolrException.ErrorCode.BAD_REQUEST,
+ "Unable to range facet on Point field of unexpected type:" + this.facetOn);
+ }
} else {
throw new SolrException
(SolrException.ErrorCode.BAD_REQUEST,
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java b/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
index 68284c7..6a6e9be 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
@@ -45,6 +45,12 @@ public class StatsComponent extends SearchComponent {
rb.setNeedDocSet( true );
rb.doStats = true;
rb._statsInfo = new StatsInfo(rb);
+ for (StatsField statsField : rb._statsInfo.getStatsFields()) {
+ if (statsField.getSchemaField() != null && statsField.getSchemaField().getType().isPointField() && !statsField.getSchemaField().hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ "Can't calculate stats on a PointField without docValues");
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java b/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
index 8a35ee0..7605f73 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
@@ -65,7 +65,7 @@ public class StatsValuesFactory {
if (TrieDateField.class.isInstance(fieldType)) {
return new DateStatsValues(statsField);
- } else if (TrieField.class.isInstance(fieldType)) {
+ } else if (TrieField.class.isInstance(fieldType) || PointField.class.isInstance(fieldType)) {
return new NumericStatsValues(statsField);
} else if (StrField.class.isInstance(fieldType)) {
return new StringStatsValues(statsField);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
index 5031faf..12f5bd1 100644
--- a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
+++ b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
@@ -65,9 +65,6 @@ public final class SlowCompositeReaderWrapper extends LeafReader {
SlowCompositeReaderWrapper(CompositeReader reader, boolean merging) throws IOException {
super();
in = reader;
- if (getFieldInfos().hasPointValues()) {
- throw new IllegalArgumentException("cannot wrap points");
- }
fields = MultiFields.getFields(in);
in.registerParentReader(this);
this.merging = merging;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/request/IntervalFacets.java b/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
index 14bf700..88e39fc 100644
--- a/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
@@ -42,6 +42,7 @@ import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.IntervalFacets.FacetInterval;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.PointField;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieDateField;
import org.apache.solr.search.DocIterator;
@@ -625,6 +626,9 @@ public class IntervalFacets implements Iterable<FacetInterval> {
if ("*".equals(value)) {
return null;
}
+ if (schemaField.getType().isPointField()) {
+ return ((PointField)schemaField.getType()).toInternalByteRef(value);
+ }
return new BytesRef(schemaField.getType().toInternal(value));
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
index 641b1f3..0d9cb29 100644
--- a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
@@ -411,6 +411,10 @@ public class SimpleFacets {
NamedList<Integer> counts;
SchemaField sf = searcher.getSchema().getField(field);
+ if (sf.getType().isPointField() && !sf.hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ "Can't facet on a PointField without docValues");
+ }
FieldType ft = sf.getType();
// determine what type of faceting method to use
@@ -579,6 +583,10 @@ public class SimpleFacets {
static FacetMethod selectFacetMethod(SchemaField field, FacetMethod method, Integer mincount) {
FieldType type = field.getType();
+ if (type.isPointField()) {
+ // Only FCS is supported for PointFields for now
+ return FacetMethod.FCS;
+ }
/*The user did not specify any preference*/
if (method == null) {
@@ -810,12 +818,20 @@ public class SimpleFacets {
* @param terms a list of term values (in the specified field) to compute the counts for
*/
protected NamedList<Integer> getListedTermCounts(String field, final ParsedParams parsed, List<String> terms) throws IOException {
- FieldType ft = searcher.getSchema().getFieldType(field);
+ SchemaField sf = searcher.getSchema().getField(field);
+ FieldType ft = sf.getType();
NamedList<Integer> res = new NamedList<>();
- for (String term : terms) {
- String internal = ft.toInternal(term);
- int count = searcher.numDocs(new TermQuery(new Term(field, internal)), parsed.docs);
- res.add(term, count);
+ if (ft.isPointField()) {
+ for (String term : terms) {
+ int count = searcher.numDocs(ft.getFieldQuery(null, sf, term), parsed.docs);
+ res.add(term, count);
+ }
+ } else {
+ for (String term : terms) {
+ String internal = ft.toInternal(term);
+ int count = searcher.numDocs(new TermQuery(new Term(field, internal)), parsed.docs);
+ res.add(term, count);
+ }
}
return res;
}
@@ -848,7 +864,7 @@ public class SimpleFacets {
public NamedList<Integer> getFacetTermEnumCounts(SolrIndexSearcher searcher, DocSet docs, String field, int offset, int limit, int mincount, boolean missing,
String sort, String prefix, String contains, boolean ignoreCase, boolean intersectsCheck)
throws IOException {
-
+
/* :TODO: potential optimization...
* cache the Terms with the highest docFreq and try them first
* don't enum if we get our max from them
@@ -864,10 +880,12 @@ public class SimpleFacets {
fastForRandomSet = new HashDocSet(sset.getDocs(), 0, sset.size());
}
-
IndexSchema schema = searcher.getSchema();
- LeafReader r = searcher.getSlowAtomicReader();
FieldType ft = schema.getFieldType(field);
+ assert !ft.isPointField(): "Point Fields don't support enum method";
+
+ LeafReader r = searcher.getSlowAtomicReader();
+
boolean sortByCount = sort.equals("count") || sort.equals("true");
final int maxsize = limit>=0 ? offset+limit : Integer.MAX_VALUE-1;
@@ -1082,6 +1100,9 @@ public class SimpleFacets {
if (parsed.params.getBool(GroupParams.GROUP_FACET, false)) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Interval Faceting can't be used with " + GroupParams.GROUP_FACET);
}
+ if (schemaField.getType().isPointField() && !schemaField.hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't use interval faceting on a PointField without docValues");
+ }
SimpleOrderedMap<Integer> fieldResults = new SimpleOrderedMap<Integer>();
res.add(parsed.key, fieldResults);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/response/DocsStreamer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/DocsStreamer.java b/solr/core/src/java/org/apache/solr/response/DocsStreamer.java
index bee699c..ef0b0c7 100644
--- a/solr/core/src/java/org/apache/solr/response/DocsStreamer.java
+++ b/solr/core/src/java/org/apache/solr/response/DocsStreamer.java
@@ -31,8 +31,12 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.response.transform.DocTransformer;
import org.apache.solr.schema.BinaryField;
import org.apache.solr.schema.BoolField;
+import org.apache.solr.schema.DoublePointField;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.FloatPointField;
import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.IntPointField;
+import org.apache.solr.schema.LongPointField;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.apache.solr.schema.TextField;
@@ -213,6 +217,10 @@ public class DocsStreamer implements Iterator<SolrDocument> {
KNOWN_TYPES.add(TrieDoubleField.class);
KNOWN_TYPES.add(TrieDateField.class);
KNOWN_TYPES.add(BinaryField.class);
+ KNOWN_TYPES.add(IntPointField.class);
+ KNOWN_TYPES.add(LongPointField.class);
+ KNOWN_TYPES.add(DoublePointField.class);
+ KNOWN_TYPES.add(FloatPointField.class);
// We do not add UUIDField because UUID object is not a supported type in JavaBinCodec
// and if we write UUIDField.toObject, we wouldn't know how to handle it in the client side
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/DoublePointField.java b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
new file mode 100644
index 0000000..c393dfe
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
@@ -0,0 +1,187 @@
+/*
+ * 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.lang.invoke.MethodHandles;
+import java.util.Collection;
+
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.DocValuesType;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.legacy.LegacyNumericType;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code PointField} implementation for {@code Double} values.
+ * @see PointField
+ * @see DoublePoint
+ */
+public class DoublePointField extends PointField implements DoubleValueFieldType {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public Object toNativeType(Object val) {
+ if (val == null) return null;
+ if (val instanceof Number) return ((Number) val).doubleValue();
+ if (val instanceof String) return Double.parseDouble((String) val);
+ return super.toNativeType(val);
+ }
+
+ @Override
+ public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
+ boolean maxInclusive) {
+ double actualMin, actualMax;
+ if (min == null) {
+ actualMin = Double.NEGATIVE_INFINITY;
+ } else {
+ actualMin = Double.parseDouble(min);
+ if (!minInclusive) {
+ actualMin = DoublePoint.nextUp(actualMin);
+ }
+ }
+ if (max == null) {
+ actualMax = Double.POSITIVE_INFINITY;
+ } else {
+ actualMax = Double.parseDouble(max);
+ if (!maxInclusive) {
+ actualMax = DoublePoint.nextDown(actualMax);
+ }
+ }
+ return DoublePoint.newRangeQuery(field.getName(), actualMin, actualMax);
+ }
+
+ @Override
+ public Object toObject(SchemaField sf, BytesRef term) {
+ return DoublePoint.decodeDimension(term.bytes, term.offset);
+ }
+
+ @Override
+ public Object toObject(IndexableField f) {
+ final Number val = f.numericValue();
+ if (val != null) {
+ if (f.fieldType().stored() == false && f.fieldType().docValuesType() == DocValuesType.NUMERIC) {
+ return Double.longBitsToDouble(val.longValue());
+ } else {
+ return val;
+ }
+ } else {
+ throw new AssertionError("Unexpected state. Field: '" + f + "'");
+ }
+ }
+
+ @Override
+ protected Query getExactQuery(SchemaField field, String externalVal) {
+ return DoublePoint.newExactQuery(field.getName(), Double.parseDouble(externalVal));
+ }
+
+ @Override
+ public Query getSetQuery(QParser parser, SchemaField field, Collection<String> externalVal) {
+ assert externalVal.size() > 0;
+ double[] values = new double[externalVal.size()];
+ int i = 0;
+ for (String val:externalVal) {
+ values[i] = Double.parseDouble(val);
+ i++;
+ }
+ return DoublePoint.newSetQuery(field.getName(), values);
+ }
+
+ @Override
+ protected String indexedToReadable(BytesRef indexedForm) {
+ return Double.toString(DoublePoint.decodeDimension(indexedForm.bytes, indexedForm.offset));
+ }
+
+ @Override
+ public void readableToIndexed(CharSequence val, BytesRefBuilder result) {
+ result.grow(Double.BYTES);
+ result.setLength(Double.BYTES);
+ DoublePoint.encodeDimension(Double.parseDouble(val.toString()), result.bytes(), 0);
+ }
+
+ @Override
+ public SortField getSortField(SchemaField field, boolean top) {
+ field.checkSortability();
+
+ Object missingValue = null;
+ boolean sortMissingLast = field.sortMissingLast();
+ boolean sortMissingFirst = field.sortMissingFirst();
+
+ if (sortMissingLast) {
+ missingValue = top ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ } else if (sortMissingFirst) {
+ missingValue = top ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
+ }
+ SortField sf = new SortField(field.getName(), SortField.Type.DOUBLE, top);
+ sf.setMissingValue(missingValue);
+ return sf;
+ }
+
+ @Override
+ public Type getUninversionType(SchemaField sf) {
+ if (sf.multiValued()) {
+ throw new UnsupportedOperationException("MultiValued Point fields with DocValues is not currently supported");
+// return Type.SORTED_DOUBLE;
+ } else {
+ return Type.DOUBLE_POINT;
+ }
+ }
+
+ @Override
+ public ValueSource getValueSource(SchemaField field, QParser qparser) {
+ field.checkFieldCacheSource();
+ return new DoubleFieldSource(field.getName());
+ }
+
+ @Override
+ public LegacyNumericType getNumericType() {
+ // TODO: refactor this to not use LegacyNumericType
+ return LegacyNumericType.DOUBLE;
+ }
+
+ @Override
+ public IndexableField createField(SchemaField field, Object value, float boost) {
+ if (!isFieldUsed(field)) return null;
+
+ if (boost != 1.0 && log.isTraceEnabled()) {
+ log.trace("Can't use document/field boost for PointField. Field: " + field.getName() + ", boost: " + boost);
+ }
+ double doubleValue = (value instanceof Number) ? ((Number) value).doubleValue() : Double.parseDouble(value.toString());
+ return new DoublePoint(field.getName(), doubleValue);
+ }
+
+ @Override
+ protected StoredField getStoredField(SchemaField sf, Object value) {
+ return new StoredField(sf.getName(), (Double) this.toNativeType(value));
+ }
+
+ @Override
+ public PointTypes getType() {
+ return PointTypes.DOUBLE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/FieldType.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldType.java b/solr/core/src/java/org/apache/solr/schema/FieldType.java
index a5c898a..3922edc 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldType.java
@@ -126,6 +126,10 @@ public abstract class FieldType extends FieldProperties {
public boolean isPolyField(){
return false;
}
+
+ public boolean isPointField() {
+ return false;
+ }
/**
* Returns true if the fields' docValues should be used for obtaining stored value
@@ -395,7 +399,10 @@ public abstract class FieldType extends FieldProperties {
return toInternal(val);
}
- /** Given the readable value, return the term value that will match it. */
+ /** Given the readable value, return the term value that will match it.
+ * This method will modify the size and length of the {@code result}
+ * parameter and write from offset 0
+ */
public void readableToIndexed(CharSequence val, BytesRefBuilder result) {
final String internal = readableToIndexed(val.toString());
result.copyChars(internal);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FloatPointField.java b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
new file mode 100644
index 0000000..766c6e9
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
@@ -0,0 +1,187 @@
+/*
+ * 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.lang.invoke.MethodHandles;
+import java.util.Collection;
+
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.DocValuesType;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.legacy.LegacyNumericType;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code PointField} implementation for {@code Float} values.
+ * @see PointField
+ * @see FloatPoint
+ */
+public class FloatPointField extends PointField implements FloatValueFieldType {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public Object toNativeType(Object val) {
+ if (val == null) return null;
+ if (val instanceof Number) return ((Number) val).floatValue();
+ if (val instanceof String) return Float.parseFloat((String) val);
+ return super.toNativeType(val);
+ }
+
+ @Override
+ public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
+ boolean maxInclusive) {
+ float actualMin, actualMax;
+ if (min == null) {
+ actualMin = Float.NEGATIVE_INFINITY;
+ } else {
+ actualMin = Float.parseFloat(min);
+ if (!minInclusive) {
+ actualMin = FloatPoint.nextUp(actualMin);
+ }
+ }
+ if (max == null) {
+ actualMax = Float.POSITIVE_INFINITY;
+ } else {
+ actualMax = Float.parseFloat(max);
+ if (!maxInclusive) {
+ actualMax = FloatPoint.nextDown(actualMax);
+ }
+ }
+ return FloatPoint.newRangeQuery(field.getName(), actualMin, actualMax);
+ }
+
+ @Override
+ public Object toObject(SchemaField sf, BytesRef term) {
+ return FloatPoint.decodeDimension(term.bytes, term.offset);
+ }
+
+ @Override
+ public Object toObject(IndexableField f) {
+ final Number val = f.numericValue();
+ if (val != null) {
+ if (f.fieldType().stored() == false && f.fieldType().docValuesType() == DocValuesType.NUMERIC) {
+ return Float.intBitsToFloat(val.intValue());
+ } else {
+ return val;
+ }
+ } else {
+ throw new AssertionError("Unexpected state. Field: '" + f + "'");
+ }
+ }
+
+ @Override
+ protected Query getExactQuery(SchemaField field, String externalVal) {
+ return FloatPoint.newExactQuery(field.getName(), Float.parseFloat(externalVal));
+ }
+
+ @Override
+ public Query getSetQuery(QParser parser, SchemaField field, Collection<String> externalVal) {
+ assert externalVal.size() > 0;
+ float[] values = new float[externalVal.size()];
+ int i = 0;
+ for (String val:externalVal) {
+ values[i] = Float.parseFloat(val);
+ i++;
+ }
+ return FloatPoint.newSetQuery(field.getName(), values);
+ }
+
+ @Override
+ protected String indexedToReadable(BytesRef indexedForm) {
+ return Float.toString(FloatPoint.decodeDimension(indexedForm.bytes, indexedForm.offset));
+ }
+
+ @Override
+ public void readableToIndexed(CharSequence val, BytesRefBuilder result) {
+ result.grow(Float.BYTES);
+ result.setLength(Float.BYTES);
+ FloatPoint.encodeDimension(Float.parseFloat(val.toString()), result.bytes(), 0);
+ }
+
+ @Override
+ public SortField getSortField(SchemaField field, boolean top) {
+ field.checkSortability();
+
+ Object missingValue = null;
+ boolean sortMissingLast = field.sortMissingLast();
+ boolean sortMissingFirst = field.sortMissingFirst();
+
+ if (sortMissingLast) {
+ missingValue = top ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ } else if (sortMissingFirst) {
+ missingValue = top ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
+ }
+ SortField sf = new SortField(field.getName(), SortField.Type.FLOAT, top);
+ sf.setMissingValue(missingValue);
+ return sf;
+ }
+
+ @Override
+ public Type getUninversionType(SchemaField sf) {
+ if (sf.multiValued()) {
+ throw new UnsupportedOperationException("MultiValued Point fields with DocValues is not currently supported");
+// return Type.SORTED_FLOAT;
+ } else {
+ return Type.FLOAT_POINT;
+ }
+ }
+
+ @Override
+ public ValueSource getValueSource(SchemaField field, QParser qparser) {
+ field.checkFieldCacheSource();
+ return new FloatFieldSource(field.getName());
+ }
+
+ @Override
+ public LegacyNumericType getNumericType() {
+ // TODO: refactor this to not use LegacyNumericType
+ return LegacyNumericType.FLOAT;
+ }
+
+ @Override
+ public IndexableField createField(SchemaField field, Object value, float boost) {
+ if (!isFieldUsed(field)) return null;
+
+ if (boost != 1.0 && log.isTraceEnabled()) {
+ log.trace("Can't use document/field boost for PointField. Field: " + field.getName() + ", boost: " + boost);
+ }
+ float floatValue = (value instanceof Number) ? ((Number) value).floatValue() : Float.parseFloat(value.toString());
+ return new FloatPoint(field.getName(), floatValue);
+ }
+
+ @Override
+ protected StoredField getStoredField(SchemaField sf, Object value) {
+ return new StoredField(sf.getName(), (Float) this.toNativeType(value));
+ }
+
+ @Override
+ public PointTypes getType() {
+ return PointTypes.FLOAT;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/IntPointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/IntPointField.java b/solr/core/src/java/org/apache/solr/schema/IntPointField.java
new file mode 100644
index 0000000..a7bab07
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/IntPointField.java
@@ -0,0 +1,186 @@
+/*
+ * 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.lang.invoke.MethodHandles;
+import java.util.Collection;
+
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.legacy.LegacyNumericType;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.IntFieldSource;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code PointField} implementation for {@code Integer} values.
+ * @see PointField
+ * @see IntPoint
+ */
+public class IntPointField extends PointField implements IntValueFieldType {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public Object toNativeType(Object val) {
+ if (val == null) return null;
+ if (val instanceof Number) return ((Number) val).intValue();
+ try {
+ if (val instanceof String) return Integer.parseInt((String) val);
+ } catch (NumberFormatException e) {
+ Float v = Float.parseFloat((String) val);
+ return v.intValue();
+ }
+ return super.toNativeType(val);
+ }
+
+ @Override
+ public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
+ boolean maxInclusive) {
+ int actualMin, actualMax;
+ if (min == null) {
+ actualMin = Integer.MIN_VALUE;
+ } else {
+ actualMin = Integer.parseInt(min);
+ if (!minInclusive) {
+ actualMin++;
+ }
+ }
+ if (max == null) {
+ actualMax = Integer.MAX_VALUE;
+ } else {
+ actualMax = Integer.parseInt(max);
+ if (!maxInclusive) {
+ actualMax--;
+ }
+ }
+ return IntPoint.newRangeQuery(field.getName(), actualMin, actualMax);
+ }
+
+ @Override
+ public Object toObject(SchemaField sf, BytesRef term) {
+ return IntPoint.decodeDimension(term.bytes, term.offset);
+ }
+
+ @Override
+ public Object toObject(IndexableField f) {
+ final Number val = f.numericValue();
+ if (val != null) {
+ return val;
+ } else {
+ throw new AssertionError("Unexpected state. Field: '" + f + "'");
+ }
+ }
+
+ @Override
+ protected Query getExactQuery(SchemaField field, String externalVal) {
+ return IntPoint.newExactQuery(field.getName(), Integer.parseInt(externalVal));
+ }
+
+ @Override
+ public Query getSetQuery(QParser parser, SchemaField field, Collection<String> externalVal) {
+ assert externalVal.size() > 0;
+ int[] values = new int[externalVal.size()];
+ int i = 0;
+ for (String val:externalVal) {
+ values[i] = Integer.parseInt(val);
+ i++;
+ }
+ return IntPoint.newSetQuery(field.getName(), values);
+ }
+
+ @Override
+ protected String indexedToReadable(BytesRef indexedForm) {
+ return Integer.toString(IntPoint.decodeDimension(indexedForm.bytes, indexedForm.offset));
+ }
+
+ @Override
+ public void readableToIndexed(CharSequence val, BytesRefBuilder result) {
+ result.grow(Integer.BYTES);
+ result.setLength(Integer.BYTES);
+ IntPoint.encodeDimension(Integer.parseInt(val.toString()), result.bytes(), 0);
+ }
+
+ @Override
+ public SortField getSortField(SchemaField field, boolean top) {
+ field.checkSortability();
+
+ Object missingValue = null;
+ boolean sortMissingLast = field.sortMissingLast();
+ boolean sortMissingFirst = field.sortMissingFirst();
+
+ if (sortMissingLast) {
+ missingValue = top ? Integer.MIN_VALUE : Integer.MAX_VALUE;
+ } else if (sortMissingFirst) {
+ missingValue = top ? Integer.MAX_VALUE : Integer.MIN_VALUE;
+ }
+ SortField sf = new SortField(field.getName(), SortField.Type.INT, top);
+ sf.setMissingValue(missingValue);
+ return sf;
+ }
+
+ @Override
+ public Type getUninversionType(SchemaField sf) {
+ if (sf.multiValued()) {
+ throw new UnsupportedOperationException("MultiValued Point fields with DocValues is not currently supported");
+// return Type.SORTED_INTEGER;
+ } else {
+ return Type.INTEGER_POINT;
+ }
+ }
+
+ @Override
+ public ValueSource getValueSource(SchemaField field, QParser qparser) {
+ field.checkFieldCacheSource();
+ return new IntFieldSource(field.getName());
+ }
+
+ @Override
+ public LegacyNumericType getNumericType() {
+ return LegacyNumericType.INT;
+ }
+
+ @Override
+ public IndexableField createField(SchemaField field, Object value, float boost) {
+ if (!isFieldUsed(field)) return null;
+
+ if (boost != 1.0 && log.isTraceEnabled()) {
+ log.trace("Can't use document/field boost for PointField. Field: " + field.getName() + ", boost: " + boost);
+ }
+ int intValue = (value instanceof Number) ? ((Number) value).intValue() : Integer.parseInt(value.toString());
+ return new IntPoint(field.getName(), intValue);
+ }
+
+ @Override
+ protected StoredField getStoredField(SchemaField sf, Object value) {
+ return new StoredField(sf.getName(), (Integer) this.toNativeType(value));
+ }
+
+ @Override
+ public PointTypes getType() {
+ return PointTypes.INTEGER;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/LongPointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/LongPointField.java b/solr/core/src/java/org/apache/solr/schema/LongPointField.java
new file mode 100644
index 0000000..f3fca3c
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/LongPointField.java
@@ -0,0 +1,186 @@
+/*
+ * 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.lang.invoke.MethodHandles;
+import java.util.Collection;
+
+import org.apache.lucene.document.LongPoint;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.legacy.LegacyNumericType;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code PointField} implementation for {@code Long} values.
+ * @see PointField
+ * @see LongPoint
+ */
+public class LongPointField extends PointField implements LongValueFieldType {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public Object toNativeType(Object val) {
+ if (val == null) return null;
+ if (val instanceof Number) return ((Number) val).longValue();
+ try {
+ if (val instanceof String) return Long.parseLong((String) val);
+ } catch (NumberFormatException e) {
+ Double v = Double.parseDouble((String) val);
+ return v.longValue();
+ }
+ return super.toNativeType(val);
+ }
+
+ @Override
+ public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
+ boolean maxInclusive) {
+ long actualMin, actualMax;
+ if (min == null) {
+ actualMin = Long.MIN_VALUE;
+ } else {
+ actualMin = Long.parseLong(min);
+ if (!minInclusive) {
+ actualMin++;
+ }
+ }
+ if (max == null) {
+ actualMax = Long.MAX_VALUE;
+ } else {
+ actualMax = Long.parseLong(max);
+ if (!maxInclusive) {
+ actualMax--;
+ }
+ }
+ return LongPoint.newRangeQuery(field.getName(), actualMin, actualMax);
+ }
+
+ @Override
+ public Object toObject(SchemaField sf, BytesRef term) {
+ return LongPoint.decodeDimension(term.bytes, term.offset);
+ }
+
+ @Override
+ public Object toObject(IndexableField f) {
+ final Number val = f.numericValue();
+ if (val != null) {
+ return val;
+ } else {
+ throw new AssertionError("Unexpected state. Field: '" + f + "'");
+ }
+ }
+
+ @Override
+ protected Query getExactQuery(SchemaField field, String externalVal) {
+ return LongPoint.newExactQuery(field.getName(), Long.parseLong(externalVal));
+ }
+
+ @Override
+ public Query getSetQuery(QParser parser, SchemaField field, Collection<String> externalVal) {
+ assert externalVal.size() > 0;
+ long[] values = new long[externalVal.size()];
+ int i = 0;
+ for (String val:externalVal) {
+ values[i] = Long.parseLong(val);
+ i++;
+ }
+ return LongPoint.newSetQuery(field.getName(), values);
+ }
+
+ @Override
+ protected String indexedToReadable(BytesRef indexedForm) {
+ return Long.toString(LongPoint.decodeDimension(indexedForm.bytes, indexedForm.offset));
+ }
+
+ @Override
+ public void readableToIndexed(CharSequence val, BytesRefBuilder result) {
+ result.grow(Long.BYTES);
+ result.setLength(Long.BYTES);
+ LongPoint.encodeDimension(Long.parseLong(val.toString()), result.bytes(), 0);
+ }
+
+ @Override
+ public SortField getSortField(SchemaField field, boolean top) {
+ field.checkSortability();
+
+ Object missingValue = null;
+ boolean sortMissingLast = field.sortMissingLast();
+ boolean sortMissingFirst = field.sortMissingFirst();
+
+ if (sortMissingLast) {
+ missingValue = top ? Long.MIN_VALUE : Long.MAX_VALUE;
+ } else if (sortMissingFirst) {
+ missingValue = top ? Long.MAX_VALUE : Long.MIN_VALUE;
+ }
+ SortField sf = new SortField(field.getName(), SortField.Type.LONG, top);
+ sf.setMissingValue(missingValue);
+ return sf;
+ }
+
+ @Override
+ public Type getUninversionType(SchemaField sf) {
+ if (sf.multiValued()) {
+ throw new UnsupportedOperationException("MultiValued Point fields with DocValues is not currently supported");
+// return Type.SORTED_LONG;
+ } else {
+ return Type.LONG_POINT;
+ }
+ }
+
+ @Override
+ public ValueSource getValueSource(SchemaField field, QParser qparser) {
+ field.checkFieldCacheSource();
+ return new LongFieldSource(field.getName());
+ }
+
+ @Override
+ public LegacyNumericType getNumericType() {
+ return LegacyNumericType.LONG;
+ }
+
+ @Override
+ public IndexableField createField(SchemaField field, Object value, float boost) {
+ if (!isFieldUsed(field)) return null;
+
+ if (boost != 1.0 && log.isTraceEnabled()) {
+ log.trace("Can't use document/field boost for PointField. Field: " + field.getName() + ", boost: " + boost);
+ }
+ long longValue = (value instanceof Number) ? ((Number) value).longValue() : Long.parseLong(value.toString());
+ return new LongPoint(field.getName(), longValue);
+ }
+
+ @Override
+ protected StoredField getStoredField(SchemaField sf, Object value) {
+ return new StoredField(sf.getName(), (Long) this.toNativeType(value));
+ }
+
+ @Override
+ public PointTypes getType() {
+ return PointTypes.LONG;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/PointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/PointField.java b/solr/core/src/java/org/apache/solr/schema/PointField.java
new file mode 100644
index 0000000..a2dd8a8
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/schema/PointField.java
@@ -0,0 +1,233 @@
+/*
+ * 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.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortedSetSelector;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.lucene.util.CharsRef;
+import org.apache.lucene.util.CharsRefBuilder;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.response.TextResponseWriter;
+import org.apache.solr.search.QParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides field types to support for Lucene's {@link
+ * org.apache.lucene.document.IntPoint}, {@link org.apache.lucene.document.LongPoint}, {@link org.apache.lucene.document.FloatPoint} and
+ * {@link org.apache.lucene.document.DoublePoint}.
+ * See {@link org.apache.lucene.search.PointRangeQuery} for more details.
+ * It supports integer, float, long and double types. See subclasses for details.
+ * <br>
+ * {@code DocValues} are supported for single-value cases ({@code NumericDocValues}).
+ * {@code FieldCache} is not supported for {@code PointField}s, so sorting, faceting, etc on these fields require the use of {@code docValues="true"} in the schema.
+ */
+public abstract class PointField extends PrimitiveFieldType {
+
+ public enum PointTypes {
+ INTEGER,
+ LONG,
+ FLOAT,
+ DOUBLE,
+ DATE
+ }
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public boolean isPointField() {
+ return true;
+ }
+
+ @Override
+ public final ValueSource getSingleValueSource(MultiValueSelector choice, SchemaField field, QParser parser) {
+ // trivial base case
+ if (!field.multiValued()) {
+ // single value matches any selector
+ return getValueSource(field, parser);
+ }
+
+ // Point fields don't support UninvertingReader. See SOLR-9202
+ if (!field.hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ "docValues='true' is required to select '" + choice.toString() +
+ "' value from multivalued field ("+ field.getName() +") at query time");
+ }
+
+ // multivalued Point fields all use SortedSetDocValues, so we give a clean error if that's
+ // not supported by the specified choice, else we delegate to a helper
+ SortedSetSelector.Type selectorType = choice.getSortedSetSelectorType();
+ if (null == selectorType) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ choice.toString() + " is not a supported option for picking a single value"
+ + " from the multivalued field: " + field.getName() +
+ " (type: " + this.getTypeName() + ")");
+ }
+
+ return getSingleValueSource(selectorType, field);
+ }
+
+ /**
+ * Helper method that will only be called for multivalued Point fields that have doc values.
+ * Default impl throws an error indicating that selecting a single value from this multivalued
+ * field is not supported for this field type
+ *
+ * @param choice the selector Type to use, will never be null
+ * @param field the field to use, guaranteed to be multivalued.
+ * @see #getSingleValueSource(MultiValueSelector,SchemaField,QParser)
+ */
+ protected ValueSource getSingleValueSource(SortedSetSelector.Type choice, SchemaField field) {
+ throw new UnsupportedOperationException("MultiValued Point fields with DocValues is not currently supported");
+ }
+
+ @Override
+ public boolean isTokenized() {
+ return false;
+ }
+
+ @Override
+ public boolean multiValuedFieldCache() {
+ return false;
+ }
+
+ /**
+ * @return the type of this field
+ */
+ public abstract PointTypes getType();
+
+ @Override
+ public abstract Query getSetQuery(QParser parser, SchemaField field, Collection<String> externalVals);
+
+ @Override
+ public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
+ if (!field.indexed() && field.hasDocValues()) {
+ // currently implemented as singleton range
+ return getRangeQuery(parser, field, externalVal, externalVal, true, true);
+ } else {
+ return getExactQuery(field, externalVal);
+ }
+ }
+
+ protected abstract Query getExactQuery(SchemaField field, String externalVal);
+
+ @Override
+ public String storedToReadable(IndexableField f) {
+ return toExternal(f);
+ }
+
+ @Override
+ public String toInternal(String val) {
+ throw new UnsupportedOperationException("Can't generate internal string in PointField. use PointField.toInternalByteRef");
+ }
+
+ public BytesRef toInternalByteRef(String val) {
+ final BytesRefBuilder bytes = new BytesRefBuilder();
+ readableToIndexed(val, bytes);
+ return bytes.get();
+ }
+
+ @Override
+ public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+ writer.writeVal(name, toObject(f));
+ }
+
+ @Override
+ public String storedToIndexed(IndexableField f) {
+ throw new UnsupportedOperationException("Not supported with PointFields");
+ }
+
+ @Override
+ public CharsRef indexedToReadable(BytesRef indexedForm, CharsRefBuilder charsRef) {
+ final String value = indexedToReadable(indexedForm);
+ charsRef.grow(value.length());
+ charsRef.setLength(value.length());
+ value.getChars(0, charsRef.length(), charsRef.chars(), 0);
+ return charsRef.get();
+ }
+
+ @Override
+ public String indexedToReadable(String indexedForm) {
+ return indexedToReadable(new BytesRef(indexedForm));
+ }
+
+ protected abstract String indexedToReadable(BytesRef indexedForm);
+
+ protected boolean isFieldUsed(SchemaField field) {
+ boolean indexed = field.indexed();
+ boolean stored = field.stored();
+ boolean docValues = field.hasDocValues();
+
+ if (!indexed && !stored && !docValues) {
+ if (log.isTraceEnabled()) {
+ log.trace("Ignoring unindexed/unstored field: " + field);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public List<IndexableField> createFields(SchemaField sf, Object value, float boost) {
+ if (!(sf.hasDocValues() || sf.stored())) {
+ return Collections.singletonList(createField(sf, value, boost));
+ }
+ List<IndexableField> fields = new ArrayList<>();
+ final IndexableField field = createField(sf, value, boost);
+ fields.add(field);
+
+ if (sf.hasDocValues()) {
+ if (sf.multiValued()) {
+ throw new UnsupportedOperationException("MultiValued Point fields with DocValues is not currently supported. Field: '" + sf.getName() + "'");
+ } else {
+ final long bits;
+ if (field.numericValue() instanceof Integer || field.numericValue() instanceof Long) {
+ bits = field.numericValue().longValue();
+ } else if (field.numericValue() instanceof Float) {
+ bits = Float.floatToIntBits(field.numericValue().floatValue());
+ } else {
+ assert field.numericValue() instanceof Double;
+ bits = Double.doubleToLongBits(field.numericValue().doubleValue());
+ }
+ fields.add(new NumericDocValuesField(sf.getName(), bits));
+ }
+ }
+ if (sf.stored()) {
+ fields.add(getStoredField(sf, value));
+ }
+ return fields;
+ }
+
+ protected abstract StoredField getStoredField(SchemaField sf, Object value);
+
+ @Override
+ public void checkSchemaField(final SchemaField field) {
+ // PointFields support DocValues
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/schema/SchemaField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaField.java b/solr/core/src/java/org/apache/solr/schema/SchemaField.java
index bcd68c2..009e5fc 100644
--- a/solr/core/src/java/org/apache/solr/schema/SchemaField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SchemaField.java
@@ -170,6 +170,11 @@ public final class SchemaField extends FieldProperties implements IndexableField
"can not sort on multivalued field: "
+ getName());
}
+ if (this.type.isPointField() && !hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ "can not sort on a PointField without doc values: "
+ + getName());
+ }
}
/**
@@ -191,6 +196,11 @@ public final class SchemaField extends FieldProperties implements IndexableField
"can not use FieldCache on multivalued field: "
+ getName());
}
+ if (this.type.isPointField() && !hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ "Point fields can't use FieldCache. Use docValues=true for field: "
+ + getName());
+ }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
index 6d13b51..7c56311 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -98,6 +98,7 @@ import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.BoolField;
import org.apache.solr.schema.EnumField;
import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.PointField;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieDateField;
import org.apache.solr.schema.TrieDoubleField;
@@ -821,16 +822,39 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
continue;
}
Object newVal = val;
- if (schemaField.getType() instanceof TrieIntField) {
- newVal = val.intValue();
- } else if (schemaField.getType() instanceof TrieFloatField) {
- newVal = Float.intBitsToFloat(val.intValue());
- } else if (schemaField.getType() instanceof TrieDoubleField) {
- newVal = Double.longBitsToDouble(val);
- } else if (schemaField.getType() instanceof TrieDateField) {
- newVal = new Date(val);
- } else if (schemaField.getType() instanceof EnumField) {
- newVal = ((EnumField) schemaField.getType()).intValueToStringValue(val.intValue());
+ if (schemaField.getType().isPointField()) {
+ PointField.PointTypes type = ((PointField)schemaField.getType()).getType();
+ switch (type) {
+ case INTEGER:
+ newVal = val.intValue();
+ break;
+ case LONG:
+ newVal = val.longValue();
+ break;
+ case FLOAT:
+ newVal = Float.intBitsToFloat(val.intValue());
+ break;
+ case DOUBLE:
+ newVal = Double.longBitsToDouble(val);
+ break;
+ case DATE:
+ newVal = new Date(val);
+ break;
+ default:
+ throw new AssertionError("Unexpected PointType: " + type);
+ }
+ } else {
+ if (schemaField.getType() instanceof TrieIntField) {
+ newVal = val.intValue();
+ } else if (schemaField.getType() instanceof TrieFloatField) {
+ newVal = Float.intBitsToFloat(val.intValue());
+ } else if (schemaField.getType() instanceof TrieDoubleField) {
+ newVal = Double.longBitsToDouble(val);
+ } else if (schemaField.getType() instanceof TrieDateField) {
+ newVal = new Date(val);
+ } else if (schemaField.getType() instanceof EnumField) {
+ newVal = ((EnumField) schemaField.getType()).intValueToStringValue(val.intValue());
+ }
}
doc.addField(fieldName, newVal);
break;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/search/TermQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/TermQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/TermQParserPlugin.java
index 99ef4c4..89b3d28 100644
--- a/solr/core/src/java/org/apache/solr/search/TermQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/TermQParserPlugin.java
@@ -50,10 +50,16 @@ public class TermQParserPlugin extends QParserPlugin {
String fname = localParams.get(QueryParsing.F);
FieldType ft = req.getSchema().getFieldTypeNoEx(fname);
String val = localParams.get(QueryParsing.V);
- BytesRefBuilder term = new BytesRefBuilder();
+ BytesRefBuilder term;
if (ft != null) {
- ft.readableToIndexed(val, term);
+ if (ft.isPointField()) {
+ return ft.getFieldQuery(this, req.getSchema().getField(fname), val);
+ } else {
+ term = new BytesRefBuilder();
+ ft.readableToIndexed(val, term);
+ }
} else {
+ term = new BytesRefBuilder();
term.copyChars(val);
}
return new TermQuery(new Term(fname, term.get()));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/search/TermsQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/TermsQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/TermsQParserPlugin.java
index 3a60149..c407353 100644
--- a/solr/core/src/java/org/apache/solr/search/TermsQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/TermsQParserPlugin.java
@@ -17,6 +17,7 @@
package org.apache.solr.search;
import java.util.Arrays;
+import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.lucene.index.Term;
@@ -35,6 +36,7 @@ import org.apache.lucene.util.automaton.Automaton;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.PointField;
/**
* Finds documents whose specified field has any of the specified values. It's like
@@ -110,6 +112,14 @@ public class TermsQParserPlugin extends QParserPlugin {
return new MatchNoDocsQuery();
final String[] splitVals = sepIsSpace ? qstr.split("\\s+") : qstr.split(Pattern.quote(separator), -1);
assert splitVals.length > 0;
+
+ if (ft.isPointField()) {
+ if (localParams.get(METHOD) != null) {
+ throw new IllegalArgumentException(
+ String.format(Locale.ROOT, "Method '%s' not supported in TermsQParser when using PointFields", localParams.get(METHOD)));
+ }
+ return ((PointField)ft).getSetQuery(this, req.getSchema().getField(fname), Arrays.asList(splitVals));
+ }
BytesRef[] bytesRefs = new BytesRef[splitVals.length];
BytesRefBuilder term = new BytesRefBuilder();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java b/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
index 99f6fce..900bbf7 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
@@ -30,6 +30,7 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.PointField;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieDateField;
import org.apache.solr.schema.TrieField;
@@ -141,7 +142,32 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
(SolrException.ErrorCode.BAD_REQUEST,
"Expected numeric field type :" + sf);
}
- } else {
+ } else if (ft instanceof PointField) {
+ final PointField pfield = (PointField)ft;
+
+ switch (pfield.getType()) {
+ case FLOAT:
+ calc = new FloatCalc(sf);
+ break;
+ case DOUBLE:
+ calc = new DoubleCalc(sf);
+ break;
+ case INTEGER:
+ calc = new IntCalc(sf);
+ break;
+ case LONG:
+ calc = new LongCalc(sf);
+ break;
+ case DATE:
+ calc = new DateCalc(sf, null);
+ break;
+ default:
+ throw new SolrException
+ (SolrException.ErrorCode.BAD_REQUEST,
+ "Expected numeric field type :" + sf);
+ }
+ }
+ else {
throw new SolrException
(SolrException.ErrorCode.BAD_REQUEST,
"Expected numeric field type :" + sf);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/java/org/apache/solr/spelling/suggest/DocumentExpressionDictionaryFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/spelling/suggest/DocumentExpressionDictionaryFactory.java b/solr/core/src/java/org/apache/solr/spelling/suggest/DocumentExpressionDictionaryFactory.java
index b0d7007..3b7abdf 100644
--- a/solr/core/src/java/org/apache/solr/spelling/suggest/DocumentExpressionDictionaryFactory.java
+++ b/solr/core/src/java/org/apache/solr/spelling/suggest/DocumentExpressionDictionaryFactory.java
@@ -28,7 +28,11 @@ import org.apache.lucene.search.SortField;
import org.apache.lucene.search.spell.Dictionary;
import org.apache.lucene.search.suggest.DocumentValueSourceDictionary;
import org.apache.solr.core.SolrCore;
+import org.apache.solr.schema.DoublePointField;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.FloatPointField;
+import org.apache.solr.schema.IntPointField;
+import org.apache.solr.schema.LongPointField;
import org.apache.solr.schema.TrieDoubleField;
import org.apache.solr.schema.TrieFloatField;
import org.apache.solr.schema.TrieIntField;
@@ -111,13 +115,13 @@ public class DocumentExpressionDictionaryFactory extends DictionaryFactory {
SortField.Type type = null;
String fieldTypeName = core.getLatestSchema().getField(sortFieldName).getType().getTypeName();
FieldType ft = core.getLatestSchema().getFieldTypes().get(fieldTypeName);
- if (ft instanceof TrieFloatField) {
+ if (ft instanceof TrieFloatField || ft instanceof FloatPointField) {
type = SortField.Type.FLOAT;
- } else if (ft instanceof TrieIntField) {
+ } else if (ft instanceof TrieIntField || ft instanceof IntPointField) {
type = SortField.Type.INT;
- } else if (ft instanceof TrieLongField) {
+ } else if (ft instanceof TrieLongField || ft instanceof LongPointField) {
type = SortField.Type.LONG;
- } else if (ft instanceof TrieDoubleField) {
+ } else if (ft instanceof TrieDoubleField || ft instanceof DoublePointField) {
type = SortField.Type.DOUBLE;
}
return type;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml b/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml
index 79d200d..ff73fdc 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml
@@ -24,12 +24,18 @@
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+
+ <!-- Point Fields -->
+ <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
+ <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+ <fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>
+ <fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
<field name="id" type="string" indexed="true" stored="true" docValues="false" multiValued="false" required="true"/>
<field name="id_dv" type="string" indexed="false" stored="false" docValues="true" multiValued="false"
required="true"/>
<dynamicField name="*_i" type="int" indexed="true" stored="false" docValues="false"/>
- <dynamicField name="*_i_dv" type="int" indexed="false" stored="false" docValues="true"/>
+ <dynamicField name="*_i_dv" type="${solr.tests.intClass:pint}" indexed="false" stored="false" docValues="true"/>
<dynamicField name="*_is" type="int" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_is_dv" type="int" indexed="false" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="false" docValues="false"/>
@@ -37,13 +43,13 @@
<dynamicField name="*_ss" type="string" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_ss_dv" type="string" indexed="false" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_f" type="float" indexed="true" stored="false" docValues="false"/>
- <dynamicField name="*_f_dv" type="float" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_f_dv" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_fs_dv" type="float" indexed="true" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_l" type="long" indexed="true" stored="false" docValues="false"/>
- <dynamicField name="*_l_dv" type="long" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_l_dv" type="${solr.tests.longClass:plong}" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_ls_dv" type="long" indexed="true" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_d" type="double" indexed="true" stored="false" docValues="false"/>
- <dynamicField name="*_d_dv" type="double" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_d_dv" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_ds_dv" type="double" indexed="true" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_dt" type="date" indexed="true" stored="false" docValues="false"/>
<dynamicField name="*_dt_dv" type="date" indexed="true" stored="false" docValues="true"/>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/57934ba4/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
index 113e868..673e7dd 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
@@ -23,12 +23,17 @@
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
+ <fieldType name="pint" class="solr.IntPointField"/>
+ <fieldType name="plong" class="solr.LongPointField"/>
+ <fieldType name="pdouble" class="solr.DoublePointField"/>
+ <fieldType name="pfloat" class="solr.FloatPointField"/>
<field name="id" type="string" indexed="true" stored="true" docValues="false" multiValued="false" required="true"/>
<field name="id_dv" type="string" indexed="false" stored="false" docValues="true" multiValued="false"
required="true"/>
<dynamicField name="*_i" type="int" indexed="true" stored="false" docValues="false"/>
<dynamicField name="*_i_dv" type="int" indexed="false" stored="false" docValues="true"/>
+ <dynamicField name="*_i_p" type="pint" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_is" type="int" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_is_dv" type="int" indexed="false" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="false" docValues="false"/>
@@ -37,14 +42,17 @@
<dynamicField name="*_ss_dv" type="string" indexed="false" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_f" type="float" indexed="true" stored="false" docValues="false"/>
<dynamicField name="*_f_dv" type="float" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_f_p" type="pfloat" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_fs" type="float" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_fs_dv" type="float" indexed="true" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_l" type="long" indexed="true" stored="false" docValues="false"/>
<dynamicField name="*_l_dv" type="long" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_l_p" type="plong" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_ls" type="long" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_ls_dv" type="long" indexed="true" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_d" type="double" indexed="true" stored="false" docValues="false"/>
<dynamicField name="*_d_dv" type="double" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_d_p" type="pdouble" indexed="true" stored="false" docValues="true"/>
<dynamicField name="*_ds" type="double" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_ds_dv" type="double" indexed="true" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_dt" type="date" indexed="true" stored="false" docValues="false"/>
@@ -55,11 +63,15 @@
<uniqueKey>id</uniqueKey>
<copyField source="*_i" dest="*_i_dv"/>
+ <copyField source="*_i" dest="*_i_p"/>
<copyField source="*_f" dest="*_f_dv"/>
+ <copyField source="*_f" dest="*_f_p"/>
<copyField source="*_is" dest="*_is_dv"/>
<copyField source="*_s" dest="*_s_dv"/>
<copyField source="*_l" dest="*_l_dv"/>
+ <copyField source="*_l" dest="*_l_p"/>
<copyField source="*_d" dest="*_d_dv"/>
+ <copyField source="*_d" dest="*_d_p"/>
<copyField source="*_ss" dest="*_ss_dv"/>
<copyField source="*_is" dest="*_is_dv"/>
<copyField source="*_fs" dest="*_fs_dv"/>