mirror of https://github.com/apache/lucene.git
SOLR-10011: Refactor PointField & TrieField to now have a common base class, NumericFieldType.
The TrieField.TrieTypes and PointField.PointTypes are now consolidated to NumericFieldType.NumberType. This refactoring also fixes a bug whereby PointFields were not using DocValues for range queries for indexed=false, docValues=true fields.
This commit is contained in:
parent
49fa7b0dd5
commit
285a1013ad
|
@ -80,6 +80,11 @@ Other Changes
|
|||
----------------------
|
||||
* SOLR-8396: Add support for PointFields in Solr (Ishan Chattopadhyaya, Tomás Fernández Löbbe)
|
||||
|
||||
* SOLR-10011: Refactor PointField & TrieField to now have a common base class, NumericFieldType. The
|
||||
TrieField.TrieTypes and PointField.PointTypes are now consolidated to NumericFieldType.NumberType. This
|
||||
refactoring also fixes a bug whereby PointFields were not using DocValues for range queries for
|
||||
indexed=false, docValues=true fields.
|
||||
|
||||
================== 6.5.0 ==================
|
||||
|
||||
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.
|
||||
|
|
|
@ -45,6 +45,10 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public DoublePointField() {
|
||||
type = NumberType.DOUBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toNativeType(Object val) {
|
||||
if (val == null) return null;
|
||||
|
@ -54,7 +58,7 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
|
|||
}
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
public Query getPointRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
boolean maxInclusive) {
|
||||
double actualMin, actualMax;
|
||||
if (min == null) {
|
||||
|
@ -179,9 +183,4 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
|
|||
protected StoredField getStoredField(SchemaField sf, Object value) {
|
||||
return new StoredField(sf.getName(), (Double) this.toNativeType(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointTypes getType() {
|
||||
return PointTypes.DOUBLE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public FloatPointField() {
|
||||
type = NumberType.FLOAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toNativeType(Object val) {
|
||||
if (val == null) return null;
|
||||
|
@ -54,7 +58,7 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
public Query getPointRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
boolean maxInclusive) {
|
||||
float actualMin, actualMax;
|
||||
if (min == null) {
|
||||
|
@ -179,9 +183,4 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
|
|||
protected StoredField getStoredField(SchemaField sf, Object value) {
|
||||
return new StoredField(sf.getName(), (Float) this.toNativeType(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointTypes getType() {
|
||||
return PointTypes.FLOAT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,10 @@ public class IntPointField extends PointField implements IntValueFieldType {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public IntPointField() {
|
||||
type = NumberType.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toNativeType(Object val) {
|
||||
if (val == null) return null;
|
||||
|
@ -58,7 +62,7 @@ public class IntPointField extends PointField implements IntValueFieldType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
public Query getPointRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
boolean maxInclusive) {
|
||||
int actualMin, actualMax;
|
||||
if (min == null) {
|
||||
|
@ -179,8 +183,4 @@ public class IntPointField extends PointField implements IntValueFieldType {
|
|||
return new StoredField(sf.getName(), (Integer) this.toNativeType(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointTypes getType() {
|
||||
return PointTypes.INTEGER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,10 @@ public class LongPointField extends PointField implements LongValueFieldType {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public LongPointField() {
|
||||
type = NumberType.LONG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toNativeType(Object val) {
|
||||
if (val == null) return null;
|
||||
|
@ -58,7 +62,7 @@ public class LongPointField extends PointField implements LongValueFieldType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
public Query getPointRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
boolean maxInclusive) {
|
||||
long actualMin, actualMax;
|
||||
if (min == null) {
|
||||
|
@ -178,9 +182,4 @@ public class LongPointField extends PointField implements LongValueFieldType {
|
|||
protected StoredField getStoredField(SchemaField sf, Object value) {
|
||||
return new StoredField(sf.getName(), (Long) this.toNativeType(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointTypes getType() {
|
||||
return PointTypes.LONG;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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 org.apache.lucene.document.NumericDocValuesField;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.search.FunctionRangeQuery;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.function.ValueSourceRangeFilter;
|
||||
import org.apache.solr.util.DateMathParser;
|
||||
|
||||
public abstract class NumericFieldType extends PrimitiveFieldType {
|
||||
|
||||
public static enum NumberType {
|
||||
INTEGER,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
DATE
|
||||
}
|
||||
|
||||
protected NumberType type;
|
||||
|
||||
/**
|
||||
* @return the type of this field
|
||||
*/
|
||||
final public NumberType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static long FLOAT_NEGATIVE_INFINITY_BITS = (long)Float.floatToIntBits(Float.NEGATIVE_INFINITY);
|
||||
private static long DOUBLE_NEGATIVE_INFINITY_BITS = Double.doubleToLongBits(Double.NEGATIVE_INFINITY);
|
||||
private static long FLOAT_POSITIVE_INFINITY_BITS = (long)Float.floatToIntBits(Float.POSITIVE_INFINITY);
|
||||
private static long DOUBLE_POSITIVE_INFINITY_BITS = Double.doubleToLongBits(Double.POSITIVE_INFINITY);
|
||||
private static long FLOAT_MINUS_ZERO_BITS = (long)Float.floatToIntBits(-0f);
|
||||
private static long DOUBLE_MINUS_ZERO_BITS = Double.doubleToLongBits(-0d);
|
||||
private static long FLOAT_ZERO_BITS = (long)Float.floatToIntBits(0f);
|
||||
private static long DOUBLE_ZERO_BITS = Double.doubleToLongBits(0d);
|
||||
|
||||
protected Query getDocValuesRangeQuery(QParser parser, SchemaField field, String min, String max,
|
||||
boolean minInclusive, boolean maxInclusive) {
|
||||
assert field.hasDocValues() && !field.multiValued();
|
||||
|
||||
switch (getType()) {
|
||||
case INTEGER:
|
||||
return numericDocValuesRangeQuery(field.getName(),
|
||||
min == null ? null : (long) Integer.parseInt(min),
|
||||
max == null ? null : (long) Integer.parseInt(max),
|
||||
minInclusive, maxInclusive);
|
||||
case FLOAT:
|
||||
return getRangeQueryForFloatDoubleDocValues(field, min, max, minInclusive, maxInclusive);
|
||||
case LONG:
|
||||
return numericDocValuesRangeQuery(field.getName(),
|
||||
min == null ? null : Long.parseLong(min),
|
||||
max == null ? null : Long.parseLong(max),
|
||||
minInclusive, maxInclusive);
|
||||
case DOUBLE:
|
||||
return getRangeQueryForFloatDoubleDocValues(field, min, max, minInclusive, maxInclusive);
|
||||
case DATE:
|
||||
return numericDocValuesRangeQuery(field.getName(),
|
||||
min == null ? null : DateMathParser.parseMath(null, min).getTime(),
|
||||
max == null ? null : DateMathParser.parseMath(null, max).getTime(),
|
||||
minInclusive, maxInclusive);
|
||||
default:
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for point field");
|
||||
}
|
||||
}
|
||||
|
||||
protected Query getRangeQueryForFloatDoubleDocValues(SchemaField sf, String min, String max, boolean minInclusive, boolean maxInclusive) {
|
||||
Query query;
|
||||
String fieldName = sf.getName();
|
||||
|
||||
Number minVal = min == null ? null : getType() == NumberType.FLOAT ? Float.parseFloat(min): Double.parseDouble(min);
|
||||
Number maxVal = max == null ? null : getType() == NumberType.FLOAT ? Float.parseFloat(max): Double.parseDouble(max);
|
||||
|
||||
Long minBits =
|
||||
min == null ? null : getType() == NumberType.FLOAT ? (long) Float.floatToIntBits(minVal.floatValue()): Double.doubleToLongBits(minVal.doubleValue());
|
||||
Long maxBits =
|
||||
max == null ? null : getType() == NumberType.FLOAT ? (long) Float.floatToIntBits(maxVal.floatValue()): Double.doubleToLongBits(maxVal.doubleValue());
|
||||
|
||||
long negativeInfinityBits = getType() == NumberType.FLOAT ? FLOAT_NEGATIVE_INFINITY_BITS : DOUBLE_NEGATIVE_INFINITY_BITS;
|
||||
long positiveInfinityBits = getType() == NumberType.FLOAT ? FLOAT_POSITIVE_INFINITY_BITS : DOUBLE_POSITIVE_INFINITY_BITS;
|
||||
long minusZeroBits = getType() == NumberType.FLOAT ? FLOAT_MINUS_ZERO_BITS : DOUBLE_MINUS_ZERO_BITS;
|
||||
long zeroBits = getType() == NumberType.FLOAT ? FLOAT_ZERO_BITS : DOUBLE_ZERO_BITS;
|
||||
|
||||
// If min is negative (or -0d) and max is positive (or +0d), then issue a FunctionRangeQuery
|
||||
if ((minVal == null || minVal.doubleValue() < 0d || minBits == minusZeroBits) &&
|
||||
(maxVal == null || (maxVal.doubleValue() > 0d || maxBits == zeroBits))) {
|
||||
|
||||
ValueSource vs = getValueSource(sf, null);
|
||||
query = new FunctionRangeQuery(new ValueSourceRangeFilter(vs, min, max, minInclusive, maxInclusive));
|
||||
|
||||
} else { // If both max and min are negative (or -0d), then issue range query with max and min reversed
|
||||
if ((minVal == null || minVal.doubleValue() < 0d || minBits == minusZeroBits) &&
|
||||
(maxVal != null && (maxVal.doubleValue() < 0d || maxBits == minusZeroBits))) {
|
||||
query = numericDocValuesRangeQuery
|
||||
(fieldName, maxBits, (min == null ? negativeInfinityBits : minBits), maxInclusive, minInclusive);
|
||||
} else { // If both max and min are positive, then issue range query
|
||||
query = numericDocValuesRangeQuery
|
||||
(fieldName, minBits, (max == null ? positiveInfinityBits : maxBits), minInclusive, maxInclusive);
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
public static Query numericDocValuesRangeQuery(
|
||||
String field,
|
||||
Number lowerValue, Number upperValue,
|
||||
boolean lowerInclusive, boolean upperInclusive) {
|
||||
|
||||
long actualLowerValue = Long.MIN_VALUE;
|
||||
if (lowerValue != null) {
|
||||
actualLowerValue = lowerValue.longValue();
|
||||
if (lowerInclusive == false) {
|
||||
if (actualLowerValue == Long.MAX_VALUE) {
|
||||
return new MatchNoDocsQuery();
|
||||
}
|
||||
++actualLowerValue;
|
||||
}
|
||||
}
|
||||
|
||||
long actualUpperValue = Long.MAX_VALUE;
|
||||
if (upperValue != null) {
|
||||
actualUpperValue = upperValue.longValue();
|
||||
if (upperInclusive == false) {
|
||||
if (actualUpperValue == Long.MIN_VALUE) {
|
||||
return new MatchNoDocsQuery();
|
||||
}
|
||||
--actualUpperValue;
|
||||
}
|
||||
}
|
||||
return NumericDocValuesField.newRangeQuery(field, actualLowerValue, actualUpperValue);
|
||||
}
|
||||
}
|
|
@ -49,15 +49,7 @@ import org.slf4j.LoggerFactory;
|
|||
* {@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
|
||||
}
|
||||
public abstract class PointField extends NumericFieldType {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
|
@ -117,11 +109,6 @@ public abstract class PointField extends PrimitiveFieldType {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of this field
|
||||
*/
|
||||
public abstract PointTypes getType();
|
||||
|
||||
@Override
|
||||
public abstract Query getSetQuery(QParser parser, SchemaField field, Collection<String> externalVals);
|
||||
|
||||
|
@ -137,6 +124,19 @@ public abstract class PointField extends PrimitiveFieldType {
|
|||
|
||||
protected abstract Query getExactQuery(SchemaField field, String externalVal);
|
||||
|
||||
public abstract Query getPointRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
boolean maxInclusive);
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String min, String max, boolean minInclusive,
|
||||
boolean maxInclusive) {
|
||||
if (!field.indexed() && field.hasDocValues() && !field.multiValued()) {
|
||||
return getDocValuesRangeQuery(parser, field, min, max, minInclusive, maxInclusive);
|
||||
} else {
|
||||
return getPointRangeQuery(parser, field, min, max, minInclusive, maxInclusive);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String storedToReadable(IndexableField f) {
|
||||
return toExternal(f);
|
||||
|
|
|
@ -84,7 +84,7 @@ import org.apache.solr.util.DateMathParser;
|
|||
*/
|
||||
public class TrieDateField extends TrieField implements DateValueFieldType {
|
||||
{
|
||||
this.type = TrieTypes.DATE;
|
||||
this.type = NumberType.DATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,7 +52,7 @@ import org.apache.lucene.util.mutable.MutableValueDouble;
|
|||
*/
|
||||
public class TrieDoubleField extends TrieField implements DoubleValueFieldType {
|
||||
{
|
||||
type=TrieTypes.DOUBLE;
|
||||
type = NumberType.DOUBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
|
|||
import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
|
||||
import org.apache.lucene.queries.function.valuesource.IntFieldSource;
|
||||
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.lucene.search.SortedSetSelector;
|
||||
|
@ -56,9 +55,7 @@ import org.apache.lucene.util.mutable.MutableValueDate;
|
|||
import org.apache.lucene.util.mutable.MutableValueLong;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.response.TextResponseWriter;
|
||||
import org.apache.solr.search.FunctionRangeQuery;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.function.ValueSourceRangeFilter;
|
||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||
import org.apache.solr.util.DateMathParser;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -84,12 +81,11 @@ import org.slf4j.LoggerFactory;
|
|||
* @see org.apache.lucene.legacy.LegacyNumericRangeQuery
|
||||
* @since solr 1.4
|
||||
*/
|
||||
public class TrieField extends PrimitiveFieldType {
|
||||
public class TrieField extends NumericFieldType {
|
||||
public static final int DEFAULT_PRECISION_STEP = 8;
|
||||
|
||||
protected int precisionStepArg = TrieField.DEFAULT_PRECISION_STEP; // the one passed in or defaulted
|
||||
protected int precisionStep; // normalized
|
||||
protected TrieTypes type;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
|
@ -107,7 +103,7 @@ public class TrieField extends PrimitiveFieldType {
|
|||
|
||||
if (t != null) {
|
||||
try {
|
||||
type = TrieTypes.valueOf(t.toUpperCase(Locale.ROOT));
|
||||
type = NumberType.valueOf(t.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
||||
"Invalid type specified in schema.xml for field: " + args.get("name"), e);
|
||||
|
@ -139,7 +135,7 @@ public class TrieField extends PrimitiveFieldType {
|
|||
}
|
||||
|
||||
// normal stored case
|
||||
return (type == TrieTypes.DATE) ? new Date(val.longValue()) : val;
|
||||
return (type == NumberType.DATE) ? new Date(val.longValue()) : val;
|
||||
} else {
|
||||
// multi-valued numeric docValues currently use SortedSet on the indexed terms.
|
||||
BytesRef term = f.binaryValue();
|
||||
|
@ -340,13 +336,6 @@ public class TrieField extends PrimitiveFieldType {
|
|||
return precisionStepArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of this field
|
||||
*/
|
||||
public TrieTypes getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LegacyNumericType getNumericType() {
|
||||
switch (type) {
|
||||
|
@ -372,66 +361,41 @@ public class TrieField extends PrimitiveFieldType {
|
|||
}
|
||||
int ps = precisionStep;
|
||||
Query query;
|
||||
final boolean matchOnly = field.hasDocValues() && !field.indexed();
|
||||
|
||||
if (field.hasDocValues() && !field.indexed()) {
|
||||
return getDocValuesRangeQuery(parser, field, min, max, minInclusive, maxInclusive);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case INTEGER:
|
||||
if (matchOnly) {
|
||||
query = numericDocValuesRangeQuery(field.getName(),
|
||||
min == null ? null : Integer.parseInt(min),
|
||||
max == null ? null : Integer.parseInt(max),
|
||||
minInclusive, maxInclusive);
|
||||
} else {
|
||||
query = LegacyNumericRangeQuery.newIntRange(field.getName(), ps,
|
||||
min == null ? null : Integer.parseInt(min),
|
||||
max == null ? null : Integer.parseInt(max),
|
||||
minInclusive, maxInclusive);
|
||||
}
|
||||
query = LegacyNumericRangeQuery.newIntRange(field.getName(), ps,
|
||||
min == null ? null : Integer.parseInt(min),
|
||||
max == null ? null : Integer.parseInt(max),
|
||||
minInclusive, maxInclusive);
|
||||
break;
|
||||
case FLOAT:
|
||||
if (matchOnly) {
|
||||
return getRangeQueryForFloatDoubleDocValues(field, min, max, minInclusive, maxInclusive);
|
||||
} else {
|
||||
query = LegacyNumericRangeQuery.newFloatRange(field.getName(), ps,
|
||||
min == null ? null : Float.parseFloat(min),
|
||||
max == null ? null : Float.parseFloat(max),
|
||||
minInclusive, maxInclusive);
|
||||
}
|
||||
query = LegacyNumericRangeQuery.newFloatRange(field.getName(), ps,
|
||||
min == null ? null : Float.parseFloat(min),
|
||||
max == null ? null : Float.parseFloat(max),
|
||||
minInclusive, maxInclusive);
|
||||
break;
|
||||
case LONG:
|
||||
if (matchOnly) {
|
||||
query = numericDocValuesRangeQuery(field.getName(),
|
||||
min == null ? null : Long.parseLong(min),
|
||||
max == null ? null : Long.parseLong(max),
|
||||
minInclusive, maxInclusive);
|
||||
} else {
|
||||
query = LegacyNumericRangeQuery.newLongRange(field.getName(), ps,
|
||||
min == null ? null : Long.parseLong(min),
|
||||
max == null ? null : Long.parseLong(max),
|
||||
minInclusive, maxInclusive);
|
||||
}
|
||||
query = LegacyNumericRangeQuery.newLongRange(field.getName(), ps,
|
||||
min == null ? null : Long.parseLong(min),
|
||||
max == null ? null : Long.parseLong(max),
|
||||
minInclusive, maxInclusive);
|
||||
break;
|
||||
case DOUBLE:
|
||||
if (matchOnly) {
|
||||
return getRangeQueryForFloatDoubleDocValues(field, min, max, minInclusive, maxInclusive);
|
||||
} else {
|
||||
query = LegacyNumericRangeQuery.newDoubleRange(field.getName(), ps,
|
||||
min == null ? null : Double.parseDouble(min),
|
||||
max == null ? null : Double.parseDouble(max),
|
||||
minInclusive, maxInclusive);
|
||||
}
|
||||
query = LegacyNumericRangeQuery.newDoubleRange(field.getName(), ps,
|
||||
min == null ? null : Double.parseDouble(min),
|
||||
max == null ? null : Double.parseDouble(max),
|
||||
minInclusive, maxInclusive);
|
||||
break;
|
||||
case DATE:
|
||||
if (matchOnly) {
|
||||
query = numericDocValuesRangeQuery(field.getName(),
|
||||
min == null ? null : DateMathParser.parseMath(null, min).getTime(),
|
||||
max == null ? null : DateMathParser.parseMath(null, max).getTime(),
|
||||
minInclusive, maxInclusive);
|
||||
} else {
|
||||
query = LegacyNumericRangeQuery.newLongRange(field.getName(), ps,
|
||||
min == null ? null : DateMathParser.parseMath(null, min).getTime(),
|
||||
max == null ? null : DateMathParser.parseMath(null, max).getTime(),
|
||||
minInclusive, maxInclusive);
|
||||
}
|
||||
query = LegacyNumericRangeQuery.newLongRange(field.getName(), ps,
|
||||
min == null ? null : DateMathParser.parseMath(null, min).getTime(),
|
||||
max == null ? null : DateMathParser.parseMath(null, max).getTime(),
|
||||
minInclusive, maxInclusive);
|
||||
break;
|
||||
default:
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field");
|
||||
|
@ -440,81 +404,6 @@ public class TrieField extends PrimitiveFieldType {
|
|||
return query;
|
||||
}
|
||||
|
||||
private static Query numericDocValuesRangeQuery(
|
||||
String field,
|
||||
Number lowerValue, Number upperValue,
|
||||
boolean lowerInclusive, boolean upperInclusive) {
|
||||
|
||||
long actualLowerValue = Long.MIN_VALUE;
|
||||
if (lowerValue != null) {
|
||||
actualLowerValue = lowerValue.longValue();
|
||||
if (lowerInclusive == false) {
|
||||
if (actualLowerValue == Long.MAX_VALUE) {
|
||||
return new MatchNoDocsQuery();
|
||||
}
|
||||
++actualLowerValue;
|
||||
}
|
||||
}
|
||||
|
||||
long actualUpperValue = Long.MAX_VALUE;
|
||||
if (upperValue != null) {
|
||||
actualUpperValue = upperValue.longValue();
|
||||
if (upperInclusive == false) {
|
||||
if (actualUpperValue == Long.MIN_VALUE) {
|
||||
return new MatchNoDocsQuery();
|
||||
}
|
||||
--actualUpperValue;
|
||||
}
|
||||
}
|
||||
return NumericDocValuesField.newRangeQuery(field, actualLowerValue, actualUpperValue);
|
||||
}
|
||||
|
||||
private static long FLOAT_NEGATIVE_INFINITY_BITS = (long)Float.floatToIntBits(Float.NEGATIVE_INFINITY);
|
||||
private static long DOUBLE_NEGATIVE_INFINITY_BITS = Double.doubleToLongBits(Double.NEGATIVE_INFINITY);
|
||||
private static long FLOAT_POSITIVE_INFINITY_BITS = (long)Float.floatToIntBits(Float.POSITIVE_INFINITY);
|
||||
private static long DOUBLE_POSITIVE_INFINITY_BITS = Double.doubleToLongBits(Double.POSITIVE_INFINITY);
|
||||
private static long FLOAT_MINUS_ZERO_BITS = (long)Float.floatToIntBits(-0f);
|
||||
private static long DOUBLE_MINUS_ZERO_BITS = Double.doubleToLongBits(-0d);
|
||||
private static long FLOAT_ZERO_BITS = (long)Float.floatToIntBits(0f);
|
||||
private static long DOUBLE_ZERO_BITS = Double.doubleToLongBits(0d);
|
||||
|
||||
private Query getRangeQueryForFloatDoubleDocValues(SchemaField sf, String min, String max, boolean minInclusive, boolean maxInclusive) {
|
||||
Query query;
|
||||
String fieldName = sf.getName();
|
||||
|
||||
Number minVal = min == null ? null : type == TrieTypes.FLOAT ? Float.parseFloat(min): Double.parseDouble(min);
|
||||
Number maxVal = max == null ? null : type == TrieTypes.FLOAT ? Float.parseFloat(max): Double.parseDouble(max);
|
||||
|
||||
Long minBits =
|
||||
min == null ? null : type == TrieTypes.FLOAT ? (long) Float.floatToIntBits(minVal.floatValue()): Double.doubleToLongBits(minVal.doubleValue());
|
||||
Long maxBits =
|
||||
max == null ? null : type == TrieTypes.FLOAT ? (long) Float.floatToIntBits(maxVal.floatValue()): Double.doubleToLongBits(maxVal.doubleValue());
|
||||
|
||||
long negativeInfinityBits = type == TrieTypes.FLOAT ? FLOAT_NEGATIVE_INFINITY_BITS : DOUBLE_NEGATIVE_INFINITY_BITS;
|
||||
long positiveInfinityBits = type == TrieTypes.FLOAT ? FLOAT_POSITIVE_INFINITY_BITS : DOUBLE_POSITIVE_INFINITY_BITS;
|
||||
long minusZeroBits = type == TrieTypes.FLOAT ? FLOAT_MINUS_ZERO_BITS : DOUBLE_MINUS_ZERO_BITS;
|
||||
long zeroBits = type == TrieTypes.FLOAT ? FLOAT_ZERO_BITS : DOUBLE_ZERO_BITS;
|
||||
|
||||
// If min is negative (or -0d) and max is positive (or +0d), then issue a FunctionRangeQuery
|
||||
if ((minVal == null || minVal.doubleValue() < 0d || minBits == minusZeroBits) &&
|
||||
(maxVal == null || (maxVal.doubleValue() > 0d || maxBits == zeroBits))) {
|
||||
|
||||
ValueSource vs = getValueSource(sf, null);
|
||||
query = new FunctionRangeQuery(new ValueSourceRangeFilter(vs, min, max, minInclusive, maxInclusive));
|
||||
|
||||
} else { // If both max and min are negative (or -0d), then issue range query with max and min reversed
|
||||
if ((minVal == null || minVal.doubleValue() < 0d || minBits == minusZeroBits) &&
|
||||
(maxVal != null && (maxVal.doubleValue() < 0d || maxBits == minusZeroBits))) {
|
||||
query = numericDocValuesRangeQuery
|
||||
(fieldName, maxBits, (min == null ? negativeInfinityBits : minBits), maxInclusive, minInclusive);
|
||||
} else { // If both max and min are positive, then issue range query
|
||||
query = numericDocValuesRangeQuery
|
||||
(fieldName, minBits, (max == null ? positiveInfinityBits : maxBits), minInclusive, maxInclusive);
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
|
||||
if (!field.indexed() && field.hasDocValues()) {
|
||||
|
@ -579,7 +468,7 @@ public class TrieField extends PrimitiveFieldType {
|
|||
|
||||
@Override
|
||||
public String toExternal(IndexableField f) {
|
||||
return (type == TrieTypes.DATE)
|
||||
return (type == NumberType.DATE)
|
||||
? ((Date) toObject(f)).toInstant().toString()
|
||||
: toObject(f).toString();
|
||||
}
|
||||
|
@ -792,15 +681,6 @@ public class TrieField extends PrimitiveFieldType {
|
|||
}
|
||||
}
|
||||
|
||||
public enum TrieTypes {
|
||||
INTEGER,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
DATE
|
||||
}
|
||||
|
||||
|
||||
static final String INT_PREFIX = new String(new char[]{LegacyNumericUtils.SHIFT_START_INT});
|
||||
static final String LONG_PREFIX = new String(new char[]{LegacyNumericUtils.SHIFT_START_LONG});
|
||||
|
||||
|
@ -863,7 +743,6 @@ class TrieDateFieldSource extends LongFieldSource {
|
|||
public long externalToLong(String extVal) {
|
||||
return DateMathParser.parseMath(null, extVal).getTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ import org.apache.lucene.util.mutable.MutableValueFloat;
|
|||
*/
|
||||
public class TrieFloatField extends TrieField implements FloatValueFieldType {
|
||||
{
|
||||
type=TrieTypes.FLOAT;
|
||||
type = NumberType.FLOAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.apache.lucene.util.mutable.MutableValueInt;
|
|||
*/
|
||||
public class TrieIntField extends TrieField implements IntValueFieldType {
|
||||
{
|
||||
type=TrieTypes.INTEGER;
|
||||
type = NumberType.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.apache.lucene.util.mutable.MutableValueLong;
|
|||
*/
|
||||
public class TrieLongField extends TrieField implements LongValueFieldType {
|
||||
{
|
||||
type=TrieTypes.LONG;
|
||||
type = NumberType.LONG;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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.NumericFieldType;
|
||||
import org.apache.solr.schema.PointField;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.schema.TrieDateField;
|
||||
|
@ -823,7 +824,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
|
|||
}
|
||||
Object newVal = val;
|
||||
if (schemaField.getType().isPointField()) {
|
||||
PointField.PointTypes type = ((PointField)schemaField.getType()).getType();
|
||||
NumericFieldType.NumberType type = ((PointField)schemaField.getType()).getType();
|
||||
switch (type) {
|
||||
case INTEGER:
|
||||
newVal = val.intValue();
|
||||
|
|
|
@ -70,7 +70,7 @@ class GroupConverter {
|
|||
for (SearchGroup<BytesRef> original : values) {
|
||||
SearchGroup<MutableValue> converted = new SearchGroup<MutableValue>();
|
||||
converted.sortValues = original.sortValues; // ?
|
||||
TrieField.TrieTypes type = ((TrieField)fieldType).getType();
|
||||
TrieField.NumberType type = ((TrieField)fieldType).getType();
|
||||
final MutableValue v;
|
||||
switch (type) {
|
||||
case INTEGER:
|
||||
|
|
|
@ -79,6 +79,10 @@
|
|||
<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"/>
|
||||
<dynamicField name="*_p_i_ni_ns_dv" type="pint" indexed="false" stored="false" docValues="true" useDocValuesAsStored="true"/>
|
||||
<dynamicField name="*_p_l_ni_ns_dv" type="plong" indexed="false" stored="false" docValues="true" useDocValuesAsStored="true"/>
|
||||
<dynamicField name="*_p_d_ni_ns_dv" type="pdouble" indexed="false" stored="false" docValues="true" useDocValuesAsStored="true"/>
|
||||
<dynamicField name="*_p_f_ni_ns_dv" type="pfloat" indexed="false" stored="false" docValues="true" useDocValuesAsStored="true"/>
|
||||
|
||||
</fields>
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
doTestIntPointFieldExactQuery("number_p_i", false);
|
||||
doTestIntPointFieldExactQuery("number_p_i_mv", false);
|
||||
doTestIntPointFieldExactQuery("number_p_i_ni_dv", false);
|
||||
doTestIntPointFieldExactQuery("number_p_i_ni_ns_dv", false);
|
||||
// uncomment once MultiValued docValues are supported in PointFields
|
||||
// doTestIntPointFieldExactQuery("number_p_i_ni_mv_dv", false);
|
||||
}
|
||||
|
@ -74,6 +75,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testIntPointFieldRangeQuery() throws Exception {
|
||||
doTestIntPointFieldRangeQuery("number_p_i", "int", false);
|
||||
doTestIntPointFieldRangeQuery("number_p_i_ni_ns_dv", "int", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -235,6 +237,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
doTestFloatPointFieldExactQuery("number_p_d");
|
||||
doTestFloatPointFieldExactQuery("number_p_d_mv");
|
||||
doTestFloatPointFieldExactQuery("number_p_d_ni_dv");
|
||||
doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv");
|
||||
// TODO enable once MuultiValued docValues are supported with PointFields
|
||||
// doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv");
|
||||
}
|
||||
|
@ -258,6 +261,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testDoublePointFieldRangeQuery() throws Exception {
|
||||
doTestFloatPointFieldRangeQuery("number_p_d", "double", true);
|
||||
doTestFloatPointFieldRangeQuery("number_p_d_ni_ns_dv", "double", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -457,6 +461,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
doTestFloatPointFieldExactQuery("number_p_f");
|
||||
doTestFloatPointFieldExactQuery("number_p_f_mv");
|
||||
doTestFloatPointFieldExactQuery("number_p_f_ni_dv");
|
||||
doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv");
|
||||
// doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv");
|
||||
}
|
||||
|
||||
|
@ -479,6 +484,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testFloatPointFieldRangeQuery() throws Exception {
|
||||
doTestFloatPointFieldRangeQuery("number_p_f", "float", false);
|
||||
doTestFloatPointFieldRangeQuery("number_p_f_ni_ns_dv", "float", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -551,6 +557,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
doTestIntPointFieldExactQuery("number_p_l", true);
|
||||
doTestIntPointFieldExactQuery("number_p_l_mv", true);
|
||||
doTestIntPointFieldExactQuery("number_p_l_ni_dv", true);
|
||||
doTestIntPointFieldExactQuery("number_p_l_ni_ns_dv", true);
|
||||
// doTestIntPointFieldExactQuery("number_p_i_ni_mv_dv", true);
|
||||
}
|
||||
|
||||
|
@ -565,6 +572,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testLongPointFieldRangeQuery() throws Exception {
|
||||
doTestIntPointFieldRangeQuery("number_p_l", "long", true);
|
||||
doTestIntPointFieldRangeQuery("number_p_l_ni_ns_dv", "long", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue