gerlowskija commented on code in PR #3922:
URL: https://github.com/apache/solr/pull/3922#discussion_r3095339624


##########
solr/core/src/java/org/apache/solr/schema/NumericField.java:
##########
@@ -0,0 +1,384 @@
+/*
+ * 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.Date;
+import java.util.List;
+import java.util.Map;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.document.SortedNumericDocValuesField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.IndexOrDocValuesQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.SortedNumericSelector;
+import org.apache.lucene.search.SortedNumericSortField;
+import org.apache.lucene.search.TermInSetQuery;
+import org.apache.lucene.search.TermQuery;
+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.lucene.util.NumericUtils;
+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 NumericField extends PrimitiveFieldType {
+
+  protected NumberType type;
+
+  /**
+   * @return the type of this field
+   */
+  @Override
+  public NumberType getNumberType() {
+    return type;
+  }
+
+  private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  /**
+   * The Test framework can set this global variable to instruct PointField 
that (on init) it should
+   * be tolerant of the <code>precisionStep</code> argument used by 
TrieFields. This allows for
+   * simple randomization of TrieFields and PointFields w/o extensive 
duplication of <code>
+   * &lt;fieldType/&gt;</code> declarations.
+   *
+   * <p>NOTE: When {@link TrieField} is removed, this boolean must also be 
removed
+   *
+   * @lucene.internal
+   * @lucene.experimental
+   */
+  public static boolean TEST_HACK_IGNORE_USELESS_TRIEFIELD_ARGS = false;

Review Comment:
   [Q] Does our test randomization now include these field types in addition to 
Trie and Point?  If not, is this line intended or perhaps a copy-paste error?



