mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-08 22:14:59 +00:00
Add new ip_range field type
This commit adds support for indexing and searching a new ip_range field type. Both IPv4 and IPv6 formats are supported. Tests are updated and docs are added.
This commit is contained in:
parent
e3766d2828
commit
0c4eb0a029
@ -22,6 +22,8 @@ import org.apache.lucene.document.Field;
|
|||||||
import org.apache.lucene.document.DoubleRange;
|
import org.apache.lucene.document.DoubleRange;
|
||||||
import org.apache.lucene.document.FloatRange;
|
import org.apache.lucene.document.FloatRange;
|
||||||
import org.apache.lucene.document.IntRange;
|
import org.apache.lucene.document.IntRange;
|
||||||
|
import org.apache.lucene.document.InetAddressPoint;
|
||||||
|
import org.apache.lucene.document.InetAddressRange;
|
||||||
import org.apache.lucene.document.LongRange;
|
import org.apache.lucene.document.LongRange;
|
||||||
import org.apache.lucene.document.StoredField;
|
import org.apache.lucene.document.StoredField;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
@ -29,12 +31,12 @@ import org.apache.lucene.index.IndexableField;
|
|||||||
import org.apache.lucene.search.BoostQuery;
|
import org.apache.lucene.search.BoostQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.NumericUtils;
|
|
||||||
import org.elasticsearch.common.Explicit;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.geo.ShapeRelation;
|
import org.elasticsearch.common.geo.ShapeRelation;
|
||||||
import org.elasticsearch.common.joda.DateMathParser;
|
import org.elasticsearch.common.joda.DateMathParser;
|
||||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||||
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
import org.elasticsearch.common.settings.Setting;
|
import org.elasticsearch.common.settings.Setting;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.util.LocaleUtils;
|
import org.elasticsearch.common.util.LocaleUtils;
|
||||||
@ -45,6 +47,7 @@ import org.elasticsearch.index.query.QueryShardContext;
|
|||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -341,8 +344,8 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
RangeFieldType fieldType = fieldType();
|
RangeFieldType fieldType = fieldType();
|
||||||
RangeType rangeType = fieldType.rangeType;
|
RangeType rangeType = fieldType.rangeType;
|
||||||
String fieldName = null;
|
String fieldName = null;
|
||||||
Number from = rangeType.minValue();
|
Object from = rangeType.minValue();
|
||||||
Number to = rangeType.maxValue();
|
Object to = rangeType.maxValue();
|
||||||
boolean includeFrom = DEFAULT_INCLUDE_LOWER;
|
boolean includeFrom = DEFAULT_INCLUDE_LOWER;
|
||||||
boolean includeTo = DEFAULT_INCLUDE_UPPER;
|
boolean includeTo = DEFAULT_INCLUDE_UPPER;
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
@ -427,10 +430,72 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
|
|
||||||
/** Enum defining the type of range */
|
/** Enum defining the type of range */
|
||||||
public enum RangeType {
|
public enum RangeType {
|
||||||
|
IP("ip_range") {
|
||||||
|
@Override
|
||||||
|
public Field getRangeField(String name, Range r) {
|
||||||
|
return new InetAddressRange(name, (InetAddress)r.from, (InetAddress)r.to);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress parseFrom(RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included)
|
||||||
|
throws IOException {
|
||||||
|
InetAddress address = InetAddresses.forString(parser.text());
|
||||||
|
return included ? address : nextUp(address);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress parseTo(RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included)
|
||||||
|
throws IOException {
|
||||||
|
InetAddress address = InetAddresses.forString(parser.text());
|
||||||
|
return included ? address : nextDown(address);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress parse(Object value, boolean coerce) {
|
||||||
|
return value instanceof InetAddress ? (InetAddress) value : InetAddresses.forString((String) value);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress minValue() {
|
||||||
|
return InetAddressPoint.MIN_VALUE;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress maxValue() {
|
||||||
|
return InetAddressPoint.MAX_VALUE;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress nextUp(Object value) {
|
||||||
|
return InetAddressPoint.nextUp((InetAddress)value);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public InetAddress nextDown(Object value) {
|
||||||
|
return InetAddressPoint.nextDown((InetAddress)value);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Query withinQuery(String field, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||||
|
InetAddress lower = (InetAddress)from;
|
||||||
|
InetAddress upper = (InetAddress)to;
|
||||||
|
return InetAddressRange.newWithinQuery(field,
|
||||||
|
includeLower ? lower : nextUp(lower), includeUpper ? upper : nextDown(upper));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Query containsQuery(String field, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||||
|
InetAddress lower = (InetAddress)from;
|
||||||
|
InetAddress upper = (InetAddress)to;
|
||||||
|
return InetAddressRange.newContainsQuery(field,
|
||||||
|
includeLower ? lower : nextUp(lower), includeUpper ? upper : nextDown(upper));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Query intersectsQuery(String field, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||||
|
InetAddress lower = (InetAddress)from;
|
||||||
|
InetAddress upper = (InetAddress)to;
|
||||||
|
return InetAddressRange.newIntersectsQuery(field,
|
||||||
|
includeLower ? lower : nextUp(lower), includeUpper ? upper : nextDown(upper));
|
||||||
|
}
|
||||||
|
public String toString(InetAddress address) {
|
||||||
|
return InetAddresses.toAddrString(address);
|
||||||
|
}
|
||||||
|
},
|
||||||
DATE("date_range", NumberType.LONG) {
|
DATE("date_range", NumberType.LONG) {
|
||||||
@Override
|
@Override
|
||||||
public Field getRangeField(String name, Range r) {
|
public Field getRangeField(String name, Range r) {
|
||||||
return new LongRange(name, new long[] {r.from.longValue()}, new long[] {r.to.longValue()});
|
return new LongRange(name, new long[] {((Number)r.from).longValue()}, new long[] {((Number)r.to).longValue()});
|
||||||
}
|
}
|
||||||
private Number parse(DateMathParser dateMathParser, String dateStr) {
|
private Number parse(DateMathParser dateMathParser, String dateStr) {
|
||||||
return dateMathParser.parse(dateStr, () -> {throw new IllegalArgumentException("now is not used at indexing time");});
|
return dateMathParser.parse(dateStr, () -> {throw new IllegalArgumentException("now is not used at indexing time");});
|
||||||
@ -456,16 +521,12 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return Long.MAX_VALUE;
|
return Long.MAX_VALUE;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Number nextUp(Number value) {
|
public Long nextUp(Object value) {
|
||||||
return LONG.nextUp(value);
|
return (long) LONG.nextUp(value);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Number nextDown(Number value) {
|
public Long nextDown(Object value) {
|
||||||
return LONG.nextDown(value);
|
return (long) LONG.nextDown(value);
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public byte[] getBytes(Range r) {
|
|
||||||
return LONG.getBytes(r);
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String field, Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper,
|
public Query rangeQuery(String field, Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper,
|
||||||
@ -484,15 +545,15 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return super.rangeQuery(field, low, high, includeLower, includeUpper, relation, zone, dateMathParser, context);
|
return super.rangeQuery(field, low, high, includeLower, includeUpper, relation, zone, dateMathParser, context);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query withinQuery(String field, Number from, Number to, boolean includeLower, boolean includeUpper) {
|
public Query withinQuery(String field, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||||
return LONG.withinQuery(field, from, to, includeLower, includeUpper);
|
return LONG.withinQuery(field, from, to, includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query containsQuery(String field, Number from, Number to, boolean includeLower, boolean includeUpper) {
|
public Query containsQuery(String field, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||||
return LONG.containsQuery(field, from, to, includeLower, includeUpper);
|
return LONG.containsQuery(field, from, to, includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query intersectsQuery(String field, Number from, Number to, boolean includeLower, boolean includeUpper) {
|
public Query intersectsQuery(String field, Object from, Object to, boolean includeLower, boolean includeUpper) {
|
||||||
return LONG.intersectsQuery(field, from, to, includeLower, includeUpper);
|
return LONG.intersectsQuery(field, from, to, includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -507,38 +568,31 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return Float.POSITIVE_INFINITY;
|
return Float.POSITIVE_INFINITY;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Float nextUp(Number value) {
|
public Float nextUp(Object value) {
|
||||||
return Math.nextUp(value.floatValue());
|
return Math.nextUp(((Number)value).floatValue());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Float nextDown(Number value) {
|
public Float nextDown(Object value) {
|
||||||
return Math.nextDown(value.floatValue());
|
return Math.nextDown(((Number)value).floatValue());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Field getRangeField(String name, Range r) {
|
public Field getRangeField(String name, Range r) {
|
||||||
return new FloatRange(name, new float[] {r.from.floatValue()}, new float[] {r.to.floatValue()});
|
return new FloatRange(name, new float[] {((Number)r.from).floatValue()}, new float[] {((Number)r.to).floatValue()});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public byte[] getBytes(Range r) {
|
public Query withinQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
byte[] b = new byte[Float.BYTES*2];
|
|
||||||
NumericUtils.intToSortableBytes(NumericUtils.floatToSortableInt(r.from.floatValue()), b, 0);
|
|
||||||
NumericUtils.intToSortableBytes(NumericUtils.floatToSortableInt(r.to.floatValue()), b, Float.BYTES);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Query withinQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
|
||||||
return FloatRange.newWithinQuery(field,
|
return FloatRange.newWithinQuery(field,
|
||||||
new float[] {includeFrom ? (Float)from : Math.nextUp((Float)from)},
|
new float[] {includeFrom ? (Float)from : Math.nextUp((Float)from)},
|
||||||
new float[] {includeTo ? (Float)to : Math.nextDown((Float)to)});
|
new float[] {includeTo ? (Float)to : Math.nextDown((Float)to)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query containsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query containsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return FloatRange.newContainsQuery(field,
|
return FloatRange.newContainsQuery(field,
|
||||||
new float[] {includeFrom ? (Float)from : Math.nextUp((Float)from)},
|
new float[] {includeFrom ? (Float)from : Math.nextUp((Float)from)},
|
||||||
new float[] {includeTo ? (Float)to : Math.nextDown((Float)to)});
|
new float[] {includeTo ? (Float)to : Math.nextDown((Float)to)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query intersectsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query intersectsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return FloatRange.newIntersectsQuery(field,
|
return FloatRange.newIntersectsQuery(field,
|
||||||
new float[] {includeFrom ? (Float)from : Math.nextUp((Float)from)},
|
new float[] {includeFrom ? (Float)from : Math.nextUp((Float)from)},
|
||||||
new float[] {includeTo ? (Float)to : Math.nextDown((Float)to)});
|
new float[] {includeTo ? (Float)to : Math.nextDown((Float)to)});
|
||||||
@ -554,38 +608,31 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return Double.POSITIVE_INFINITY;
|
return Double.POSITIVE_INFINITY;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Double nextUp(Number value) {
|
public Double nextUp(Object value) {
|
||||||
return Math.nextUp(value.doubleValue());
|
return Math.nextUp(((Number)value).doubleValue());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Double nextDown(Number value) {
|
public Double nextDown(Object value) {
|
||||||
return Math.nextDown(value.doubleValue());
|
return Math.nextDown(((Number)value).doubleValue());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Field getRangeField(String name, Range r) {
|
public Field getRangeField(String name, Range r) {
|
||||||
return new DoubleRange(name, new double[] {r.from.doubleValue()}, new double[] {r.to.doubleValue()});
|
return new DoubleRange(name, new double[] {((Number)r.from).doubleValue()}, new double[] {((Number)r.to).doubleValue()});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public byte[] getBytes(Range r) {
|
public Query withinQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
byte[] b = new byte[Double.BYTES*2];
|
|
||||||
NumericUtils.longToSortableBytes(NumericUtils.doubleToSortableLong(r.from.doubleValue()), b, 0);
|
|
||||||
NumericUtils.longToSortableBytes(NumericUtils.doubleToSortableLong(r.to.doubleValue()), b, Double.BYTES);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Query withinQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
|
||||||
return DoubleRange.newWithinQuery(field,
|
return DoubleRange.newWithinQuery(field,
|
||||||
new double[] {includeFrom ? (Double)from : Math.nextUp((Double)from)},
|
new double[] {includeFrom ? (Double)from : Math.nextUp((Double)from)},
|
||||||
new double[] {includeTo ? (Double)to : Math.nextDown((Double)to)});
|
new double[] {includeTo ? (Double)to : Math.nextDown((Double)to)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query containsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query containsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return DoubleRange.newContainsQuery(field,
|
return DoubleRange.newContainsQuery(field,
|
||||||
new double[] {includeFrom ? (Double)from : Math.nextUp((Double)from)},
|
new double[] {includeFrom ? (Double)from : Math.nextUp((Double)from)},
|
||||||
new double[] {includeTo ? (Double)to : Math.nextDown((Double)to)});
|
new double[] {includeTo ? (Double)to : Math.nextDown((Double)to)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query intersectsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query intersectsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return DoubleRange.newIntersectsQuery(field,
|
return DoubleRange.newIntersectsQuery(field,
|
||||||
new double[] {includeFrom ? (Double)from : Math.nextUp((Double)from)},
|
new double[] {includeFrom ? (Double)from : Math.nextUp((Double)from)},
|
||||||
new double[] {includeTo ? (Double)to : Math.nextDown((Double)to)});
|
new double[] {includeTo ? (Double)to : Math.nextDown((Double)to)});
|
||||||
@ -603,36 +650,29 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Integer nextUp(Number value) {
|
public Integer nextUp(Object value) {
|
||||||
return value.intValue() + 1;
|
return ((Number)value).intValue() + 1;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Integer nextDown(Number value) {
|
public Integer nextDown(Object value) {
|
||||||
return value.intValue() - 1;
|
return ((Number)value).intValue() - 1;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Field getRangeField(String name, Range r) {
|
public Field getRangeField(String name, Range r) {
|
||||||
return new IntRange(name, new int[] {r.from.intValue()}, new int[] {r.to.intValue()});
|
return new IntRange(name, new int[] {((Number)r.from).intValue()}, new int[] {((Number)r.to).intValue()});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public byte[] getBytes(Range r) {
|
public Query withinQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
byte[] b = new byte[Integer.BYTES*2];
|
|
||||||
NumericUtils.intToSortableBytes(r.from.intValue(), b, 0);
|
|
||||||
NumericUtils.intToSortableBytes(r.to.intValue(), b, Integer.BYTES);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Query withinQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
|
||||||
return IntRange.newWithinQuery(field, new int[] {(Integer)from + (includeFrom ? 0 : 1)},
|
return IntRange.newWithinQuery(field, new int[] {(Integer)from + (includeFrom ? 0 : 1)},
|
||||||
new int[] {(Integer)to - (includeTo ? 0 : 1)});
|
new int[] {(Integer)to - (includeTo ? 0 : 1)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query containsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query containsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return IntRange.newContainsQuery(field, new int[] {(Integer)from + (includeFrom ? 0 : 1)},
|
return IntRange.newContainsQuery(field, new int[] {(Integer)from + (includeFrom ? 0 : 1)},
|
||||||
new int[] {(Integer)to - (includeTo ? 0 : 1)});
|
new int[] {(Integer)to - (includeTo ? 0 : 1)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query intersectsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query intersectsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return IntRange.newIntersectsQuery(field, new int[] {(Integer)from + (includeFrom ? 0 : 1)},
|
return IntRange.newIntersectsQuery(field, new int[] {(Integer)from + (includeFrom ? 0 : 1)},
|
||||||
new int[] {(Integer)to - (includeTo ? 0 : 1)});
|
new int[] {(Integer)to - (includeTo ? 0 : 1)});
|
||||||
}
|
}
|
||||||
@ -647,43 +687,40 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return Long.MAX_VALUE;
|
return Long.MAX_VALUE;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Long nextUp(Number value) {
|
public Long nextUp(Object value) {
|
||||||
return value.longValue() + 1;
|
return ((Number)value).longValue() + 1;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Long nextDown(Number value) {
|
public Long nextDown(Object value) {
|
||||||
return value.longValue() - 1;
|
return ((Number)value).longValue() - 1;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Field getRangeField(String name, Range r) {
|
public Field getRangeField(String name, Range r) {
|
||||||
return new LongRange(name, new long[] {r.from.longValue()}, new long[] {r.to.longValue()});
|
return new LongRange(name, new long[] {((Number)r.from).longValue()},
|
||||||
|
new long[] {((Number)r.to).longValue()});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public byte[] getBytes(Range r) {
|
public Query withinQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
byte[] b = new byte[Long.BYTES*2];
|
|
||||||
long from = r.from == null ? Long.MIN_VALUE : r.from.longValue();
|
|
||||||
long to = r.to == null ? Long.MAX_VALUE : r.to.longValue();
|
|
||||||
NumericUtils.longToSortableBytes(from, b, 0);
|
|
||||||
NumericUtils.longToSortableBytes(to, b, Long.BYTES);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Query withinQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
|
||||||
return LongRange.newWithinQuery(field, new long[] {(Long)from + (includeFrom ? 0 : 1)},
|
return LongRange.newWithinQuery(field, new long[] {(Long)from + (includeFrom ? 0 : 1)},
|
||||||
new long[] {(Long)to - (includeTo ? 0 : 1)});
|
new long[] {(Long)to - (includeTo ? 0 : 1)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query containsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query containsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return LongRange.newContainsQuery(field, new long[] {(Long)from + (includeFrom ? 0 : 1)},
|
return LongRange.newContainsQuery(field, new long[] {(Long)from + (includeFrom ? 0 : 1)},
|
||||||
new long[] {(Long)to - (includeTo ? 0 : 1)});
|
new long[] {(Long)to - (includeTo ? 0 : 1)});
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Query intersectsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Query intersectsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
return LongRange.newIntersectsQuery(field, new long[] {(Long)from + (includeFrom ? 0 : 1)},
|
return LongRange.newIntersectsQuery(field, new long[] {(Long)from + (includeFrom ? 0 : 1)},
|
||||||
new long[] {(Long)to - (includeTo ? 0 : 1)});
|
new long[] {(Long)to - (includeTo ? 0 : 1)});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RangeType(String name) {
|
||||||
|
this.name = name;
|
||||||
|
this.numberType = null;
|
||||||
|
}
|
||||||
|
|
||||||
RangeType(String name, NumberType type) {
|
RangeType(String name, NumberType type) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.numberType = type;
|
this.numberType = type;
|
||||||
@ -694,7 +731,6 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract byte[] getBytes(Range range);
|
|
||||||
public abstract Field getRangeField(String name, Range range);
|
public abstract Field getRangeField(String name, Range range);
|
||||||
public List<IndexableField> createFields(String name, Range range, boolean indexed, boolean docValued, boolean stored) {
|
public List<IndexableField> createFields(String name, Range range, boolean indexed, boolean docValued, boolean stored) {
|
||||||
assert range != null : "range cannot be null when creating fields";
|
assert range != null : "range cannot be null when creating fields";
|
||||||
@ -709,29 +745,31 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
/** parses from value. rounds according to included flag */
|
/** parses from value. rounds according to included flag */
|
||||||
public Number parseFrom(RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included) throws IOException {
|
public Object parseFrom(RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included) throws IOException {
|
||||||
Number value = numberType.parse(parser, coerce);
|
Number value = numberType.parse(parser, coerce);
|
||||||
return included ? value : nextUp(value);
|
return included ? value : (Number)nextUp(value);
|
||||||
}
|
}
|
||||||
/** parses to value. rounds according to included flag */
|
/** parses to value. rounds according to included flag */
|
||||||
public Number parseTo(RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included) throws IOException {
|
public Object parseTo(RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included) throws IOException {
|
||||||
Number value = numberType.parse(parser, coerce);
|
Number value = numberType.parse(parser, coerce);
|
||||||
return included ? value : nextDown(value);
|
return included ? value : (Number)nextDown(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Number minValue();
|
public abstract Object minValue();
|
||||||
public abstract Number maxValue();
|
public abstract Object maxValue();
|
||||||
public abstract Number nextUp(Number value);
|
public abstract Object nextUp(Object value);
|
||||||
public abstract Number nextDown(Number value);
|
public abstract Object nextDown(Object value);
|
||||||
public abstract Query withinQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo);
|
public abstract Query withinQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo);
|
||||||
public abstract Query containsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo);
|
public abstract Query containsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo);
|
||||||
public abstract Query intersectsQuery(String field, Number from, Number to, boolean includeFrom, boolean includeTo);
|
public abstract Query intersectsQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo);
|
||||||
|
public Object parse(Object value, boolean coerce) {
|
||||||
|
return numberType.parse(value, coerce);
|
||||||
|
}
|
||||||
public Query rangeQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo,
|
public Query rangeQuery(String field, Object from, Object to, boolean includeFrom, boolean includeTo,
|
||||||
ShapeRelation relation, @Nullable DateTimeZone timeZone, @Nullable DateMathParser dateMathParser,
|
ShapeRelation relation, @Nullable DateTimeZone timeZone, @Nullable DateMathParser dateMathParser,
|
||||||
QueryShardContext context) {
|
QueryShardContext context) {
|
||||||
Number lower = from == null ? minValue() : numberType.parse(from, false);
|
Object lower = from == null ? minValue() : parse(from, false);
|
||||||
Number upper = to == null ? maxValue() : numberType.parse(to, false);
|
Object upper = to == null ? maxValue() : parse(to, false);
|
||||||
if (relation == ShapeRelation.WITHIN) {
|
if (relation == ShapeRelation.WITHIN) {
|
||||||
return withinQuery(field, lower, upper, includeFrom, includeTo);
|
return withinQuery(field, lower, upper, includeFrom, includeTo);
|
||||||
} else if (relation == ShapeRelation.CONTAINS) {
|
} else if (relation == ShapeRelation.CONTAINS) {
|
||||||
@ -747,12 +785,12 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
/** Class defining a range */
|
/** Class defining a range */
|
||||||
public static class Range {
|
public static class Range {
|
||||||
RangeType type;
|
RangeType type;
|
||||||
private Number from;
|
private Object from;
|
||||||
private Number to;
|
private Object to;
|
||||||
private boolean includeFrom;
|
private boolean includeFrom;
|
||||||
private boolean includeTo;
|
private boolean includeTo;
|
||||||
|
|
||||||
public Range(RangeType type, Number from, Number to, boolean includeFrom, boolean includeTo) {
|
public Range(RangeType type, Object from, Object to, boolean includeFrom, boolean includeTo) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.from = from;
|
this.from = from;
|
||||||
this.to = to;
|
this.to = to;
|
||||||
@ -764,9 +802,11 @@ public class RangeFieldMapper extends FieldMapper {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(includeFrom ? '[' : '(');
|
sb.append(includeFrom ? '[' : '(');
|
||||||
sb.append(includeFrom || from.equals(type.minValue()) ? from : type.nextDown(from));
|
Object f = includeFrom || from.equals(type.minValue()) ? from : type.nextDown(from);
|
||||||
sb.append(':');
|
Object t = includeTo || to.equals(type.maxValue()) ? to : type.nextUp(to);
|
||||||
sb.append(includeTo || to.equals(type.maxValue()) ? to : type.nextUp(to));
|
sb.append(type == RangeType.IP ? InetAddresses.toAddrString((InetAddress)f) : f.toString());
|
||||||
|
sb.append(" : ");
|
||||||
|
sb.append(type == RangeType.IP ? InetAddresses.toAddrString((InetAddress)t) : t.toString());
|
||||||
sb.append(includeTo ? ']' : ')');
|
sb.append(includeTo ? ']' : ')');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
|
import org.apache.lucene.document.InetAddressPoint;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.elasticsearch.common.compress.CompressedXContent;
|
import org.elasticsearch.common.compress.CompressedXContent;
|
||||||
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -40,6 +43,8 @@ import static org.hamcrest.Matchers.containsString;
|
|||||||
public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
||||||
private static String FROM_DATE = "2016-10-31";
|
private static String FROM_DATE = "2016-10-31";
|
||||||
private static String TO_DATE = "2016-11-01 20:00:00";
|
private static String TO_DATE = "2016-11-01 20:00:00";
|
||||||
|
private static String FROM_IP = "::ffff:c0a8:107";
|
||||||
|
private static String TO_IP = "2001:db8::";
|
||||||
private static int FROM = 5;
|
private static int FROM = 5;
|
||||||
private static String FROM_STR = FROM + "";
|
private static String FROM_STR = FROM + "";
|
||||||
private static int TO = 10;
|
private static int TO = 10;
|
||||||
@ -48,12 +53,14 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setTypeList() {
|
protected void setTypeList() {
|
||||||
TYPES = new HashSet<>(Arrays.asList("date_range", "float_range", "double_range", "integer_range", "long_range"));
|
TYPES = new HashSet<>(Arrays.asList("date_range", "ip_range", "float_range", "double_range", "integer_range", "long_range"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getFrom(String type) {
|
private Object getFrom(String type) {
|
||||||
if (type.equals("date_range")) {
|
if (type.equals("date_range")) {
|
||||||
return FROM_DATE;
|
return FROM_DATE;
|
||||||
|
} else if (type.equals("ip_range")) {
|
||||||
|
return FROM_IP;
|
||||||
}
|
}
|
||||||
return random().nextBoolean() ? FROM : FROM_STR;
|
return random().nextBoolean() ? FROM : FROM_STR;
|
||||||
}
|
}
|
||||||
@ -69,13 +76,17 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
private Object getTo(String type) {
|
private Object getTo(String type) {
|
||||||
if (type.equals("date_range")) {
|
if (type.equals("date_range")) {
|
||||||
return TO_DATE;
|
return TO_DATE;
|
||||||
|
} else if (type.equals("ip_range")) {
|
||||||
|
return TO_IP;
|
||||||
}
|
}
|
||||||
return random().nextBoolean() ? TO : TO_STR;
|
return random().nextBoolean() ? TO : TO_STR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Number getMax(String type) {
|
private Object getMax(String type) {
|
||||||
if (type.equals("date_range") || type.equals("long_range")) {
|
if (type.equals("date_range") || type.equals("long_range")) {
|
||||||
return Long.MAX_VALUE;
|
return Long.MAX_VALUE;
|
||||||
|
} else if (type.equals("ip_range")) {
|
||||||
|
return InetAddressPoint.MAX_VALUE;
|
||||||
} else if (type.equals("integer_range")) {
|
} else if (type.equals("integer_range")) {
|
||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
} else if (type.equals("float_range")) {
|
} else if (type.equals("float_range")) {
|
||||||
@ -189,7 +200,14 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
assertEquals(2, pointField.fieldType().pointDimensionCount());
|
assertEquals(2, pointField.fieldType().pointDimensionCount());
|
||||||
IndexableField storedField = fields[1];
|
IndexableField storedField = fields[1];
|
||||||
assertTrue(storedField.fieldType().stored());
|
assertTrue(storedField.fieldType().stored());
|
||||||
assertThat(storedField.stringValue(), containsString(type.equals("date_range") ? "1477872000000" : "5"));
|
String strVal = "5";
|
||||||
|
if (type.equals("date_range")) {
|
||||||
|
strVal = "1477872000000";
|
||||||
|
} else if (type.equals("ip_range")) {
|
||||||
|
strVal = InetAddresses.toAddrString(InetAddresses.forString("192.168.1.7")) + " : "
|
||||||
|
+ InetAddresses.toAddrString(InetAddresses.forString("2001:db8:0:0:0:0:0:0"));
|
||||||
|
}
|
||||||
|
assertThat(storedField.stringValue(), containsString(strVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -234,7 +252,8 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
.endObject().bytes(),
|
.endObject().bytes(),
|
||||||
XContentType.JSON));
|
XContentType.JSON));
|
||||||
MapperParsingException e = expectThrows(MapperParsingException.class, runnable);
|
MapperParsingException e = expectThrows(MapperParsingException.class, runnable);
|
||||||
assertThat(e.getCause().getMessage(), anyOf(containsString("passed as String"), containsString("failed to parse date")));
|
assertThat(e.getCause().getMessage(), anyOf(containsString("passed as String"),
|
||||||
|
containsString("failed to parse date"), containsString("is not an IP string literal")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -261,7 +280,8 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
assertEquals(2, doc.rootDoc().getFields("field").length);
|
assertEquals(2, doc.rootDoc().getFields("field").length);
|
||||||
IndexableField[] fields = doc.rootDoc().getFields("field");
|
IndexableField[] fields = doc.rootDoc().getFields("field");
|
||||||
IndexableField storedField = fields[1];
|
IndexableField storedField = fields[1];
|
||||||
assertThat(storedField.stringValue(), containsString(type.equals("date_range") ? Long.MAX_VALUE+"" : getMax(type)+""));
|
String expected = type.equals("ip_range") ? InetAddresses.toAddrString((InetAddress)getMax(type)) : getMax(type) +"";
|
||||||
|
assertThat(storedField.stringValue(), containsString(expected));
|
||||||
|
|
||||||
// test null max value
|
// test null max value
|
||||||
doc = mapper.parse(SourceToParse.source("test", "type", "1", XContentFactory.jsonBuilder()
|
doc = mapper.parse(SourceToParse.source("test", "type", "1", XContentFactory.jsonBuilder()
|
||||||
@ -280,8 +300,14 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
assertFalse(pointField.fieldType().stored());
|
assertFalse(pointField.fieldType().stored());
|
||||||
storedField = fields[1];
|
storedField = fields[1];
|
||||||
assertTrue(storedField.fieldType().stored());
|
assertTrue(storedField.fieldType().stored());
|
||||||
assertThat(storedField.stringValue(), containsString(type.equals("date_range") ? "1477872000000" : "5"));
|
String strVal = "5";
|
||||||
assertThat(storedField.stringValue(), containsString(getMax(type) + ""));
|
if (type.equals("date_range")) {
|
||||||
|
strVal = "1477872000000";
|
||||||
|
} else if (type.equals("ip_range")) {
|
||||||
|
strVal = InetAddresses.toAddrString(InetAddresses.forString("192.168.1.7")) + " : "
|
||||||
|
+ InetAddresses.toAddrString(InetAddresses.forString("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
|
||||||
|
}
|
||||||
|
assertThat(storedField.stringValue(), containsString(strVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoBounds() throws Exception {
|
public void testNoBounds() throws Exception {
|
||||||
@ -316,8 +342,8 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
|||||||
assertFalse(pointField.fieldType().stored());
|
assertFalse(pointField.fieldType().stored());
|
||||||
IndexableField storedField = fields[1];
|
IndexableField storedField = fields[1];
|
||||||
assertTrue(storedField.fieldType().stored());
|
assertTrue(storedField.fieldType().stored());
|
||||||
assertThat(storedField.stringValue(), containsString(type.equals("date_range") ? Long.MAX_VALUE+"" : getMax(type)+""));
|
String expected = type.equals("ip_range") ? InetAddresses.toAddrString((InetAddress)getMax(type)) : getMax(type) +"";
|
||||||
assertThat(storedField.stringValue(), containsString(getMax(type) + ""));
|
assertThat(storedField.stringValue(), containsString(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIllegalArguments() throws Exception {
|
public void testIllegalArguments() throws Exception {
|
||||||
|
@ -21,6 +21,8 @@ package org.elasticsearch.index.mapper;
|
|||||||
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
||||||
import org.apache.lucene.document.DoubleRange;
|
import org.apache.lucene.document.DoubleRange;
|
||||||
import org.apache.lucene.document.FloatRange;
|
import org.apache.lucene.document.FloatRange;
|
||||||
|
import org.apache.lucene.document.InetAddressPoint;
|
||||||
|
import org.apache.lucene.document.InetAddressRange;
|
||||||
import org.apache.lucene.document.IntRange;
|
import org.apache.lucene.document.IntRange;
|
||||||
import org.apache.lucene.document.LongRange;
|
import org.apache.lucene.document.LongRange;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
@ -37,6 +39,7 @@ import org.elasticsearch.test.IndexSettingsModule;
|
|||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class RangeFieldTypeTests extends FieldTypeTestCase {
|
public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
@ -100,6 +103,8 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||||||
return getLongRangeQuery(relation, (long)from, (long)to, includeLower, includeUpper);
|
return getLongRangeQuery(relation, (long)from, (long)to, includeLower, includeUpper);
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
return getDoubleRangeQuery(relation, (double)from, (double)to, includeLower, includeUpper);
|
return getDoubleRangeQuery(relation, (double)from, (double)to, includeLower, includeUpper);
|
||||||
|
case IP:
|
||||||
|
return getInetAddressRangeQuery(relation, (InetAddress)from, (InetAddress)to, includeLower, includeUpper);
|
||||||
default:
|
default:
|
||||||
return getFloatRangeQuery(relation, (float)from, (float)to, includeLower, includeUpper);
|
return getFloatRangeQuery(relation, (float)from, (float)to, includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
@ -142,7 +147,8 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||||||
return FloatRange.newIntersectsQuery(FIELDNAME, lower, upper);
|
return FloatRange.newIntersectsQuery(FIELDNAME, lower, upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Query getDoubleRangeQuery(ShapeRelation relation, double from, double to, boolean includeLower, boolean includeUpper) {
|
private Query getDoubleRangeQuery(ShapeRelation relation, double from, double to, boolean includeLower,
|
||||||
|
boolean includeUpper) {
|
||||||
double[] lower = new double[] {includeLower ? from : Math.nextUp(from)};
|
double[] lower = new double[] {includeLower ? from : Math.nextUp(from)};
|
||||||
double[] upper = new double[] {includeUpper ? to : Math.nextDown(to)};
|
double[] upper = new double[] {includeUpper ? to : Math.nextDown(to)};
|
||||||
if (relation == ShapeRelation.WITHIN) {
|
if (relation == ShapeRelation.WITHIN) {
|
||||||
@ -153,7 +159,19 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||||||
return DoubleRange.newIntersectsQuery(FIELDNAME, lower, upper);
|
return DoubleRange.newIntersectsQuery(FIELDNAME, lower, upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object nextFrom() {
|
private Query getInetAddressRangeQuery(ShapeRelation relation, InetAddress from, InetAddress to, boolean includeLower,
|
||||||
|
boolean includeUpper) {
|
||||||
|
InetAddress lower = includeLower ? from : InetAddressPoint.nextUp(from);
|
||||||
|
InetAddress upper = includeUpper ? to : InetAddressPoint.nextDown(to);
|
||||||
|
if (relation == ShapeRelation.WITHIN) {
|
||||||
|
return InetAddressRange.newWithinQuery(FIELDNAME, lower, upper);
|
||||||
|
} else if (relation == ShapeRelation.CONTAINS) {
|
||||||
|
return InetAddressRange.newContainsQuery(FIELDNAME, lower, upper);
|
||||||
|
}
|
||||||
|
return InetAddressRange.newIntersectsQuery(FIELDNAME, lower, upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object nextFrom() throws Exception {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
return (int)(random().nextInt() * 0.5 - DISTANCE);
|
return (int)(random().nextInt() * 0.5 - DISTANCE);
|
||||||
@ -163,12 +181,14 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||||||
return (long)(random().nextLong() * 0.5 - DISTANCE);
|
return (long)(random().nextLong() * 0.5 - DISTANCE);
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
return (float)(random().nextFloat() * 0.5 - DISTANCE);
|
return (float)(random().nextFloat() * 0.5 - DISTANCE);
|
||||||
|
case IP:
|
||||||
|
return InetAddress.getByName("::ffff:c0a8:107");
|
||||||
default:
|
default:
|
||||||
return random().nextDouble() * 0.5 - DISTANCE;
|
return random().nextDouble() * 0.5 - DISTANCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object nextTo(Object from) {
|
private Object nextTo(Object from) throws Exception {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
return (Integer)from + DISTANCE;
|
return (Integer)from + DISTANCE;
|
||||||
@ -178,6 +198,8 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
|||||||
return (Long)from + DISTANCE;
|
return (Long)from + DISTANCE;
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
return (Double)from + DISTANCE;
|
return (Double)from + DISTANCE;
|
||||||
|
case IP:
|
||||||
|
return InetAddress.getByName("2001:db8::");
|
||||||
default:
|
default:
|
||||||
return (Float)from + DISTANCE;
|
return (Float)from + DISTANCE;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ The following range types are supported:
|
|||||||
`long_range`:: A range of signed 64-bit integers with a minimum value of +-2^63^+ and maximum of +2^63^-1+.
|
`long_range`:: A range of signed 64-bit integers with a minimum value of +-2^63^+ and maximum of +2^63^-1+.
|
||||||
`double_range`:: A range of double-precision 64-bit IEEE 754 floating point values.
|
`double_range`:: A range of double-precision 64-bit IEEE 754 floating point values.
|
||||||
`date_range`:: A range of date values represented as unsigned 64-bit integer milliseconds elapsed since system epoch.
|
`date_range`:: A range of date values represented as unsigned 64-bit integer milliseconds elapsed since system epoch.
|
||||||
|
`ip_range` :: A range of ip values supporting either https://en.wikipedia.org/wiki/IPv4[IPv4] or
|
||||||
|
https://en.wikipedia.org/wiki/IPv6[IPv6] (or mixed) addresses.
|
||||||
|
|
||||||
Below is an example of configuring a mapping with various range fields followed by an example that indexes several range types.
|
Below is an example of configuring a mapping with various range fields followed by an example that indexes several range types.
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ Internal::
|
|||||||
|
|
||||||
Core::
|
Core::
|
||||||
* Enable index-time sorting {pull}24055[#24055] (issue: {issue}6720[#6720])
|
* Enable index-time sorting {pull}24055[#24055] (issue: {issue}6720[#6720])
|
||||||
|
* Add new ip_range field type {pull}24433[#24433]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user