##########
solr/core/src/java/org/apache/solr/schema/IntField.java:
##########
@@ -0,0 +1,331 @@
+/*
+ * 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.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.InvertableType;
+import org.apache.lucene.document.SortedNumericDocValuesField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StoredValue;
+import org.apache.lucene.index.DocValuesType;
+import org.apache.lucene.index.IndexOptions;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.queries.function.ValueSource;
+import 
org.apache.lucene.queries.function.valuesource.MultiValuedIntFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortedNumericSelector;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+
+/**
+ * An {@code NumericField} implementation of a field for {@code Int} values 
using {@code IntPoint}, {@code StringField}, {@code 
SortedNumericDocValuesField} and {@code StoredField}.

Review Comment:
   ```suggestion
    * A {@code NumericField} implementation of a field for {@code Int} values 
using {@code IntPoint}, {@code StringField}, {@code 
SortedNumericDocValuesField} and {@code StoredField}.
   ```



##########
solr/core/src/java/org/apache/solr/schema/IntField.java:
##########
@@ -0,0 +1,331 @@
+/*
+ * 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.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.InvertableType;
+import org.apache.lucene.document.SortedNumericDocValuesField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StoredValue;
+import org.apache.lucene.index.DocValuesType;
+import org.apache.lucene.index.IndexOptions;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.queries.function.ValueSource;
+import 
org.apache.lucene.queries.function.valuesource.MultiValuedIntFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortedNumericSelector;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+
+/**
+ * An {@code NumericField} implementation of a field for {@code Int} values 
using {@code IntPoint}, {@code StringField}, {@code 
SortedNumericDocValuesField} and {@code StoredField}.
+ *
+ * @see PointField
+ * @see IntPoint
+ */
+public class IntField extends NumericField implements IntValueFieldType {
+
+  public IntField() {
+    type = NumberType.INTEGER;
+  }
+
+  @Override
+  public Object toNativeType(Object val) {
+    if (val == null) return null;
+    if (val instanceof Number) return ((Number) val).intValue();
+    if (val instanceof CharSequence) return Integer.parseInt(val.toString());
+    return super.toNativeType(val);
+  }
+
+  @Override
+  public Query getPointFieldQuery(QParser parser, SchemaField field, String 
value) {
+    return IntPoint.newExactQuery(field.getName(), 
parseIntFromUser(field.getName(), value));
+  }
+
+  @Override
+  public Query getDocValuesFieldQuery(QParser parser, SchemaField field, 
String value) {
+    return SortedNumericDocValuesField.newSlowExactQuery(field.getName(), 
parseIntFromUser(field.getName(), value));
+  }
+
+  @Override
+  public Query getPointRangeQuery(
+      QParser parser,
+      SchemaField field,
+      String min,
+      String max,
+      boolean minInclusive,
+      boolean maxInclusive) {
+    int actualMin, actualMax;
+    if (min == null) {
+      actualMin = Integer.MIN_VALUE;
+    } else {
+      actualMin = parseIntFromUser(field.getName(), min);
+      if (!minInclusive) {
+        if (actualMin == Integer.MAX_VALUE) return new MatchNoDocsQuery();
+        ++actualMin;
+      }
+    }
+    if (max == null) {
+      actualMax = Integer.MAX_VALUE;
+    } else {
+      actualMax = parseIntFromUser(field.getName(), max);
+      if (!maxInclusive) {
+        if (actualMax == Integer.MIN_VALUE) return new MatchNoDocsQuery();
+        --actualMax;
+      }
+    }
+    return IntPoint.newRangeQuery(field.getName(), actualMin, actualMax);
+  }
+
+  @Override
+  public Query getDocValuesRangeQuery(
+      QParser parser,
+      SchemaField field,
+      String min,
+      String max,
+      boolean minInclusive,
+      boolean maxInclusive) {
+    int actualMin, actualMax;
+    if (min == null) {
+      actualMin = Integer.MIN_VALUE;
+    } else {
+      actualMin = parseIntFromUser(field.getName(), min);
+      if (!minInclusive) {
+        if (actualMin == Integer.MAX_VALUE) return new MatchNoDocsQuery();
+        ++actualMin;
+      }
+    }
+    if (max == null) {
+      actualMax = Integer.MAX_VALUE;
+    } else {
+      actualMax = parseIntFromUser(field.getName(), max);
+      if (!maxInclusive) {
+        if (actualMax == Integer.MIN_VALUE) return new MatchNoDocsQuery();
+        --actualMax;
+      }
+    }
+    return SortedNumericDocValuesField.newSlowRangeQuery(field.getName(), 
actualMin, actualMax);
+  }
+
+  @Override
+  public Query getPointSetQuery(QParser parser, SchemaField field, 
Collection<String> externalVals) {
+    int[] values = new int[externalVals.size()];
+    int i = 0;
+    for (String val : externalVals) {
+      values[i++] = parseIntFromUser(field.getName(), val);
+    }
+    return IntPoint.newSetQuery(field.getName(), values);
+  }
+
+  @Override
+  public Query getDocValuesSetQuery(QParser parser, SchemaField field, 
Collection<String> externalVals) {
+    long[] points = new long[externalVals.size()];
+    int i = 0;
+    for (String val : externalVals) {
+      points[i++] = parseIntFromUser(field.getName(), val);
+    }
+    return SortedNumericDocValuesField.newSlowSetQuery(field.getName(), 
points);
+  }
+
+  @Override
+  public Object toObject(SchemaField sf, BytesRef term) {
+    return IntPoint.decodeDimension(term.bytes, term.offset);
+  }
+
+  @Override
+  public Object toObject(IndexableField f) {
+    final StoredValue storedValue = f.storedValue();
+    if (storedValue != null) {
+      return storedValue.getIntValue();
+    }
+    final Number val = f.numericValue();
+    if (val != null) {
+      return val.intValue();
+    } else {
+      throw new AssertionError("Unexpected state. Field: '" + f + "'");
+    }
+  }
+
+  @Override
+  public String storedToReadable(IndexableField f) {
+    return Integer.toString(f.storedValue().getIntValue());
+  }
+
+  @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(parseIntFromUser(null, val.toString()), 
result.bytes(), 0);
+  }
+
+  @Override
+  public Type getUninversionType(SchemaField sf) {
+    if (sf.multiValued()) {
+      return null;
+    } else {
+      return Type.INTEGER_POINT;
+    }
+  }
+
+  @Override
+  public ValueSource getValueSource(SchemaField field, QParser qparser) {
+    field.checkFieldCacheSource();
+    return new MultiValuedIntFieldSource(field.getName(), 
SortedNumericSelector.Type.MIN);
+  }
+
+  @Override
+  protected ValueSource getSingleValueSource(SortedNumericSelector.Type 
choice, SchemaField f) {
+    return new MultiValuedIntFieldSource(f.getName(), choice);
+  }
+
+  @Override
+  public List<IndexableField> createFields(SchemaField sf, Object value) {
+    int intValue =
+        (value instanceof Number)
+            ? ((Number) value).intValue()
+            : Integer.parseInt(value.toString());
+    return Collections.singletonList(new SolrIntField(sf.getName(), intValue, 
sf.indexed(), sf.enhancedIndex(), sf.hasDocValues(), sf.stored()));
+  }
+
+  @Override
+  public IndexableField createField(SchemaField field, Object value) {
+    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));
+  }
+
+  /**
+   * Wrapper for {@link Integer#parseInt(String)} that throws a BAD_REQUEST 
error if the input is
+   * not valid
+   *
+   * @param fieldName used in any exception, may be null
+   * @param val string to parse, NPE if null
+   */
+  static int parseIntFromUser(String fieldName, String val) {
+    if (val == null) {
+      throw new NullPointerException(
+          "Invalid input" + (null == fieldName ? "" : " for field " + 
fieldName));
+    }
+    try {
+      return Integer.parseInt(val);
+    } catch (NumberFormatException e) {
+      String msg = "Invalid Number: " + val + (null == fieldName ? "" : " for 
field " + fieldName);
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, msg);
+    }
+  }
+
+  static final class SolrIntField extends Field {
+
+    static org.apache.lucene.document.FieldType getType(boolean rangeIndex, 
boolean termIndex, boolean docValues, boolean stored) {
+      org.apache.lucene.document.FieldType type = new 
org.apache.lucene.document.FieldType();
+      if (rangeIndex) {
+        type.setDimensions(1, Integer.BYTES);
+      }
+      if (termIndex) {
+        type.setIndexOptions(IndexOptions.DOCS);
+      }
+      if (docValues) {
+        type.setDocValuesType(DocValuesType.SORTED_NUMERIC);
+      }
+      type.setTokenized(false);
+      type.setStored(stored);
+      type.freeze();
+      return type;
+    }
+
+    private final StoredValue storedValue;
+
+    /**
+     * Creates a new IntField, indexing the provided point and term, storing 
it as a DocValue, and optionally

Review Comment:
   ```suggestion
        * Creates a new SolrIntField, indexing the provided point and term, 
storing it as a DocValue, and optionally
   ```



##########
solr/core/src/java/org/apache/solr/schema/IntField.java:
##########
@@ -0,0 +1,331 @@
+/*
+ * 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.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.InvertableType;
+import org.apache.lucene.document.SortedNumericDocValuesField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StoredValue;
+import org.apache.lucene.index.DocValuesType;
+import org.apache.lucene.index.IndexOptions;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.queries.function.ValueSource;
+import 
org.apache.lucene.queries.function.valuesource.MultiValuedIntFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortedNumericSelector;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.search.QParser;
+import org.apache.solr.uninverting.UninvertingReader.Type;
+
+/**
+ * An {@code NumericField} implementation of a field for {@code Int} values 
using {@code IntPoint}, {@code StringField}, {@code 
SortedNumericDocValuesField} and {@code StoredField}.
+ *
+ * @see PointField
+ * @see IntPoint
+ */
+public class IntField extends NumericField implements IntValueFieldType {
+
+  public IntField() {
+    type = NumberType.INTEGER;
+  }
+
+  @Override
+  public Object toNativeType(Object val) {
+    if (val == null) return null;
+    if (val instanceof Number) return ((Number) val).intValue();
+    if (val instanceof CharSequence) return Integer.parseInt(val.toString());
+    return super.toNativeType(val);
+  }
+
+  @Override
+  public Query getPointFieldQuery(QParser parser, SchemaField field, String 
value) {
+    return IntPoint.newExactQuery(field.getName(), 
parseIntFromUser(field.getName(), value));
+  }
+
+  @Override
+  public Query getDocValuesFieldQuery(QParser parser, SchemaField field, 
String value) {
+    return SortedNumericDocValuesField.newSlowExactQuery(field.getName(), 
parseIntFromUser(field.getName(), value));
+  }
+
+  @Override
+  public Query getPointRangeQuery(
+      QParser parser,
+      SchemaField field,
+      String min,
+      String max,
+      boolean minInclusive,
+      boolean maxInclusive) {
+    int actualMin, actualMax;
+    if (min == null) {
+      actualMin = Integer.MIN_VALUE;
+    } else {
+      actualMin = parseIntFromUser(field.getName(), min);
+      if (!minInclusive) {
+        if (actualMin == Integer.MAX_VALUE) return new MatchNoDocsQuery();
+        ++actualMin;
+      }
+    }
+    if (max == null) {
+      actualMax = Integer.MAX_VALUE;
+    } else {
+      actualMax = parseIntFromUser(field.getName(), max);
+      if (!maxInclusive) {
+        if (actualMax == Integer.MIN_VALUE) return new MatchNoDocsQuery();
+        --actualMax;
+      }
+    }
+    return IntPoint.newRangeQuery(field.getName(), actualMin, actualMax);
+  }
+
+  @Override
+  public Query getDocValuesRangeQuery(
+      QParser parser,
+      SchemaField field,
+      String min,
+      String max,
+      boolean minInclusive,
+      boolean maxInclusive) {
+    int actualMin, actualMax;
+    if (min == null) {
+      actualMin = Integer.MIN_VALUE;
+    } else {
+      actualMin = parseIntFromUser(field.getName(), min);
+      if (!minInclusive) {
+        if (actualMin == Integer.MAX_VALUE) return new MatchNoDocsQuery();
+        ++actualMin;
+      }
+    }
+    if (max == null) {
+      actualMax = Integer.MAX_VALUE;
+    } else {
+      actualMax = parseIntFromUser(field.getName(), max);
+      if (!maxInclusive) {
+        if (actualMax == Integer.MIN_VALUE) return new MatchNoDocsQuery();
+        --actualMax;
+      }
+    }
+    return SortedNumericDocValuesField.newSlowRangeQuery(field.getName(), 
actualMin, actualMax);
+  }
+
+  @Override
+  public Query getPointSetQuery(QParser parser, SchemaField field, 
Collection<String> externalVals) {
+    int[] values = new int[externalVals.size()];
+    int i = 0;
+    for (String val : externalVals) {
+      values[i++] = parseIntFromUser(field.getName(), val);
+    }
+    return IntPoint.newSetQuery(field.getName(), values);
+  }
+
+  @Override
+  public Query getDocValuesSetQuery(QParser parser, SchemaField field, 
Collection<String> externalVals) {
+    long[] points = new long[externalVals.size()];
+    int i = 0;
+    for (String val : externalVals) {
+      points[i++] = parseIntFromUser(field.getName(), val);
+    }
+    return SortedNumericDocValuesField.newSlowSetQuery(field.getName(), 
points);
+  }
+
+  @Override
+  public Object toObject(SchemaField sf, BytesRef term) {
+    return IntPoint.decodeDimension(term.bytes, term.offset);
+  }
+
+  @Override
+  public Object toObject(IndexableField f) {
+    final StoredValue storedValue = f.storedValue();
+    if (storedValue != null) {
+      return storedValue.getIntValue();
+    }
+    final Number val = f.numericValue();
+    if (val != null) {
+      return val.intValue();
+    } else {
+      throw new AssertionError("Unexpected state. Field: '" + f + "'");
+    }
+  }
+
+  @Override
+  public String storedToReadable(IndexableField f) {
+    return Integer.toString(f.storedValue().getIntValue());
+  }
+
+  @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(parseIntFromUser(null, val.toString()), 
result.bytes(), 0);
+  }
+
+  @Override
+  public Type getUninversionType(SchemaField sf) {
+    if (sf.multiValued()) {
+      return null;
+    } else {
+      return Type.INTEGER_POINT;
+    }
+  }
+
+  @Override
+  public ValueSource getValueSource(SchemaField field, QParser qparser) {
+    field.checkFieldCacheSource();
+    return new MultiValuedIntFieldSource(field.getName(), 
SortedNumericSelector.Type.MIN);
+  }
+
+  @Override
+  protected ValueSource getSingleValueSource(SortedNumericSelector.Type 
choice, SchemaField f) {
+    return new MultiValuedIntFieldSource(f.getName(), choice);
+  }
+
+  @Override
+  public List<IndexableField> createFields(SchemaField sf, Object value) {
+    int intValue =
+        (value instanceof Number)
+            ? ((Number) value).intValue()
+            : Integer.parseInt(value.toString());
+    return Collections.singletonList(new SolrIntField(sf.getName(), intValue, 
sf.indexed(), sf.enhancedIndex(), sf.hasDocValues(), sf.stored()));
+  }
+
+  @Override
+  public IndexableField createField(SchemaField field, Object value) {
+    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));
+  }
+
+  /**
+   * Wrapper for {@link Integer#parseInt(String)} that throws a BAD_REQUEST 
error if the input is
+   * not valid
+   *
+   * @param fieldName used in any exception, may be null
+   * @param val string to parse, NPE if null
+   */
+  static int parseIntFromUser(String fieldName, String val) {
+    if (val == null) {
+      throw new NullPointerException(
+          "Invalid input" + (null == fieldName ? "" : " for field " + 
fieldName));
+    }
+    try {
+      return Integer.parseInt(val);
+    } catch (NumberFormatException e) {
+      String msg = "Invalid Number: " + val + (null == fieldName ? "" : " for 
field " + fieldName);
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, msg);
+    }
+  }
+
+  static final class SolrIntField extends Field {

Review Comment:
   [0] It looks like this is inspired by Lucene's `IntField`?  If so, it might 
be worth a Javadoc comment to tie it back to the original implementation?



##########
solr/core/src/java/org/apache/solr/schema/NumericField.java:
##########
@@ -0,0 +1,384 @@
+/*
+ * 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.Date;
+import java.util.List;
+import java.util.Map;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.document.SortedNumericDocValuesField;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.IndexOrDocValuesQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.SortedNumericSelector;
+import org.apache.lucene.search.SortedNumericSortField;
+import org.apache.lucene.search.TermInSetQuery;
+import org.apache.lucene.search.TermQuery;
+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.lucene.util.NumericUtils;
+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 NumericField extends PrimitiveFieldType {

Review Comment:
   [Q] Can you provide a bit of context on why this extends directly from 
PrimitiveFieldType rather than NumericFieldType?  (Or even PointField - I 
notice that many of the methods here are verbatim copies from PointField, which 
makes it seem a likely parent.)
   
   I take it there are particular things in NumericFieldType and PointField 
that we absolutely don't want to inherit for whatever reason?



##########
solr/core/src/java/org/apache/solr/schema/IntPointField.java:
##########
@@ -104,26 +105,42 @@ public Object toObject(IndexableField f) {
   }
 
   @Override
-  protected Query getExactQuery(SchemaField field, String externalVal) {
-    return IntPoint.newExactQuery(field.getName(), 
parseIntFromUser(field.getName(), externalVal));
-  }
-
-  @Override
-  public Query getSetQuery(QParser parser, SchemaField field, 
Collection<String> externalVal) {
-    assert externalVal.size() > 0;
-    if (!field.indexed()) {
-      return super.getSetQuery(parser, field, externalVal);
-    }
-    int[] values = new int[externalVal.size()];
-    int i = 0;
-    for (String val : externalVal) {
-      values[i] = parseIntFromUser(field.getName(), val);
-      i++;
+  public Query getSetQuery(QParser parser, SchemaField field, 
Collection<String> externalVals) {
+    assert externalVals.size() > 0;
+    Query indexQuery = null;
+    int[] values = null;
+    if (hasIndexedTerms(field)) {
+      indexQuery = super.getSetQuery(parser, field, externalVals);
+    } else if (field.indexed()) {
+      values = new int[externalVals.size()];
+      int i = 0;
+      for (String val : externalVals) {
+        values[i++] = parseIntFromUser(field.getName(), val);
+      }
+      indexQuery = IntPoint.newSetQuery(field.getName(), values);
     }
     if (field.hasDocValues()) {
-      return IntField.newSetQuery(field.getName(), values);
+      long[] points = new long[externalVals.size()];

Review Comment:
   [Q] The way I understand these changes they're only secondarily motivated by 
the new 'enhancedIndex' (i.e. terms-index for point fields) capability.  
Instead, most of the changes are so that we can use the 'IndexOrDocValuesQuery' 
wrapper query.
   
   Am I understanding that correctly?  Is there any inherent connection between 
the 'enhancedIndex' stuff and the IndexOrDocValuesQuery stuff?  It looks 
unrelated to me, so just trying to make sure I'm not missing some connection.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to