mirror of https://github.com/apache/lucene.git
LUCENE-7850: Move support for legacy numerics to solr/.
This commit is contained in:
parent
412e4ae2c1
commit
759fa42b62
|
@ -57,6 +57,8 @@ API Changes
|
|||
instead, which derived from the UH. WholeBreakIterator and
|
||||
CustomSeparatorBreakIterator were moved to UH's package. (David Smiley)
|
||||
|
||||
* LUCENE-7850: Removed support for legacy numerics. (Adrien Grand)
|
||||
|
||||
Bug Fixes
|
||||
|
||||
* LUCENE-7626: IndexWriter will no longer accept broken token offsets
|
||||
|
|
|
@ -74,3 +74,9 @@ collecting TopDocs for each group, but instead takes a GroupReducer that will
|
|||
perform any type of reduction on the top groups collected on a first-pass. To
|
||||
reproduce the old behaviour of SecondPassGroupingCollector, you should instead
|
||||
use TopGroupsCollector.
|
||||
|
||||
## Removed legacy numerics (LUCENE-7850)
|
||||
|
||||
Support for legacy numerics has been removed since legacy numerics had been
|
||||
deprecated since Lucene 6.0. Points should be used instead, see
|
||||
org.apache.lucene.index.PointValues for an introduction.
|
||||
|
|
|
@ -60,10 +60,6 @@ import org.apache.lucene.document.SortedSetDocValuesField;
|
|||
import org.apache.lucene.document.StringField;
|
||||
import org.apache.lucene.document.TextField;
|
||||
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
|
@ -1114,9 +1110,6 @@ public class TestBackwardsCompatibility extends LuceneTestCase {
|
|||
doc.add(new Field("utf8", "Lu\uD834\uDD1Ece\uD834\uDD60ne \u0000 \u2620 ab\ud917\udc17cd", customType2));
|
||||
doc.add(new Field("content2", "here is more content with aaa aaa aaa", customType2));
|
||||
doc.add(new Field("fie\u2C77ld", "field with non-ascii name", customType2));
|
||||
// add numeric fields, to test if flex preserves encoding
|
||||
doc.add(new LegacyIntField("trieInt", id, Field.Store.NO));
|
||||
doc.add(new LegacyLongField("trieLong", (long) id, Field.Store.NO));
|
||||
|
||||
// add docvalues fields
|
||||
doc.add(new NumericDocValuesField("dvByte", (byte) id));
|
||||
|
@ -1294,51 +1287,6 @@ public class TestBackwardsCompatibility extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testNumericFields() throws Exception {
|
||||
for (String name : oldNames) {
|
||||
|
||||
Directory dir = oldIndexDirs.get(name);
|
||||
IndexReader reader = DirectoryReader.open(dir);
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
|
||||
for (int id=10; id<15; id++) {
|
||||
ScoreDoc[] hits = searcher.search(LegacyNumericRangeQuery.newIntRange("trieInt", LegacyNumericUtils.PRECISION_STEP_DEFAULT_32, Integer.valueOf(id), Integer.valueOf(id), true, true), 100).scoreDocs;
|
||||
assertEquals("wrong number of hits", 1, hits.length);
|
||||
Document d = searcher.doc(hits[0].doc);
|
||||
assertEquals(String.valueOf(id), d.get("id"));
|
||||
|
||||
hits = searcher.search(LegacyNumericRangeQuery.newLongRange("trieLong", LegacyNumericUtils.PRECISION_STEP_DEFAULT, Long.valueOf(id), Long.valueOf(id), true, true), 100).scoreDocs;
|
||||
assertEquals("wrong number of hits", 1, hits.length);
|
||||
d = searcher.doc(hits[0].doc);
|
||||
assertEquals(String.valueOf(id), d.get("id"));
|
||||
}
|
||||
|
||||
// check that also lower-precision fields are ok
|
||||
ScoreDoc[] hits = searcher.search(LegacyNumericRangeQuery.newIntRange("trieInt", LegacyNumericUtils.PRECISION_STEP_DEFAULT_32, Integer.MIN_VALUE, Integer.MAX_VALUE, false, false), 100).scoreDocs;
|
||||
assertEquals("wrong number of hits", 34, hits.length);
|
||||
|
||||
hits = searcher.search(LegacyNumericRangeQuery.newLongRange("trieLong", LegacyNumericUtils.PRECISION_STEP_DEFAULT, Long.MIN_VALUE, Long.MAX_VALUE, false, false), 100).scoreDocs;
|
||||
assertEquals("wrong number of hits", 34, hits.length);
|
||||
|
||||
// check decoding of terms
|
||||
Terms terms = MultiFields.getTerms(searcher.getIndexReader(), "trieInt");
|
||||
TermsEnum termsEnum = LegacyNumericUtils.filterPrefixCodedInts(terms.iterator());
|
||||
while (termsEnum.next() != null) {
|
||||
int val = LegacyNumericUtils.prefixCodedToInt(termsEnum.term());
|
||||
assertTrue("value in id bounds", val >= 0 && val < 35);
|
||||
}
|
||||
|
||||
terms = MultiFields.getTerms(searcher.getIndexReader(), "trieLong");
|
||||
termsEnum = LegacyNumericUtils.filterPrefixCodedLongs(terms.iterator());
|
||||
while (termsEnum.next() != null) {
|
||||
long val = LegacyNumericUtils.prefixCodedToLong(termsEnum.term());
|
||||
assertTrue("value in id bounds", val >= 0L && val < 35L);
|
||||
}
|
||||
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
private int checkAllSegmentsUpgraded(Directory dir, int indexCreatedVersion) throws IOException {
|
||||
final SegmentInfos infos = SegmentInfos.readLatestCommit(dir);
|
||||
if (VERBOSE) {
|
||||
|
|
|
@ -25,11 +25,6 @@ import org.apache.lucene.document.StringField;
|
|||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.legacy.LegacyDoubleField;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.legacy.LegacyNumericType;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
@ -41,8 +36,6 @@ import org.apache.lucene.spatial.query.SpatialArgs;
|
|||
import org.apache.lucene.spatial.query.SpatialOperation;
|
||||
import org.apache.lucene.spatial.query.UnsupportedSpatialOperation;
|
||||
import org.apache.lucene.spatial.util.DistanceToShapeValueSource;
|
||||
import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.locationtech.spatial4j.context.SpatialContext;
|
||||
import org.locationtech.spatial4j.shape.Point;
|
||||
import org.locationtech.spatial4j.shape.Rectangle;
|
||||
|
@ -88,8 +81,6 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
*/
|
||||
public static FieldType DEFAULT_FIELDTYPE;
|
||||
|
||||
@Deprecated
|
||||
public static LegacyFieldType LEGACY_FIELDTYPE;
|
||||
static {
|
||||
// Default: pointValues + docValues
|
||||
FieldType type = new FieldType();
|
||||
|
@ -98,15 +89,6 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
type.setStored(false);
|
||||
type.freeze();
|
||||
DEFAULT_FIELDTYPE = type;
|
||||
// Legacy default: legacyNumerics + docValues
|
||||
LegacyFieldType legacyType = new LegacyFieldType();
|
||||
legacyType.setIndexOptions(IndexOptions.DOCS);
|
||||
legacyType.setNumericType(LegacyNumericType.DOUBLE);
|
||||
legacyType.setNumericPrecisionStep(8);// same as solr default
|
||||
legacyType.setDocValuesType(DocValuesType.NUMERIC);//docValues
|
||||
legacyType.setStored(false);
|
||||
legacyType.freeze();
|
||||
LEGACY_FIELDTYPE = legacyType;
|
||||
}
|
||||
|
||||
public static final String SUFFIX_MINX = "__minX";
|
||||
|
@ -131,8 +113,6 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
private final boolean hasStored;
|
||||
private final boolean hasDocVals;
|
||||
private final boolean hasPointVals;
|
||||
// equiv to "hasLegacyNumerics":
|
||||
private final LegacyFieldType legacyNumericFieldType; // not stored; holds precision step.
|
||||
private final FieldType xdlFieldType;
|
||||
|
||||
/**
|
||||
|
@ -142,15 +122,6 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
return new BBoxStrategy(ctx, fieldNamePrefix, DEFAULT_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BBoxStrategy} instance that uses {@link LegacyDoubleField} for backwards compatibility
|
||||
* @deprecated LegacyNumerics will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public static BBoxStrategy newLegacyInstance(SpatialContext ctx, String fieldNamePrefix) {
|
||||
return new BBoxStrategy(ctx, fieldNamePrefix, LEGACY_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this strategy.
|
||||
* {@code fieldType} is used to customize the indexing options of the 4 number fields, and to a lesser degree the XDL
|
||||
|
@ -179,23 +150,8 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
if ((this.hasPointVals = fieldType.pointDimensionCount() > 0)) {
|
||||
numQuads++;
|
||||
}
|
||||
if (fieldType.indexOptions() != IndexOptions.NONE && fieldType instanceof LegacyFieldType && ((LegacyFieldType)fieldType).numericType() != null) {
|
||||
if (hasPointVals) {
|
||||
throw new IllegalArgumentException("pointValues and LegacyNumericType are mutually exclusive");
|
||||
}
|
||||
final LegacyFieldType legacyType = (LegacyFieldType) fieldType;
|
||||
if (legacyType.numericType() != LegacyNumericType.DOUBLE) {
|
||||
throw new IllegalArgumentException(getClass() + " does not support " + legacyType.numericType());
|
||||
}
|
||||
numQuads++;
|
||||
legacyNumericFieldType = new LegacyFieldType(LegacyDoubleField.TYPE_NOT_STORED);
|
||||
legacyNumericFieldType.setNumericPrecisionStep(legacyType.numericPrecisionStep());
|
||||
legacyNumericFieldType.freeze();
|
||||
} else {
|
||||
legacyNumericFieldType = null;
|
||||
}
|
||||
|
||||
if (hasPointVals || legacyNumericFieldType != null) { // if we have an index...
|
||||
if (hasPointVals) { // if we have an index...
|
||||
xdlFieldType = new FieldType(StringField.TYPE_NOT_STORED);
|
||||
xdlFieldType.setIndexOptions(IndexOptions.DOCS);
|
||||
xdlFieldType.freeze();
|
||||
|
@ -242,12 +198,6 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
fields[++idx] = new DoublePoint(field_maxX, bbox.getMaxX());
|
||||
fields[++idx] = new DoublePoint(field_maxY, bbox.getMaxY());
|
||||
}
|
||||
if (legacyNumericFieldType != null) {
|
||||
fields[++idx] = new LegacyDoubleField(field_minX, bbox.getMinX(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(field_minY, bbox.getMinY(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(field_maxX, bbox.getMaxX(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(field_maxY, bbox.getMaxY(), legacyNumericFieldType);
|
||||
}
|
||||
if (xdlFieldType != null) {
|
||||
fields[++idx] = new Field(field_xdl, bbox.getCrossesDateLine()?"T":"F", xdlFieldType);
|
||||
}
|
||||
|
@ -664,17 +614,12 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
private Query makeNumberTermQuery(String field, double number) {
|
||||
if (hasPointVals) {
|
||||
return DoublePoint.newExactQuery(field, number);
|
||||
} else if (legacyNumericFieldType != null) {
|
||||
BytesRefBuilder bytes = new BytesRefBuilder();
|
||||
LegacyNumericUtils.longToPrefixCoded(NumericUtils.doubleToSortableLong(number), 0, bytes);
|
||||
return new TermQuery(new Term(field, bytes.get()));
|
||||
}
|
||||
throw new UnsupportedOperationException("An index is required for this operation.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric range query based on FieldType
|
||||
* {@link LegacyNumericRangeQuery} is used for indexes created using {@code FieldType.LegacyNumericType}
|
||||
* {@link DoublePoint#newRangeQuery} is used for indexes created using {@link DoublePoint} fields
|
||||
*
|
||||
* @param fieldname field name. must not be <code>null</code>.
|
||||
|
@ -702,8 +647,6 @@ public class BBoxStrategy extends SpatialStrategy {
|
|||
}
|
||||
|
||||
return DoublePoint.newRangeQuery(fieldname, min, max);
|
||||
} else if (legacyNumericFieldType != null) {// todo remove legacy numeric support in 7.0
|
||||
return LegacyNumericRangeQuery.newDoubleRange(fieldname, legacyNumericFieldType.numericPrecisionStep(), min, max, minInclusive, maxInclusive);
|
||||
}
|
||||
throw new UnsupportedOperationException("An index is required for this operation.");
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ import org.apache.lucene.util.BytesRefIterator;
|
|||
/**
|
||||
* A TokenStream used internally by {@link org.apache.lucene.spatial.prefix.PrefixTreeStrategy}.
|
||||
*
|
||||
* This is modelled after {@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
class BytesRefIteratorTokenStream extends TokenStream {
|
||||
|
|
|
@ -22,11 +22,6 @@ import org.apache.lucene.document.Field;
|
|||
import org.apache.lucene.document.FieldType;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.legacy.LegacyDoubleField;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.legacy.LegacyNumericType;
|
||||
import org.apache.lucene.queries.function.FunctionRangeQuery;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
|
@ -86,8 +81,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
*/
|
||||
public static FieldType DEFAULT_FIELDTYPE;
|
||||
|
||||
@Deprecated
|
||||
public static LegacyFieldType LEGACY_FIELDTYPE;
|
||||
static {
|
||||
// Default: pointValues + docValues
|
||||
FieldType type = new FieldType();
|
||||
|
@ -96,15 +89,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
type.setStored(false);
|
||||
type.freeze();
|
||||
DEFAULT_FIELDTYPE = type;
|
||||
// Legacy default: legacyNumerics
|
||||
LegacyFieldType legacyType = new LegacyFieldType();
|
||||
legacyType.setIndexOptions(IndexOptions.DOCS);
|
||||
legacyType.setNumericType(LegacyNumericType.DOUBLE);
|
||||
legacyType.setNumericPrecisionStep(8);// same as solr default
|
||||
legacyType.setDocValuesType(DocValuesType.NONE);//no docValues!
|
||||
legacyType.setStored(false);
|
||||
legacyType.freeze();
|
||||
LEGACY_FIELDTYPE = legacyType;
|
||||
}
|
||||
|
||||
public static final String SUFFIX_X = "__x";
|
||||
|
@ -117,8 +101,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
private final boolean hasStored;
|
||||
private final boolean hasDocVals;
|
||||
private final boolean hasPointVals;
|
||||
// equiv to "hasLegacyNumerics":
|
||||
private final LegacyFieldType legacyNumericFieldType; // not stored; holds precision step.
|
||||
|
||||
/**
|
||||
* Create a new {@link PointVectorStrategy} instance that uses {@link DoublePoint} and {@link DoublePoint#newRangeQuery}
|
||||
|
@ -127,18 +109,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
return new PointVectorStrategy(ctx, fieldNamePrefix, DEFAULT_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link PointVectorStrategy} instance that uses {@link LegacyDoubleField} for backwards compatibility.
|
||||
* However, back-compat is limited; we don't support circle queries or {@link #makeDistanceValueSource(Point, double)}
|
||||
* since that requires docValues (the legacy config didn't have that).
|
||||
*
|
||||
* @deprecated LegacyNumerics will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public static PointVectorStrategy newLegacyInstance(SpatialContext ctx, String fieldNamePrefix) {
|
||||
return new PointVectorStrategy(ctx, fieldNamePrefix, LEGACY_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance configured with the provided FieldType options. See {@link #DEFAULT_FIELDTYPE}.
|
||||
* a field type is used to articulate the desired options (namely pointValues, docValues, stored). Legacy numerics
|
||||
|
@ -159,21 +129,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
if ((this.hasPointVals = fieldType.pointDimensionCount() > 0)) {
|
||||
numPairs++;
|
||||
}
|
||||
if (fieldType.indexOptions() != IndexOptions.NONE && fieldType instanceof LegacyFieldType && ((LegacyFieldType)fieldType).numericType() != null) {
|
||||
if (hasPointVals) {
|
||||
throw new IllegalArgumentException("pointValues and LegacyNumericType are mutually exclusive");
|
||||
}
|
||||
final LegacyFieldType legacyType = (LegacyFieldType) fieldType;
|
||||
if (legacyType.numericType() != LegacyNumericType.DOUBLE) {
|
||||
throw new IllegalArgumentException(getClass() + " does not support " + legacyType.numericType());
|
||||
}
|
||||
numPairs++;
|
||||
legacyNumericFieldType = new LegacyFieldType(LegacyDoubleField.TYPE_NOT_STORED);
|
||||
legacyNumericFieldType.setNumericPrecisionStep(legacyType.numericPrecisionStep());
|
||||
legacyNumericFieldType.freeze();
|
||||
} else {
|
||||
legacyNumericFieldType = null;
|
||||
}
|
||||
this.fieldsLen = numPairs * 2;
|
||||
}
|
||||
|
||||
|
@ -209,10 +164,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
fields[++idx] = new DoublePoint(fieldNameX, point.getX());
|
||||
fields[++idx] = new DoublePoint(fieldNameY, point.getY());
|
||||
}
|
||||
if (legacyNumericFieldType != null) {
|
||||
fields[++idx] = new LegacyDoubleField(fieldNameX, point.getX(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(fieldNameY, point.getY(), legacyNumericFieldType);
|
||||
}
|
||||
assert idx == fields.length - 1;
|
||||
return fields;
|
||||
}
|
||||
|
@ -268,7 +219,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
|
||||
/**
|
||||
* Returns a numeric range query based on FieldType
|
||||
* {@link LegacyNumericRangeQuery} is used for indexes created using {@code FieldType.LegacyNumericType}
|
||||
* {@link DoublePoint#newRangeQuery} is used for indexes created using {@link DoublePoint} fields
|
||||
*/
|
||||
private Query rangeQuery(String fieldName, Double min, Double max) {
|
||||
|
@ -283,8 +233,6 @@ public class PointVectorStrategy extends SpatialStrategy {
|
|||
|
||||
return DoublePoint.newRangeQuery(fieldName, min, max);
|
||||
|
||||
} else if (legacyNumericFieldType != null) {// todo remove legacy numeric support in 7.0
|
||||
return LegacyNumericRangeQuery.newDoubleRange(fieldName, legacyNumericFieldType.numericPrecisionStep(), min, max, true, true);//inclusive
|
||||
}
|
||||
//TODO try doc-value range query?
|
||||
throw new UnsupportedOperationException("An index is required for this operation.");
|
||||
|
|
|
@ -68,9 +68,6 @@ public class DistanceStrategyTest extends StrategyTestCase {
|
|||
strategy = BBoxStrategy.newInstance(ctx, "bbox");
|
||||
ctorArgs.add(new Object[]{strategy.getFieldName(), strategy});
|
||||
|
||||
strategy = BBoxStrategy.newLegacyInstance(ctx, "bbox_legacy");
|
||||
ctorArgs.add(new Object[]{strategy.getFieldName(), strategy});
|
||||
|
||||
strategy = new SerializedDVStrategy(ctx, "serialized");
|
||||
ctorArgs.add(new Object[]{strategy.getFieldName(), strategy});
|
||||
|
||||
|
|
|
@ -58,9 +58,7 @@ public class QueryEqualsHashCodeTest extends LuceneTestCase {
|
|||
strategies.add(recursive_geohash);
|
||||
strategies.add(new TermQueryPrefixTreeStrategy(gridQuad, "termquery_quad"));
|
||||
strategies.add(PointVectorStrategy.newInstance(ctx, "pointvector"));
|
||||
strategies.add(PointVectorStrategy.newLegacyInstance(ctx, "pointvector_legacy"));
|
||||
strategies.add(BBoxStrategy.newInstance(ctx, "bbox"));
|
||||
strategies.add(BBoxStrategy.newLegacyInstance(ctx, "bbox_legacy"));
|
||||
final SerializedDVStrategy serialized = new SerializedDVStrategy(ctx, "serialized");
|
||||
strategies.add(serialized);
|
||||
strategies.add(new CompositeSpatialStrategy("composite", recursive_geohash, serialized));
|
||||
|
|
|
@ -21,8 +21,6 @@ import java.io.IOException;
|
|||
import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
||||
import org.apache.lucene.document.FieldType;
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.spatial.SpatialMatchConcern;
|
||||
import org.apache.lucene.spatial.prefix.RandomSpatialOpStrategyTestCase;
|
||||
|
@ -93,20 +91,10 @@ public class TestBBoxStrategy extends RandomSpatialOpStrategyTestCase {
|
|||
factory.worldBounds = new RectangleImpl(-300, 300, -100, 100, null);
|
||||
this.ctx = factory.newSpatialContext();
|
||||
}
|
||||
// randomly test legacy (numeric) and point based bbox strategy
|
||||
if (random().nextBoolean()) {
|
||||
this.strategy = BBoxStrategy.newInstance(ctx, "bbox");
|
||||
} else {
|
||||
this.strategy = BBoxStrategy.newLegacyInstance(ctx, "bbox");
|
||||
}
|
||||
this.strategy = BBoxStrategy.newInstance(ctx, "bbox");
|
||||
//test we can disable docValues for predicate tests
|
||||
if (random().nextBoolean()) {
|
||||
FieldType fieldType = ((BBoxStrategy)strategy).getFieldType();
|
||||
if (fieldType instanceof LegacyFieldType) {
|
||||
fieldType = new LegacyFieldType((LegacyFieldType)fieldType);
|
||||
} else {
|
||||
fieldType = new FieldType(fieldType);
|
||||
}
|
||||
FieldType fieldType = new FieldType(((BBoxStrategy)strategy).getFieldType());
|
||||
fieldType.setDocValuesType(DocValuesType.NONE);
|
||||
strategy = new BBoxStrategy(ctx, strategy.getFieldName(), fieldType);
|
||||
}
|
||||
|
@ -194,11 +182,7 @@ public class TestBBoxStrategy extends RandomSpatialOpStrategyTestCase {
|
|||
|
||||
private void setupGeo() {
|
||||
this.ctx = SpatialContext.GEO;
|
||||
if (random().nextBoolean()) {
|
||||
this.strategy = BBoxStrategy.newInstance(ctx, "bbox");
|
||||
} else {
|
||||
this.strategy = BBoxStrategy.newLegacyInstance(ctx, "bbox");
|
||||
}
|
||||
this.strategy = BBoxStrategy.newInstance(ctx, "bbox");
|
||||
}
|
||||
|
||||
// OLD STATIC TESTS (worthless?)
|
||||
|
@ -239,16 +223,9 @@ public class TestBBoxStrategy extends RandomSpatialOpStrategyTestCase {
|
|||
FieldType fieldType;
|
||||
// random legacy or not legacy
|
||||
String FIELD_PREFIX = "bbox";
|
||||
fieldType = new FieldType(BBoxStrategy.DEFAULT_FIELDTYPE);
|
||||
if (random().nextBoolean()) {
|
||||
fieldType = new FieldType(BBoxStrategy.DEFAULT_FIELDTYPE);
|
||||
if (random().nextBoolean()) {
|
||||
fieldType.setDimensions(0, 0);
|
||||
}
|
||||
} else {
|
||||
fieldType = new FieldType(BBoxStrategy.LEGACY_FIELDTYPE);
|
||||
if (random().nextBoolean()) {
|
||||
fieldType.setIndexOptions(IndexOptions.NONE);
|
||||
}
|
||||
fieldType.setDimensions(0, 0);
|
||||
}
|
||||
|
||||
strategy = new BBoxStrategy(ctx, FIELD_PREFIX, fieldType);
|
||||
|
|
|
@ -63,12 +63,7 @@ public class TestPointVectorStrategy extends StrategyTestCase {
|
|||
@Test
|
||||
public void testCitiesIntersectsBBox() throws IOException {
|
||||
// note: does not require docValues
|
||||
if (random().nextBoolean()) {
|
||||
this.strategy = PointVectorStrategy.newInstance(ctx, getClass().getSimpleName());
|
||||
} else {
|
||||
// switch to legacy instance sometimes, which has no docValues
|
||||
this.strategy = PointVectorStrategy.newLegacyInstance(ctx, getClass().getSimpleName());
|
||||
}
|
||||
this.strategy = PointVectorStrategy.newInstance(ctx, getClass().getSimpleName());
|
||||
getAddAndVerifyIndexedDocuments(DATA_WORLD_CITIES_POINTS);
|
||||
executeQueries(SpatialMatchConcern.FILTER, QTEST_Cities_Intersects_BBox);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.io.IOException;
|
|||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.apache.solr.schema.FieldType;
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.Map;
|
|||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.NumericDocValues;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.docvalues.LongDocValues;
|
||||
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
|
||||
|
|
|
@ -0,0 +1,706 @@
|
|||
/*
|
||||
* 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.legacy;
|
||||
|
||||
import org.apache.lucene.document.DoubleDocValuesField;
|
||||
import org.apache.lucene.document.DoublePoint;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.FieldType;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.document.StringField;
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.spatial.SpatialStrategy;
|
||||
import org.apache.lucene.spatial.bbox.BBoxOverlapRatioValueSource;
|
||||
import org.apache.lucene.spatial.query.SpatialArgs;
|
||||
import org.apache.lucene.spatial.query.SpatialOperation;
|
||||
import org.apache.lucene.spatial.query.UnsupportedSpatialOperation;
|
||||
import org.apache.lucene.spatial.util.DistanceToShapeValueSource;
|
||||
import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.locationtech.spatial4j.context.SpatialContext;
|
||||
import org.locationtech.spatial4j.shape.Point;
|
||||
import org.locationtech.spatial4j.shape.Rectangle;
|
||||
import org.locationtech.spatial4j.shape.Shape;
|
||||
|
||||
|
||||
/**
|
||||
* A SpatialStrategy for indexing and searching Rectangles by storing its
|
||||
* coordinates in numeric fields. It supports all {@link SpatialOperation}s and
|
||||
* has a custom overlap relevancy. It is based on GeoPortal's <a
|
||||
* href="http://geoportal.svn.sourceforge.net/svnroot/geoportal/Geoportal/trunk/src/com/esri/gpt/catalog/lucene/SpatialClauseAdapter.java">SpatialClauseAdapter</a>.
|
||||
* <p>
|
||||
* <b>Characteristics:</b>
|
||||
* <br>
|
||||
* <ul>
|
||||
* <li>Only indexes Rectangles; just one per field value. Other shapes can be provided
|
||||
* and the bounding box will be used.</li>
|
||||
* <li>Can query only by a Rectangle. Providing other shapes is an error.</li>
|
||||
* <li>Supports most {@link SpatialOperation}s but not Overlaps.</li>
|
||||
* <li>Uses the DocValues API for any sorting / relevancy.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* <b>Implementation:</b>
|
||||
* <p>
|
||||
* This uses 4 double fields for minX, maxX, minY, maxY
|
||||
* and a boolean to mark a dateline cross. Depending on the particular {@link
|
||||
* SpatialOperation}s, there are a variety of range queries on {@link DoublePoint}s to be
|
||||
* done.
|
||||
* The {@link #makeOverlapRatioValueSource(org.locationtech.spatial4j.shape.Rectangle, double)}
|
||||
* works by calculating the query bbox overlap percentage against the indexed
|
||||
* shape overlap percentage. The indexed shape's coordinates are retrieved from
|
||||
* {@link org.apache.lucene.index.LeafReader#getNumericDocValues}.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class BBoxStrategy extends SpatialStrategy {
|
||||
|
||||
// note: we use a FieldType to articulate the options we want on the field. We don't use it as-is with a Field, we
|
||||
// create more than one Field.
|
||||
|
||||
/**
|
||||
* pointValues, docValues, and nothing else.
|
||||
*/
|
||||
public static FieldType DEFAULT_FIELDTYPE;
|
||||
|
||||
@Deprecated
|
||||
public static LegacyFieldType LEGACY_FIELDTYPE;
|
||||
static {
|
||||
// Default: pointValues + docValues
|
||||
FieldType type = new FieldType();
|
||||
type.setDimensions(1, Double.BYTES);//pointValues (assume Double)
|
||||
type.setDocValuesType(DocValuesType.NUMERIC);//docValues
|
||||
type.setStored(false);
|
||||
type.freeze();
|
||||
DEFAULT_FIELDTYPE = type;
|
||||
// Legacy default: legacyNumerics + docValues
|
||||
LegacyFieldType legacyType = new LegacyFieldType();
|
||||
legacyType.setIndexOptions(IndexOptions.DOCS);
|
||||
legacyType.setNumericType(LegacyNumericType.DOUBLE);
|
||||
legacyType.setNumericPrecisionStep(8);// same as solr default
|
||||
legacyType.setDocValuesType(DocValuesType.NUMERIC);//docValues
|
||||
legacyType.setStored(false);
|
||||
legacyType.freeze();
|
||||
LEGACY_FIELDTYPE = legacyType;
|
||||
}
|
||||
|
||||
public static final String SUFFIX_MINX = "__minX";
|
||||
public static final String SUFFIX_MAXX = "__maxX";
|
||||
public static final String SUFFIX_MINY = "__minY";
|
||||
public static final String SUFFIX_MAXY = "__maxY";
|
||||
public static final String SUFFIX_XDL = "__xdl";
|
||||
|
||||
/*
|
||||
* The Bounding Box gets stored as four fields for x/y min/max and a flag
|
||||
* that says if the box crosses the dateline (xdl).
|
||||
*/
|
||||
final String field_bbox;
|
||||
final String field_minX;
|
||||
final String field_minY;
|
||||
final String field_maxX;
|
||||
final String field_maxY;
|
||||
final String field_xdl; // crosses dateline
|
||||
|
||||
private final FieldType optionsFieldType;//from constructor; aggregate field type used to express all options
|
||||
private final int fieldsLen;
|
||||
private final boolean hasStored;
|
||||
private final boolean hasDocVals;
|
||||
private final boolean hasPointVals;
|
||||
// equiv to "hasLegacyNumerics":
|
||||
private final LegacyFieldType legacyNumericFieldType; // not stored; holds precision step.
|
||||
private final FieldType xdlFieldType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BBoxStrategy} instance that uses {@link DoublePoint} and {@link DoublePoint#newRangeQuery}
|
||||
*/
|
||||
public static BBoxStrategy newInstance(SpatialContext ctx, String fieldNamePrefix) {
|
||||
return new BBoxStrategy(ctx, fieldNamePrefix, DEFAULT_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BBoxStrategy} instance that uses {@link LegacyDoubleField} for backwards compatibility
|
||||
* @deprecated LegacyNumerics will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public static BBoxStrategy newLegacyInstance(SpatialContext ctx, String fieldNamePrefix) {
|
||||
return new BBoxStrategy(ctx, fieldNamePrefix, LEGACY_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this strategy.
|
||||
* {@code fieldType} is used to customize the indexing options of the 4 number fields, and to a lesser degree the XDL
|
||||
* field too. Search requires pointValues (or legacy numerics), and relevancy requires docValues. If these features
|
||||
* aren't needed then disable them.
|
||||
*/
|
||||
public BBoxStrategy(SpatialContext ctx, String fieldNamePrefix, FieldType fieldType) {
|
||||
super(ctx, fieldNamePrefix);
|
||||
field_bbox = fieldNamePrefix;
|
||||
field_minX = fieldNamePrefix + SUFFIX_MINX;
|
||||
field_maxX = fieldNamePrefix + SUFFIX_MAXX;
|
||||
field_minY = fieldNamePrefix + SUFFIX_MINY;
|
||||
field_maxY = fieldNamePrefix + SUFFIX_MAXY;
|
||||
field_xdl = fieldNamePrefix + SUFFIX_XDL;
|
||||
|
||||
fieldType.freeze();
|
||||
this.optionsFieldType = fieldType;
|
||||
|
||||
int numQuads = 0;
|
||||
if ((this.hasStored = fieldType.stored())) {
|
||||
numQuads++;
|
||||
}
|
||||
if ((this.hasDocVals = fieldType.docValuesType() != DocValuesType.NONE)) {
|
||||
numQuads++;
|
||||
}
|
||||
if ((this.hasPointVals = fieldType.pointDimensionCount() > 0)) {
|
||||
numQuads++;
|
||||
}
|
||||
if (fieldType.indexOptions() != IndexOptions.NONE && fieldType instanceof LegacyFieldType && ((LegacyFieldType)fieldType).numericType() != null) {
|
||||
if (hasPointVals) {
|
||||
throw new IllegalArgumentException("pointValues and LegacyNumericType are mutually exclusive");
|
||||
}
|
||||
final LegacyFieldType legacyType = (LegacyFieldType) fieldType;
|
||||
if (legacyType.numericType() != LegacyNumericType.DOUBLE) {
|
||||
throw new IllegalArgumentException(getClass() + " does not support " + legacyType.numericType());
|
||||
}
|
||||
numQuads++;
|
||||
legacyNumericFieldType = new LegacyFieldType(LegacyDoubleField.TYPE_NOT_STORED);
|
||||
legacyNumericFieldType.setNumericPrecisionStep(legacyType.numericPrecisionStep());
|
||||
legacyNumericFieldType.freeze();
|
||||
} else {
|
||||
legacyNumericFieldType = null;
|
||||
}
|
||||
|
||||
if (hasPointVals || legacyNumericFieldType != null) { // if we have an index...
|
||||
xdlFieldType = new FieldType(StringField.TYPE_NOT_STORED);
|
||||
xdlFieldType.setIndexOptions(IndexOptions.DOCS);
|
||||
xdlFieldType.freeze();
|
||||
} else {
|
||||
xdlFieldType = null;
|
||||
}
|
||||
|
||||
this.fieldsLen = numQuads * 4 + (xdlFieldType != null ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Returns a field type representing the set of field options. This is identical to what was passed into the
|
||||
* constructor. It's frozen. */
|
||||
public FieldType getFieldType() {
|
||||
return optionsFieldType;
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
// Indexing
|
||||
//---------------------------------
|
||||
|
||||
@Override
|
||||
public Field[] createIndexableFields(Shape shape) {
|
||||
return createIndexableFields(shape.getBoundingBox());
|
||||
}
|
||||
|
||||
private Field[] createIndexableFields(Rectangle bbox) {
|
||||
Field[] fields = new Field[fieldsLen];
|
||||
int idx = -1;
|
||||
if (hasStored) {
|
||||
fields[++idx] = new StoredField(field_minX, bbox.getMinX());
|
||||
fields[++idx] = new StoredField(field_minY, bbox.getMinY());
|
||||
fields[++idx] = new StoredField(field_maxX, bbox.getMaxX());
|
||||
fields[++idx] = new StoredField(field_maxY, bbox.getMaxY());
|
||||
}
|
||||
if (hasDocVals) {
|
||||
fields[++idx] = new DoubleDocValuesField(field_minX, bbox.getMinX());
|
||||
fields[++idx] = new DoubleDocValuesField(field_minY, bbox.getMinY());
|
||||
fields[++idx] = new DoubleDocValuesField(field_maxX, bbox.getMaxX());
|
||||
fields[++idx] = new DoubleDocValuesField(field_maxY, bbox.getMaxY());
|
||||
}
|
||||
if (hasPointVals) {
|
||||
fields[++idx] = new DoublePoint(field_minX, bbox.getMinX());
|
||||
fields[++idx] = new DoublePoint(field_minY, bbox.getMinY());
|
||||
fields[++idx] = new DoublePoint(field_maxX, bbox.getMaxX());
|
||||
fields[++idx] = new DoublePoint(field_maxY, bbox.getMaxY());
|
||||
}
|
||||
if (legacyNumericFieldType != null) {
|
||||
fields[++idx] = new LegacyDoubleField(field_minX, bbox.getMinX(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(field_minY, bbox.getMinY(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(field_maxX, bbox.getMaxX(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(field_maxY, bbox.getMaxY(), legacyNumericFieldType);
|
||||
}
|
||||
if (xdlFieldType != null) {
|
||||
fields[++idx] = new Field(field_xdl, bbox.getCrossesDateLine()?"T":"F", xdlFieldType);
|
||||
}
|
||||
assert idx == fields.length - 1;
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------
|
||||
// Value Source / Relevancy
|
||||
//---------------------------------
|
||||
|
||||
/**
|
||||
* Provides access to each rectangle per document as a ValueSource in which
|
||||
* {@link org.apache.lucene.queries.function.FunctionValues#objectVal(int)} returns a {@link
|
||||
* Shape}.
|
||||
*/ //TODO raise to SpatialStrategy
|
||||
public ValueSource makeShapeValueSource() {
|
||||
return new BBoxValueSource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSource makeDistanceValueSource(Point queryPoint, double multiplier) {
|
||||
//TODO if makeShapeValueSource gets lifted to the top; this could become a generic impl.
|
||||
return new DistanceToShapeValueSource(makeShapeValueSource(), queryPoint, multiplier, ctx);
|
||||
}
|
||||
|
||||
/** Returns a similarity based on {@link BBoxOverlapRatioValueSource}. This is just a
|
||||
* convenience method. */
|
||||
public ValueSource makeOverlapRatioValueSource(Rectangle queryBox, double queryTargetProportion) {
|
||||
return new BBoxOverlapRatioValueSource(
|
||||
makeShapeValueSource(), ctx.isGeo(), queryBox, queryTargetProportion, 0.0);
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
// Query Building
|
||||
//---------------------------------
|
||||
|
||||
// Utility on SpatialStrategy?
|
||||
// public Query makeQueryWithValueSource(SpatialArgs args, ValueSource valueSource) {
|
||||
// return new CustomScoreQuery(makeQuery(args), new FunctionQuery(valueSource));
|
||||
//or...
|
||||
// return new BooleanQuery.Builder()
|
||||
// .add(new FunctionQuery(valueSource), BooleanClause.Occur.MUST)//matches everything and provides score
|
||||
// .add(filterQuery, BooleanClause.Occur.FILTER)//filters (score isn't used)
|
||||
// .build();
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Query makeQuery(SpatialArgs args) {
|
||||
Shape shape = args.getShape();
|
||||
if (!(shape instanceof Rectangle))
|
||||
throw new UnsupportedOperationException("Can only query by Rectangle, not " + shape);
|
||||
|
||||
Rectangle bbox = (Rectangle) shape;
|
||||
Query spatial;
|
||||
|
||||
// Useful for understanding Relations:
|
||||
// http://edndoc.esri.com/arcsde/9.1/general_topics/understand_spatial_relations.htm
|
||||
SpatialOperation op = args.getOperation();
|
||||
if( op == SpatialOperation.BBoxIntersects ) spatial = makeIntersects(bbox);
|
||||
else if( op == SpatialOperation.BBoxWithin ) spatial = makeWithin(bbox);
|
||||
else if( op == SpatialOperation.Contains ) spatial = makeContains(bbox);
|
||||
else if( op == SpatialOperation.Intersects ) spatial = makeIntersects(bbox);
|
||||
else if( op == SpatialOperation.IsEqualTo ) spatial = makeEquals(bbox);
|
||||
else if( op == SpatialOperation.IsDisjointTo ) spatial = makeDisjoint(bbox);
|
||||
else if( op == SpatialOperation.IsWithin ) spatial = makeWithin(bbox);
|
||||
else { //no Overlaps support yet
|
||||
throw new UnsupportedSpatialOperation(op);
|
||||
}
|
||||
return new ConstantScoreQuery(spatial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that fully contain the input envelope.
|
||||
*
|
||||
* @return the spatial query
|
||||
*/
|
||||
Query makeContains(Rectangle bbox) {
|
||||
|
||||
// general case
|
||||
// docMinX <= queryExtent.getMinX() AND docMinY <= queryExtent.getMinY() AND docMaxX >= queryExtent.getMaxX() AND docMaxY >= queryExtent.getMaxY()
|
||||
|
||||
// Y conditions
|
||||
// docMinY <= queryExtent.getMinY() AND docMaxY >= queryExtent.getMaxY()
|
||||
Query qMinY = this.makeNumericRangeQuery(field_minY, null, bbox.getMinY(), false, true);
|
||||
Query qMaxY = this.makeNumericRangeQuery(field_maxY, bbox.getMaxY(), null, true, false);
|
||||
Query yConditions = this.makeQuery(BooleanClause.Occur.MUST, qMinY, qMaxY);
|
||||
|
||||
// X conditions
|
||||
Query xConditions;
|
||||
|
||||
// queries that do not cross the date line
|
||||
if (!bbox.getCrossesDateLine()) {
|
||||
|
||||
// X Conditions for documents that do not cross the date line,
|
||||
// documents that contain the min X and max X of the query envelope,
|
||||
// docMinX <= queryExtent.getMinX() AND docMaxX >= queryExtent.getMaxX()
|
||||
Query qMinX = this.makeNumericRangeQuery(field_minX, null, bbox.getMinX(), false, true);
|
||||
Query qMaxX = this.makeNumericRangeQuery(field_maxX, bbox.getMaxX(), null, true, false);
|
||||
Query qMinMax = this.makeQuery(BooleanClause.Occur.MUST, qMinX, qMaxX);
|
||||
Query qNonXDL = this.makeXDL(false, qMinMax);
|
||||
|
||||
if (!ctx.isGeo()) {
|
||||
xConditions = qNonXDL;
|
||||
} else {
|
||||
// X Conditions for documents that cross the date line,
|
||||
// the left portion of the document contains the min X of the query
|
||||
// OR the right portion of the document contains the max X of the query,
|
||||
// docMinXLeft <= queryExtent.getMinX() OR docMaxXRight >= queryExtent.getMaxX()
|
||||
Query qXDLLeft = this.makeNumericRangeQuery(field_minX, null, bbox.getMinX(), false, true);
|
||||
Query qXDLRight = this.makeNumericRangeQuery(field_maxX, bbox.getMaxX(), null, true, false);
|
||||
Query qXDLLeftRight = this.makeQuery(BooleanClause.Occur.SHOULD, qXDLLeft, qXDLRight);
|
||||
Query qXDL = this.makeXDL(true, qXDLLeftRight);
|
||||
|
||||
Query qEdgeDL = null;
|
||||
if (bbox.getMinX() == bbox.getMaxX() && Math.abs(bbox.getMinX()) == 180) {
|
||||
double edge = bbox.getMinX() * -1;//opposite dateline edge
|
||||
qEdgeDL = makeQuery(BooleanClause.Occur.SHOULD,
|
||||
makeNumberTermQuery(field_minX, edge), makeNumberTermQuery(field_maxX, edge));
|
||||
}
|
||||
|
||||
// apply the non-XDL and XDL conditions
|
||||
xConditions = this.makeQuery(BooleanClause.Occur.SHOULD, qNonXDL, qXDL, qEdgeDL);
|
||||
}
|
||||
} else {
|
||||
// queries that cross the date line
|
||||
|
||||
// No need to search for documents that do not cross the date line
|
||||
|
||||
// X Conditions for documents that cross the date line,
|
||||
// the left portion of the document contains the min X of the query
|
||||
// AND the right portion of the document contains the max X of the query,
|
||||
// docMinXLeft <= queryExtent.getMinX() AND docMaxXRight >= queryExtent.getMaxX()
|
||||
Query qXDLLeft = this.makeNumericRangeQuery(field_minX, null, bbox.getMinX(), false, true);
|
||||
Query qXDLRight = this.makeNumericRangeQuery(field_maxX, bbox.getMaxX(), null, true, false);
|
||||
Query qXDLLeftRight = this.makeXDL(true, this.makeQuery(BooleanClause.Occur.MUST, qXDLLeft, qXDLRight));
|
||||
|
||||
Query qWorld = makeQuery(BooleanClause.Occur.MUST,
|
||||
makeNumberTermQuery(field_minX, -180), makeNumberTermQuery(field_maxX, 180));
|
||||
|
||||
xConditions = makeQuery(BooleanClause.Occur.SHOULD, qXDLLeftRight, qWorld);
|
||||
}
|
||||
|
||||
// both X and Y conditions must occur
|
||||
return this.makeQuery(BooleanClause.Occur.MUST, xConditions, yConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that are disjoint to the input envelope.
|
||||
*
|
||||
* @return the spatial query
|
||||
*/
|
||||
Query makeDisjoint(Rectangle bbox) {
|
||||
|
||||
// general case
|
||||
// docMinX > queryExtent.getMaxX() OR docMaxX < queryExtent.getMinX() OR docMinY > queryExtent.getMaxY() OR docMaxY < queryExtent.getMinY()
|
||||
|
||||
// Y conditions
|
||||
// docMinY > queryExtent.getMaxY() OR docMaxY < queryExtent.getMinY()
|
||||
Query qMinY = this.makeNumericRangeQuery(field_minY, bbox.getMaxY(), null, false, false);
|
||||
Query qMaxY = this.makeNumericRangeQuery(field_maxY, null, bbox.getMinY(), false, false);
|
||||
Query yConditions = this.makeQuery(BooleanClause.Occur.SHOULD, qMinY, qMaxY);
|
||||
|
||||
// X conditions
|
||||
Query xConditions;
|
||||
|
||||
// queries that do not cross the date line
|
||||
if (!bbox.getCrossesDateLine()) {
|
||||
|
||||
// X Conditions for documents that do not cross the date line,
|
||||
// docMinX > queryExtent.getMaxX() OR docMaxX < queryExtent.getMinX()
|
||||
Query qMinX = this.makeNumericRangeQuery(field_minX, bbox.getMaxX(), null, false, false);
|
||||
if (bbox.getMinX() == -180.0 && ctx.isGeo()) {//touches dateline; -180 == 180
|
||||
BooleanQuery.Builder bq = new BooleanQuery.Builder();
|
||||
bq.add(qMinX, BooleanClause.Occur.MUST);
|
||||
bq.add(makeNumberTermQuery(field_maxX, 180.0), BooleanClause.Occur.MUST_NOT);
|
||||
qMinX = bq.build();
|
||||
}
|
||||
Query qMaxX = this.makeNumericRangeQuery(field_maxX, null, bbox.getMinX(), false, false);
|
||||
|
||||
if (bbox.getMaxX() == 180.0 && ctx.isGeo()) {//touches dateline; -180 == 180
|
||||
BooleanQuery.Builder bq = new BooleanQuery.Builder();
|
||||
bq.add(qMaxX, BooleanClause.Occur.MUST);
|
||||
bq.add(makeNumberTermQuery(field_minX, -180.0), BooleanClause.Occur.MUST_NOT);
|
||||
qMaxX = bq.build();
|
||||
}
|
||||
Query qMinMax = this.makeQuery(BooleanClause.Occur.SHOULD, qMinX, qMaxX);
|
||||
Query qNonXDL = this.makeXDL(false, qMinMax);
|
||||
|
||||
if (!ctx.isGeo()) {
|
||||
xConditions = qNonXDL;
|
||||
} else {
|
||||
// X Conditions for documents that cross the date line,
|
||||
|
||||
// both the left and right portions of the document must be disjoint to the query
|
||||
// (docMinXLeft > queryExtent.getMaxX() OR docMaxXLeft < queryExtent.getMinX()) AND
|
||||
// (docMinXRight > queryExtent.getMaxX() OR docMaxXRight < queryExtent.getMinX())
|
||||
// where: docMaxXLeft = 180.0, docMinXRight = -180.0
|
||||
// (docMaxXLeft < queryExtent.getMinX()) equates to (180.0 < queryExtent.getMinX()) and is ignored
|
||||
// (docMinXRight > queryExtent.getMaxX()) equates to (-180.0 > queryExtent.getMaxX()) and is ignored
|
||||
Query qMinXLeft = this.makeNumericRangeQuery(field_minX, bbox.getMaxX(), null, false, false);
|
||||
Query qMaxXRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMinX(), false, false);
|
||||
Query qLeftRight = this.makeQuery(BooleanClause.Occur.MUST, qMinXLeft, qMaxXRight);
|
||||
Query qXDL = this.makeXDL(true, qLeftRight);
|
||||
|
||||
// apply the non-XDL and XDL conditions
|
||||
xConditions = this.makeQuery(BooleanClause.Occur.SHOULD, qNonXDL, qXDL);
|
||||
}
|
||||
// queries that cross the date line
|
||||
} else {
|
||||
|
||||
// X Conditions for documents that do not cross the date line,
|
||||
// the document must be disjoint to both the left and right query portions
|
||||
// (docMinX > queryExtent.getMaxX()Left OR docMaxX < queryExtent.getMinX()) AND (docMinX > queryExtent.getMaxX() OR docMaxX < queryExtent.getMinX()Left)
|
||||
// where: queryExtent.getMaxX()Left = 180.0, queryExtent.getMinX()Left = -180.0
|
||||
Query qMinXLeft = this.makeNumericRangeQuery(field_minX, 180.0, null, false, false);
|
||||
Query qMaxXLeft = this.makeNumericRangeQuery(field_maxX, null, bbox.getMinX(), false, false);
|
||||
Query qMinXRight = this.makeNumericRangeQuery(field_minX, bbox.getMaxX(), null, false, false);
|
||||
Query qMaxXRight = this.makeNumericRangeQuery(field_maxX, null, -180.0, false, false);
|
||||
Query qLeft = this.makeQuery(BooleanClause.Occur.SHOULD, qMinXLeft, qMaxXLeft);
|
||||
Query qRight = this.makeQuery(BooleanClause.Occur.SHOULD, qMinXRight, qMaxXRight);
|
||||
Query qLeftRight = this.makeQuery(BooleanClause.Occur.MUST, qLeft, qRight);
|
||||
|
||||
// No need to search for documents that do not cross the date line
|
||||
|
||||
xConditions = this.makeXDL(false, qLeftRight);
|
||||
}
|
||||
|
||||
// either X or Y conditions should occur
|
||||
return this.makeQuery(BooleanClause.Occur.SHOULD, xConditions, yConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that equal the input envelope.
|
||||
*
|
||||
* @return the spatial query
|
||||
*/
|
||||
Query makeEquals(Rectangle bbox) {
|
||||
|
||||
// docMinX = queryExtent.getMinX() AND docMinY = queryExtent.getMinY() AND docMaxX = queryExtent.getMaxX() AND docMaxY = queryExtent.getMaxY()
|
||||
Query qMinX = makeNumberTermQuery(field_minX, bbox.getMinX());
|
||||
Query qMinY = makeNumberTermQuery(field_minY, bbox.getMinY());
|
||||
Query qMaxX = makeNumberTermQuery(field_maxX, bbox.getMaxX());
|
||||
Query qMaxY = makeNumberTermQuery(field_maxY, bbox.getMaxY());
|
||||
return makeQuery(BooleanClause.Occur.MUST, qMinX, qMinY, qMaxX, qMaxY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that intersect the input envelope.
|
||||
*
|
||||
* @return the spatial query
|
||||
*/
|
||||
Query makeIntersects(Rectangle bbox) {
|
||||
|
||||
// the original intersects query does not work for envelopes that cross the date line,
|
||||
// switch to a NOT Disjoint query
|
||||
|
||||
// MUST_NOT causes a problem when it's the only clause type within a BooleanQuery,
|
||||
// to get around it we add all documents as a SHOULD
|
||||
|
||||
// there must be an envelope, it must not be disjoint
|
||||
Query qHasEnv;
|
||||
if (ctx.isGeo()) {
|
||||
Query qIsNonXDL = this.makeXDL(false);
|
||||
Query qIsXDL = ctx.isGeo() ? this.makeXDL(true) : null;
|
||||
qHasEnv = this.makeQuery(BooleanClause.Occur.SHOULD, qIsNonXDL, qIsXDL);
|
||||
} else {
|
||||
qHasEnv = this.makeXDL(false);
|
||||
}
|
||||
|
||||
BooleanQuery.Builder qNotDisjoint = new BooleanQuery.Builder();
|
||||
qNotDisjoint.add(qHasEnv, BooleanClause.Occur.MUST);
|
||||
Query qDisjoint = makeDisjoint(bbox);
|
||||
qNotDisjoint.add(qDisjoint, BooleanClause.Occur.MUST_NOT);
|
||||
|
||||
//Query qDisjoint = makeDisjoint();
|
||||
//BooleanQuery qNotDisjoint = new BooleanQuery();
|
||||
//qNotDisjoint.add(new MatchAllDocsQuery(),BooleanClause.Occur.SHOULD);
|
||||
//qNotDisjoint.add(qDisjoint,BooleanClause.Occur.MUST_NOT);
|
||||
return qNotDisjoint.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a boolean query based upon a collection of queries and a logical operator.
|
||||
*
|
||||
* @param occur the logical operator
|
||||
* @param queries the query collection
|
||||
* @return the query
|
||||
*/
|
||||
BooleanQuery makeQuery(BooleanClause.Occur occur, Query... queries) {
|
||||
BooleanQuery.Builder bq = new BooleanQuery.Builder();
|
||||
for (Query query : queries) {
|
||||
if (query != null)
|
||||
bq.add(query, occur);
|
||||
}
|
||||
return bq.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents are fully within the input envelope.
|
||||
*
|
||||
* @return the spatial query
|
||||
*/
|
||||
Query makeWithin(Rectangle bbox) {
|
||||
|
||||
// general case
|
||||
// docMinX >= queryExtent.getMinX() AND docMinY >= queryExtent.getMinY() AND docMaxX <= queryExtent.getMaxX() AND docMaxY <= queryExtent.getMaxY()
|
||||
|
||||
// Y conditions
|
||||
// docMinY >= queryExtent.getMinY() AND docMaxY <= queryExtent.getMaxY()
|
||||
Query qMinY = this.makeNumericRangeQuery(field_minY, bbox.getMinY(), null, true, false);
|
||||
Query qMaxY = this.makeNumericRangeQuery(field_maxY, null, bbox.getMaxY(), false, true);
|
||||
Query yConditions = this.makeQuery(BooleanClause.Occur.MUST, qMinY, qMaxY);
|
||||
|
||||
// X conditions
|
||||
Query xConditions;
|
||||
|
||||
if (ctx.isGeo() && bbox.getMinX() == -180.0 && bbox.getMaxX() == 180.0) {
|
||||
//if query world-wraps, only the y condition matters
|
||||
return yConditions;
|
||||
|
||||
} else if (!bbox.getCrossesDateLine()) {
|
||||
// queries that do not cross the date line
|
||||
|
||||
// docMinX >= queryExtent.getMinX() AND docMaxX <= queryExtent.getMaxX()
|
||||
Query qMinX = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
|
||||
Query qMaxX = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
|
||||
Query qMinMax = this.makeQuery(BooleanClause.Occur.MUST, qMinX, qMaxX);
|
||||
|
||||
double edge = 0;//none, otherwise opposite dateline of query
|
||||
if (bbox.getMinX() == -180.0)
|
||||
edge = 180;
|
||||
else if (bbox.getMaxX() == 180.0)
|
||||
edge = -180;
|
||||
if (edge != 0 && ctx.isGeo()) {
|
||||
Query edgeQ = makeQuery(BooleanClause.Occur.MUST,
|
||||
makeNumberTermQuery(field_minX, edge), makeNumberTermQuery(field_maxX, edge));
|
||||
qMinMax = makeQuery(BooleanClause.Occur.SHOULD, qMinMax, edgeQ);
|
||||
}
|
||||
|
||||
xConditions = this.makeXDL(false, qMinMax);
|
||||
|
||||
// queries that cross the date line
|
||||
} else {
|
||||
|
||||
// X Conditions for documents that do not cross the date line
|
||||
|
||||
// the document should be within the left portion of the query
|
||||
// docMinX >= queryExtent.getMinX() AND docMaxX <= 180.0
|
||||
Query qMinXLeft = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
|
||||
Query qMaxXLeft = this.makeNumericRangeQuery(field_maxX, null, 180.0, false, true);
|
||||
Query qLeft = this.makeQuery(BooleanClause.Occur.MUST, qMinXLeft, qMaxXLeft);
|
||||
|
||||
// the document should be within the right portion of the query
|
||||
// docMinX >= -180.0 AND docMaxX <= queryExtent.getMaxX()
|
||||
Query qMinXRight = this.makeNumericRangeQuery(field_minX, -180.0, null, true, false);
|
||||
Query qMaxXRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
|
||||
Query qRight = this.makeQuery(BooleanClause.Occur.MUST, qMinXRight, qMaxXRight);
|
||||
|
||||
// either left or right conditions should occur,
|
||||
// apply the left and right conditions to documents that do not cross the date line
|
||||
Query qLeftRight = this.makeQuery(BooleanClause.Occur.SHOULD, qLeft, qRight);
|
||||
Query qNonXDL = this.makeXDL(false, qLeftRight);
|
||||
|
||||
// X Conditions for documents that cross the date line,
|
||||
// the left portion of the document must be within the left portion of the query,
|
||||
// AND the right portion of the document must be within the right portion of the query
|
||||
// docMinXLeft >= queryExtent.getMinX() AND docMaxXLeft <= 180.0
|
||||
// AND docMinXRight >= -180.0 AND docMaxXRight <= queryExtent.getMaxX()
|
||||
Query qXDLLeft = this.makeNumericRangeQuery(field_minX, bbox.getMinX(), null, true, false);
|
||||
Query qXDLRight = this.makeNumericRangeQuery(field_maxX, null, bbox.getMaxX(), false, true);
|
||||
Query qXDLLeftRight = this.makeQuery(BooleanClause.Occur.MUST, qXDLLeft, qXDLRight);
|
||||
Query qXDL = this.makeXDL(true, qXDLLeftRight);
|
||||
|
||||
// apply the non-XDL and XDL conditions
|
||||
xConditions = this.makeQuery(BooleanClause.Occur.SHOULD, qNonXDL, qXDL);
|
||||
}
|
||||
|
||||
// both X and Y conditions must occur
|
||||
return this.makeQuery(BooleanClause.Occur.MUST, xConditions, yConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that do or do not cross the date line.
|
||||
*
|
||||
* @param crossedDateLine <code>true</true> for documents that cross the date line
|
||||
* @return the query
|
||||
*/
|
||||
private Query makeXDL(boolean crossedDateLine) {
|
||||
// The 'T' and 'F' values match solr fields
|
||||
return new TermQuery(new Term(field_xdl, crossedDateLine ? "T" : "F"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that do or do not cross the date line
|
||||
* and match the supplied spatial query.
|
||||
*
|
||||
* @param crossedDateLine <code>true</true> for documents that cross the date line
|
||||
* @param query the spatial query
|
||||
* @return the query
|
||||
*/
|
||||
private Query makeXDL(boolean crossedDateLine, Query query) {
|
||||
if (!ctx.isGeo()) {
|
||||
assert !crossedDateLine;
|
||||
return query;
|
||||
}
|
||||
BooleanQuery.Builder bq = new BooleanQuery.Builder();
|
||||
bq.add(this.makeXDL(crossedDateLine), BooleanClause.Occur.MUST);
|
||||
bq.add(query, BooleanClause.Occur.MUST);
|
||||
return bq.build();
|
||||
}
|
||||
|
||||
private Query makeNumberTermQuery(String field, double number) {
|
||||
if (hasPointVals) {
|
||||
return DoublePoint.newExactQuery(field, number);
|
||||
} else if (legacyNumericFieldType != null) {
|
||||
BytesRefBuilder bytes = new BytesRefBuilder();
|
||||
LegacyNumericUtils.longToPrefixCoded(NumericUtils.doubleToSortableLong(number), 0, bytes);
|
||||
return new TermQuery(new Term(field, bytes.get()));
|
||||
}
|
||||
throw new UnsupportedOperationException("An index is required for this operation.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric range query based on FieldType
|
||||
* {@link LegacyNumericRangeQuery} is used for indexes created using {@code FieldType.LegacyNumericType}
|
||||
* {@link DoublePoint#newRangeQuery} is used for indexes created using {@link DoublePoint} fields
|
||||
*
|
||||
* @param fieldname field name. must not be <code>null</code>.
|
||||
* @param min minimum value of the range.
|
||||
* @param max maximum value of the range.
|
||||
* @param minInclusive include the minimum value if <code>true</code>.
|
||||
* @param maxInclusive include the maximum value if <code>true</code>
|
||||
*/
|
||||
private Query makeNumericRangeQuery(String fieldname, Double min, Double max, boolean minInclusive, boolean maxInclusive) {
|
||||
if (hasPointVals) {
|
||||
if (min == null) {
|
||||
min = Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
if (max == null) {
|
||||
max = Double.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
if (minInclusive == false) {
|
||||
min = Math.nextUp(min);
|
||||
}
|
||||
|
||||
if (maxInclusive == false) {
|
||||
max = Math.nextDown(max);
|
||||
}
|
||||
|
||||
return DoublePoint.newRangeQuery(fieldname, min, max);
|
||||
} else if (legacyNumericFieldType != null) {// todo remove legacy numeric support in 7.0
|
||||
return LegacyNumericRangeQuery.newDoubleRange(fieldname, legacyNumericFieldType.numericPrecisionStep(), min, max, minInclusive, maxInclusive);
|
||||
}
|
||||
throw new UnsupportedOperationException("An index is required for this operation.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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.legacy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.NumericDocValues;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.Explanation;
|
||||
import org.locationtech.spatial4j.shape.Rectangle;
|
||||
|
||||
/**
|
||||
* A ValueSource in which the indexed Rectangle is returned from
|
||||
* {@link org.apache.lucene.queries.function.FunctionValues#objectVal(int)}.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
class BBoxValueSource extends ValueSource {
|
||||
|
||||
private final BBoxStrategy strategy;
|
||||
|
||||
public BBoxValueSource(BBoxStrategy strategy) {
|
||||
this.strategy = strategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "bboxShape(" + strategy.getFieldName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
|
||||
LeafReader reader = readerContext.reader();
|
||||
final NumericDocValues minX = DocValues.getNumeric(reader, strategy.field_minX);
|
||||
final NumericDocValues minY = DocValues.getNumeric(reader, strategy.field_minY);
|
||||
final NumericDocValues maxX = DocValues.getNumeric(reader, strategy.field_maxX);
|
||||
final NumericDocValues maxY = DocValues.getNumeric(reader, strategy.field_maxY);
|
||||
|
||||
//reused
|
||||
final Rectangle rect = strategy.getSpatialContext().makeRectangle(0,0,0,0);
|
||||
|
||||
return new FunctionValues() {
|
||||
private int lastDocID = -1;
|
||||
|
||||
private double getDocValue(NumericDocValues values, int doc) throws IOException {
|
||||
int curDocID = values.docID();
|
||||
if (doc > curDocID) {
|
||||
curDocID = values.advance(doc);
|
||||
}
|
||||
if (doc == curDocID) {
|
||||
return Double.longBitsToDouble(values.longValue());
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object objectVal(int doc) throws IOException {
|
||||
if (doc < lastDocID) {
|
||||
throw new AssertionError("docs were sent out-of-order: lastDocID=" + lastDocID + " vs doc=" + doc);
|
||||
}
|
||||
lastDocID = doc;
|
||||
|
||||
double minXValue = getDocValue(minX, doc);
|
||||
if (minX.docID() != doc) {
|
||||
return null;
|
||||
} else {
|
||||
double minYValue = getDocValue(minY, doc);
|
||||
double maxXValue = getDocValue(maxX, doc);
|
||||
double maxYValue = getDocValue(maxY, doc);
|
||||
rect.reset(minXValue, maxXValue, minYValue, maxYValue);
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String strVal(int doc) throws IOException {//TODO support WKT output once Spatial4j does
|
||||
Object v = objectVal(doc);
|
||||
return v == null ? null : v.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(int doc) throws IOException {
|
||||
getDocValue(minX, doc);
|
||||
return minX.docID() == doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
return Explanation.match(Float.NaN, toString(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int doc) throws IOException {
|
||||
return description() + '=' + strVal(doc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
BBoxValueSource that = (BBoxValueSource) o;
|
||||
|
||||
if (!strategy.equals(that.strategy)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return strategy.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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.legacy;
|
||||
|
||||
import org.apache.lucene.index.NumericDocValues;
|
||||
import org.locationtech.spatial4j.distance.DistanceCalculator;
|
||||
import org.locationtech.spatial4j.shape.Point;
|
||||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An implementation of the Lucene ValueSource model that returns the distance
|
||||
* for a {@link PointVectorStrategy}.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class DistanceValueSource extends ValueSource {
|
||||
|
||||
private PointVectorStrategy strategy;
|
||||
private final Point from;
|
||||
private final double multiplier;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public DistanceValueSource(PointVectorStrategy strategy, Point from, double multiplier) {
|
||||
this.strategy = strategy;
|
||||
this.from = from;
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ValueSource description.
|
||||
*/
|
||||
@Override
|
||||
public String description() {
|
||||
return "DistanceValueSource("+strategy+", "+from+")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FunctionValues used by the function query.
|
||||
*/
|
||||
@Override
|
||||
public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
|
||||
LeafReader reader = readerContext.reader();
|
||||
|
||||
final NumericDocValues ptX = DocValues.getNumeric(reader, strategy.getFieldNameX());
|
||||
final NumericDocValues ptY = DocValues.getNumeric(reader, strategy.getFieldNameY());
|
||||
|
||||
return new FunctionValues() {
|
||||
|
||||
private int lastDocID = -1;
|
||||
|
||||
private final Point from = DistanceValueSource.this.from;
|
||||
private final DistanceCalculator calculator = strategy.getSpatialContext().getDistCalc();
|
||||
private final double nullValue =
|
||||
(strategy.getSpatialContext().isGeo() ? 180 * multiplier : Double.MAX_VALUE);
|
||||
|
||||
private double getDocValue(NumericDocValues values, int doc) throws IOException {
|
||||
int curDocID = values.docID();
|
||||
if (doc > curDocID) {
|
||||
curDocID = values.advance(doc);
|
||||
}
|
||||
if (doc == curDocID) {
|
||||
return Double.longBitsToDouble(values.longValue());
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatVal(int doc) throws IOException {
|
||||
return (float) doubleVal(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleVal(int doc) throws IOException {
|
||||
// make sure it has minX and area
|
||||
double x = getDocValue(ptX, doc);
|
||||
if (ptX.docID() == doc) {
|
||||
double y = getDocValue(ptY, doc);
|
||||
assert ptY.docID() == doc;
|
||||
return calculator.distance(from, x, y) * multiplier;
|
||||
}
|
||||
return nullValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int doc) throws IOException {
|
||||
return description() + "=" + floatVal(doc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DistanceValueSource that = (DistanceValueSource) o;
|
||||
|
||||
if (!from.equals(that.from)) return false;
|
||||
if (!strategy.equals(that.strategy)) return false;
|
||||
if (multiplier != that.multiplier) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return from.hashCode();
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -51,7 +51,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyFloatField}.
|
||||
*
|
||||
* <p>To perform range querying or filtering against a
|
||||
* <code>LegacyDoubleField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* <code>LegacyDoubleField</code>, use {@link org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* To sort according to a
|
||||
* <code>LegacyDoubleField</code>, use the normal numeric sort types, eg
|
||||
* {@link org.apache.lucene.search.SortField.Type#DOUBLE}. <code>LegacyDoubleField</code>
|
||||
|
@ -85,7 +85,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyFieldType#setNumericPrecisionStep} method if you'd
|
||||
* like to change the value. Note that you must also
|
||||
* specify a congruent value when creating {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* For low cardinality fields larger precision steps are good.
|
||||
* If the cardinality is < 100, it is fair
|
||||
* to use {@link Integer#MAX_VALUE}, which produces one
|
||||
|
@ -94,8 +94,8 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* <p>For more information on the internals of numeric trie
|
||||
* indexing, including the <a
|
||||
* href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
|
||||
* configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
|
||||
* configuration, see {@link org.apache.solr.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.solr.legacy.LegacyNumericUtils}.
|
||||
*
|
||||
* <p>If you only need to sort by numeric value, and never
|
||||
* run range querying/filtering, you can index using a
|
||||
|
@ -103,7 +103,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* This will minimize disk space consumed. </p>
|
||||
*
|
||||
* <p>More advanced users can instead use {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* org.apache.solr.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* class is a wrapper around this token stream type for
|
||||
* easier, more intuitive usage.</p>
|
||||
*
|
||||
|
@ -144,7 +144,7 @@ public final class LegacyDoubleField extends LegacyField {
|
|||
|
||||
/** Creates a stored or un-stored LegacyDoubleField with the provided value
|
||||
* and default <code>precisionStep</code> {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* @param name field name
|
||||
* @param value 64-bit double value
|
||||
* @param stored Store.YES if the content should also be stored
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
import org.apache.lucene.document.FieldType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
|
@ -60,7 +60,7 @@ public final class LegacyFieldType extends FieldType {
|
|||
|
||||
/**
|
||||
* LegacyNumericType: if non-null then the field's value will be indexed
|
||||
* numerically so that {@link org.apache.lucene.legacy.LegacyNumericRangeQuery} can be used at
|
||||
* numerically so that {@link org.apache.solr.legacy.LegacyNumericRangeQuery} can be used at
|
||||
* search time.
|
||||
* <p>
|
||||
* The default is <code>null</code> (no numeric type)
|
||||
|
@ -97,7 +97,7 @@ public final class LegacyFieldType extends FieldType {
|
|||
* <p>
|
||||
* This has no effect if {@link #numericType()} returns null.
|
||||
* <p>
|
||||
* The default is {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT}
|
||||
* The default is {@link org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT}
|
||||
* @see #setNumericPrecisionStep(int)
|
||||
*
|
||||
* @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.FloatPoint;
|
||||
|
@ -49,7 +49,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyDoubleField}.
|
||||
*
|
||||
* <p>To perform range querying or filtering against a
|
||||
* <code>LegacyFloatField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* <code>LegacyFloatField</code>, use {@link org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* To sort according to a
|
||||
* <code>LegacyFloatField</code>, use the normal numeric sort types, eg
|
||||
* {@link org.apache.lucene.search.SortField.Type#FLOAT}. <code>LegacyFloatField</code>
|
||||
|
@ -83,7 +83,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyFieldType#setNumericPrecisionStep} method if you'd
|
||||
* like to change the value. Note that you must also
|
||||
* specify a congruent value when creating {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* For low cardinality fields larger precision steps are good.
|
||||
* If the cardinality is < 100, it is fair
|
||||
* to use {@link Integer#MAX_VALUE}, which produces one
|
||||
|
@ -92,8 +92,8 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* <p>For more information on the internals of numeric trie
|
||||
* indexing, including the <a
|
||||
* href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
|
||||
* configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
|
||||
* configuration, see {@link org.apache.solr.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.solr.legacy.LegacyNumericUtils}.
|
||||
*
|
||||
* <p>If you only need to sort by numeric value, and never
|
||||
* run range querying/filtering, you can index using a
|
||||
|
@ -101,7 +101,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* This will minimize disk space consumed. </p>
|
||||
*
|
||||
* <p>More advanced users can instead use {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* org.apache.solr.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* class is a wrapper around this token stream type for
|
||||
* easier, more intuitive usage.</p>
|
||||
*
|
||||
|
@ -144,7 +144,7 @@ public final class LegacyFloatField extends LegacyField {
|
|||
|
||||
/** Creates a stored or un-stored LegacyFloatField with the provided value
|
||||
* and default <code>precisionStep</code> {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* @param name field name
|
||||
* @param value 32-bit double value
|
||||
* @param stored Store.YES if the content should also be stored
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -50,7 +50,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyDoubleField}.
|
||||
*
|
||||
* <p>To perform range querying or filtering against a
|
||||
* <code>LegacyIntField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* <code>LegacyIntField</code>, use {@link org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* To sort according to a
|
||||
* <code>LegacyIntField</code>, use the normal numeric sort types, eg
|
||||
* {@link org.apache.lucene.search.SortField.Type#INT}. <code>LegacyIntField</code>
|
||||
|
@ -84,7 +84,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyFieldType#setNumericPrecisionStep} method if you'd
|
||||
* like to change the value. Note that you must also
|
||||
* specify a congruent value when creating {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* For low cardinality fields larger precision steps are good.
|
||||
* If the cardinality is < 100, it is fair
|
||||
* to use {@link Integer#MAX_VALUE}, which produces one
|
||||
|
@ -93,8 +93,8 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* <p>For more information on the internals of numeric trie
|
||||
* indexing, including the <a
|
||||
* href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
|
||||
* configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
|
||||
* configuration, see {@link org.apache.solr.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.solr.legacy.LegacyNumericUtils}.
|
||||
*
|
||||
* <p>If you only need to sort by numeric value, and never
|
||||
* run range querying/filtering, you can index using a
|
||||
|
@ -102,7 +102,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* This will minimize disk space consumed. </p>
|
||||
*
|
||||
* <p>More advanced users can instead use {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* org.apache.solr.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* class is a wrapper around this token stream type for
|
||||
* easier, more intuitive usage.</p>
|
||||
*
|
||||
|
@ -145,7 +145,7 @@ public final class LegacyIntField extends LegacyField {
|
|||
|
||||
/** Creates a stored or un-stored LegacyIntField with the provided value
|
||||
* and default <code>precisionStep</code> {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* @param name field name
|
||||
* @param value 32-bit integer value
|
||||
* @param stored Store.YES if the content should also be stored
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -61,7 +61,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* <code>long</code> value.
|
||||
*
|
||||
* <p>To perform range querying or filtering against a
|
||||
* <code>LegacyLongField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* <code>LegacyLongField</code>, use {@link org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* To sort according to a
|
||||
* <code>LegacyLongField</code>, use the normal numeric sort types, eg
|
||||
* {@link org.apache.lucene.search.SortField.Type#LONG}. <code>LegacyLongField</code>
|
||||
|
@ -95,7 +95,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* LegacyFieldType#setNumericPrecisionStep} method if you'd
|
||||
* like to change the value. Note that you must also
|
||||
* specify a congruent value when creating {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
* For low cardinality fields larger precision steps are good.
|
||||
* If the cardinality is < 100, it is fair
|
||||
* to use {@link Integer#MAX_VALUE}, which produces one
|
||||
|
@ -104,8 +104,8 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* <p>For more information on the internals of numeric trie
|
||||
* indexing, including the <a
|
||||
* href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
|
||||
* configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
|
||||
* configuration, see {@link org.apache.solr.legacy.LegacyNumericRangeQuery}. The format of
|
||||
* indexed values is described in {@link org.apache.solr.legacy.LegacyNumericUtils}.
|
||||
*
|
||||
* <p>If you only need to sort by numeric value, and never
|
||||
* run range querying/filtering, you can index using a
|
||||
|
@ -113,7 +113,7 @@ import org.apache.lucene.index.IndexOptions;
|
|||
* This will minimize disk space consumed.
|
||||
*
|
||||
* <p>More advanced users can instead use {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* org.apache.solr.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
|
||||
* class is a wrapper around this token stream type for
|
||||
* easier, more intuitive usage.</p>
|
||||
*
|
||||
|
@ -154,7 +154,7 @@ public final class LegacyLongField extends LegacyField {
|
|||
|
||||
/** Creates a stored or un-stored LegacyLongField with the provided value
|
||||
* and default <code>precisionStep</code> {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* @param name field name
|
||||
* @param value 64-bit long value
|
||||
* @param stored Store.YES if the content should also be stored
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -41,9 +41,9 @@ import org.apache.lucene.index.Term; // for javadocs
|
|||
/**
|
||||
* <p>A {@link Query} that matches numeric values within a
|
||||
* specified range. To use this, you must first index the
|
||||
* numeric values using {@link org.apache.lucene.legacy.LegacyIntField}, {@link
|
||||
* org.apache.lucene.legacy.LegacyFloatField}, {@link org.apache.lucene.legacy.LegacyLongField} or {@link org.apache.lucene.legacy.LegacyDoubleField} (expert: {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericTokenStream}). If your terms are instead textual,
|
||||
* numeric values using {@link org.apache.solr.legacy.LegacyIntField}, {@link
|
||||
* org.apache.solr.legacy.LegacyFloatField}, {@link org.apache.solr.legacy.LegacyLongField} or {@link org.apache.solr.legacy.LegacyDoubleField} (expert: {@link
|
||||
* org.apache.solr.legacy.LegacyNumericTokenStream}). If your terms are instead textual,
|
||||
* you should use {@link TermRangeQuery}.</p>
|
||||
*
|
||||
* <p>You create a new LegacyNumericRangeQuery with the static
|
||||
|
@ -97,7 +97,7 @@ import org.apache.lucene.index.Term; // for javadocs
|
|||
* (all numerical values like doubles, longs, floats, and ints are converted to
|
||||
* lexicographic sortable string representations and stored with different precisions
|
||||
* (for a more detailed description of how the values are stored,
|
||||
* see {@link org.apache.lucene.legacy.LegacyNumericUtils}). A range is then divided recursively into multiple intervals for searching:
|
||||
* see {@link org.apache.solr.legacy.LegacyNumericUtils}). A range is then divided recursively into multiple intervals for searching:
|
||||
* The center of the range is searched only with the lowest possible precision in the <em>trie</em>,
|
||||
* while the boundaries are matched more exactly. This reduces the number of terms dramatically.</p>
|
||||
*
|
||||
|
@ -113,7 +113,7 @@ import org.apache.lucene.index.Term; // for javadocs
|
|||
* <h3><a name="precisionStepDesc">Precision Step</a></h3>
|
||||
* <p>You can choose any <code>precisionStep</code> when encoding values.
|
||||
* Lower step values mean more precisions and so more terms in index (and index gets larger). The number
|
||||
* of indexed terms per value is (those are generated by {@link org.apache.lucene.legacy.LegacyNumericTokenStream}):
|
||||
* of indexed terms per value is (those are generated by {@link org.apache.solr.legacy.LegacyNumericTokenStream}):
|
||||
* <p style="font-family:serif">
|
||||
* indexedTermsPerValue = <b>ceil</b><big>(</big>bitsPerValue / precisionStep<big>)</big>
|
||||
* </p>
|
||||
|
@ -149,8 +149,8 @@ import org.apache.lucene.index.Term; // for javadocs
|
|||
* <li>Steps <b>≥64</b> for <em>long/double</em> and <b>≥32</b> for <em>int/float</em> produces one token
|
||||
* per value in the index and querying is as slow as a conventional {@link TermRangeQuery}. But it can be used
|
||||
* to produce fields, that are solely used for sorting (in this case simply use {@link Integer#MAX_VALUE} as
|
||||
* <code>precisionStep</code>). Using {@link org.apache.lucene.legacy.LegacyIntField},
|
||||
* {@link org.apache.lucene.legacy.LegacyLongField}, {@link org.apache.lucene.legacy.LegacyFloatField} or {@link org.apache.lucene.legacy.LegacyDoubleField} for sorting
|
||||
* <code>precisionStep</code>). Using {@link org.apache.solr.legacy.LegacyIntField},
|
||||
* {@link org.apache.solr.legacy.LegacyLongField}, {@link org.apache.solr.legacy.LegacyFloatField} or {@link org.apache.solr.legacy.LegacyDoubleField} for sorting
|
||||
* is ideal, because building the field cache is much faster than with text-only numbers.
|
||||
* These fields have one term per value and therefore also work with term enumeration for building distinct lists
|
||||
* (e.g. facets / preselected values to search for).
|
||||
|
@ -205,7 +205,7 @@ public final class LegacyNumericRangeQuery<T extends Number> extends MultiTermQu
|
|||
|
||||
/**
|
||||
* Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>long</code>
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the min or max value to <code>null</code>. By setting inclusive to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
|
@ -231,7 +231,7 @@ public final class LegacyNumericRangeQuery<T extends Number> extends MultiTermQu
|
|||
|
||||
/**
|
||||
* Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>int</code>
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the min or max value to <code>null</code>. By setting inclusive to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
|
@ -259,7 +259,7 @@ public final class LegacyNumericRangeQuery<T extends Number> extends MultiTermQu
|
|||
|
||||
/**
|
||||
* Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>double</code>
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the min or max value to <code>null</code>.
|
||||
* {@link Double#NaN} will never match a half-open range, to hit {@code NaN} use a query
|
||||
|
@ -289,7 +289,7 @@ public final class LegacyNumericRangeQuery<T extends Number> extends MultiTermQu
|
|||
|
||||
/**
|
||||
* Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>float</code>
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* range using the default <code>precisionStep</code> {@link org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the min or max value to <code>null</code>.
|
||||
* {@link Float#NaN} will never match a half-open range, to hit {@code NaN} use a query
|
||||
|
@ -390,8 +390,8 @@ public final class LegacyNumericRangeQuery<T extends Number> extends MultiTermQu
|
|||
* <p>
|
||||
* WARNING: This term enumeration is not guaranteed to be always ordered by
|
||||
* {@link Term#compareTo}.
|
||||
* The ordering depends on how {@link org.apache.lucene.legacy.LegacyNumericUtils#splitLongRange} and
|
||||
* {@link org.apache.lucene.legacy.LegacyNumericUtils#splitIntRange} generates the sub-ranges. For
|
||||
* The ordering depends on how {@link org.apache.solr.legacy.LegacyNumericUtils#splitLongRange} and
|
||||
* {@link org.apache.solr.legacy.LegacyNumericUtils#splitIntRange} generates the sub-ranges. For
|
||||
* {@link MultiTermQuery} ordering is not relevant.
|
||||
*/
|
||||
private final class NumericRangeTermsEnum extends FilteredTermsEnum {
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -35,10 +35,10 @@ import org.apache.lucene.util.NumericUtils;
|
|||
/**
|
||||
* <b>Expert:</b> This class provides a {@link TokenStream}
|
||||
* for indexing numeric values that can be used by {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
*
|
||||
* <p>Note that for simple usage, {@link org.apache.lucene.legacy.LegacyIntField}, {@link
|
||||
* org.apache.lucene.legacy.LegacyLongField}, {@link org.apache.lucene.legacy.LegacyFloatField} or {@link org.apache.lucene.legacy.LegacyDoubleField} is
|
||||
* <p>Note that for simple usage, {@link org.apache.solr.legacy.LegacyIntField}, {@link
|
||||
* org.apache.solr.legacy.LegacyLongField}, {@link org.apache.solr.legacy.LegacyFloatField} or {@link org.apache.solr.legacy.LegacyDoubleField} is
|
||||
* recommended. These fields disable norms and
|
||||
* term freqs, as they are not usually needed during
|
||||
* searching. If you need to change these settings, you
|
||||
|
@ -81,7 +81,7 @@ import org.apache.lucene.util.NumericUtils;
|
|||
* than one numeric field, use a separate <code>LegacyNumericTokenStream</code>
|
||||
* instance for each.</p>
|
||||
*
|
||||
* <p>See {@link org.apache.lucene.legacy.LegacyNumericRangeQuery} for more details on the
|
||||
* <p>See {@link org.apache.solr.legacy.LegacyNumericRangeQuery} for more details on the
|
||||
* <a
|
||||
* href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
|
||||
* parameter as well as how numeric fields work under the hood.</p>
|
||||
|
@ -140,7 +140,7 @@ public final class LegacyNumericTokenStream extends TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
/** Implementation of {@link org.apache.lucene.legacy.LegacyNumericTokenStream.LegacyNumericTermAttribute}.
|
||||
/** Implementation of {@link org.apache.solr.legacy.LegacyNumericTokenStream.LegacyNumericTermAttribute}.
|
||||
* @lucene.internal
|
||||
* @since 4.0
|
||||
*/
|
||||
|
@ -240,7 +240,7 @@ public final class LegacyNumericTokenStream extends TokenStream {
|
|||
|
||||
/**
|
||||
* Creates a token stream for numeric values using the default <code>precisionStep</code>
|
||||
* {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16). The stream is not yet initialized,
|
||||
* {@link org.apache.solr.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16). The stream is not yet initialized,
|
||||
* before using set a value using the various set<em>???</em>Value() methods.
|
||||
*/
|
||||
public LegacyNumericTokenStream() {
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
/** Data type of the numeric value
|
||||
* @since 3.2
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -43,9 +43,9 @@ import org.apache.lucene.util.BytesRefBuilder;
|
|||
* during encoding.
|
||||
*
|
||||
* <p>For easy usage, the trie algorithm is implemented for indexing inside
|
||||
* {@link org.apache.lucene.legacy.LegacyNumericTokenStream} that can index <code>int</code>, <code>long</code>,
|
||||
* {@link org.apache.solr.legacy.LegacyNumericTokenStream} that can index <code>int</code>, <code>long</code>,
|
||||
* <code>float</code>, and <code>double</code>. For querying,
|
||||
* {@link org.apache.lucene.legacy.LegacyNumericRangeQuery} implements the query part
|
||||
* {@link org.apache.solr.legacy.LegacyNumericRangeQuery} implements the query part
|
||||
* for the same data types.
|
||||
*
|
||||
* @lucene.internal
|
||||
|
@ -61,15 +61,15 @@ public final class LegacyNumericUtils {
|
|||
private LegacyNumericUtils() {} // no instance!
|
||||
|
||||
/**
|
||||
* The default precision step used by {@link org.apache.lucene.legacy.LegacyLongField},
|
||||
* {@link org.apache.lucene.legacy.LegacyDoubleField}, {@link org.apache.lucene.legacy.LegacyNumericTokenStream}, {@link
|
||||
* org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* The default precision step used by {@link org.apache.solr.legacy.LegacyLongField},
|
||||
* {@link org.apache.solr.legacy.LegacyDoubleField}, {@link org.apache.solr.legacy.LegacyNumericTokenStream}, {@link
|
||||
* org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
*/
|
||||
public static final int PRECISION_STEP_DEFAULT = 16;
|
||||
|
||||
/**
|
||||
* The default precision step used by {@link org.apache.lucene.legacy.LegacyIntField} and
|
||||
* {@link org.apache.lucene.legacy.LegacyFloatField}.
|
||||
* The default precision step used by {@link org.apache.solr.legacy.LegacyIntField} and
|
||||
* {@link org.apache.solr.legacy.LegacyFloatField}.
|
||||
*/
|
||||
public static final int PRECISION_STEP_DEFAULT_32 = 8;
|
||||
|
||||
|
@ -101,7 +101,7 @@ public final class LegacyNumericUtils {
|
|||
|
||||
/**
|
||||
* Returns prefix coded bits after reducing the precision by <code>shift</code> bits.
|
||||
* This is method is used by {@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
* This is method is used by {@link org.apache.solr.legacy.LegacyNumericTokenStream}.
|
||||
* After encoding, {@code bytes.offset} will always be 0.
|
||||
* @param val the numeric value
|
||||
* @param shift how many bits to strip from the right
|
||||
|
@ -128,7 +128,7 @@ public final class LegacyNumericUtils {
|
|||
|
||||
/**
|
||||
* Returns prefix coded bits after reducing the precision by <code>shift</code> bits.
|
||||
* This is method is used by {@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
* This is method is used by {@link org.apache.solr.legacy.LegacyNumericTokenStream}.
|
||||
* After encoding, {@code bytes.offset} will always be 0.
|
||||
* @param val the numeric value
|
||||
* @param shift how many bits to strip from the right
|
||||
|
@ -232,7 +232,7 @@ public final class LegacyNumericUtils {
|
|||
* {@link org.apache.lucene.search.BooleanQuery} for each call to its
|
||||
* {@link LongRangeBuilder#addRange(BytesRef,BytesRef)}
|
||||
* method.
|
||||
* <p>This method is used by {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* <p>This method is used by {@link org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
*/
|
||||
public static void splitLongRange(final LongRangeBuilder builder,
|
||||
final int precisionStep, final long minBound, final long maxBound
|
||||
|
@ -246,7 +246,7 @@ public final class LegacyNumericUtils {
|
|||
* {@link org.apache.lucene.search.BooleanQuery} for each call to its
|
||||
* {@link IntRangeBuilder#addRange(BytesRef,BytesRef)}
|
||||
* method.
|
||||
* <p>This method is used by {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
|
||||
* <p>This method is used by {@link org.apache.solr.legacy.LegacyNumericRangeQuery}.
|
||||
*/
|
||||
public static void splitIntRange(final IntRangeBuilder builder,
|
||||
final int precisionStep, final int minBound, final int maxBound
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* 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.legacy;
|
||||
|
||||
import org.apache.lucene.document.DoubleDocValuesField;
|
||||
import org.apache.lucene.document.DoublePoint;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.FieldType;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.solr.legacy.LegacyDoubleField;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericType;
|
||||
import org.apache.lucene.queries.function.FunctionRangeQuery;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.spatial.SpatialStrategy;
|
||||
import org.apache.lucene.spatial.query.SpatialArgs;
|
||||
import org.apache.lucene.spatial.query.SpatialOperation;
|
||||
import org.apache.lucene.spatial.query.UnsupportedSpatialOperation;
|
||||
import org.locationtech.spatial4j.context.SpatialContext;
|
||||
import org.locationtech.spatial4j.shape.Circle;
|
||||
import org.locationtech.spatial4j.shape.Point;
|
||||
import org.locationtech.spatial4j.shape.Rectangle;
|
||||
import org.locationtech.spatial4j.shape.Shape;
|
||||
|
||||
/**
|
||||
* Simple {@link SpatialStrategy} which represents Points in two numeric fields.
|
||||
* The Strategy's best feature is decent distance sort.
|
||||
*
|
||||
* <p>
|
||||
* <b>Characteristics:</b>
|
||||
* <br>
|
||||
* <ul>
|
||||
* <li>Only indexes points; just one per field value.</li>
|
||||
* <li>Can query by a rectangle or circle.</li>
|
||||
* <li>{@link
|
||||
* org.apache.lucene.spatial.query.SpatialOperation#Intersects} and {@link
|
||||
* SpatialOperation#IsWithin} is supported.</li>
|
||||
* <li>Requires DocValues for
|
||||
* {@link #makeDistanceValueSource(org.locationtech.spatial4j.shape.Point)} and for
|
||||
* searching with a Circle.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* <b>Implementation:</b>
|
||||
* <p>
|
||||
* This is a simple Strategy. Search works with a pair of range queries on two {@link DoublePoint}s representing
|
||||
* x & y fields. A Circle query does the same bbox query but adds a
|
||||
* ValueSource filter on
|
||||
* {@link #makeDistanceValueSource(org.locationtech.spatial4j.shape.Point)}.
|
||||
* <p>
|
||||
* One performance shortcoming with this strategy is that a scenario involving
|
||||
* both a search using a Circle and sort will result in calculations for the
|
||||
* spatial distance being done twice -- once for the filter and second for the
|
||||
* sort.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class PointVectorStrategy extends SpatialStrategy {
|
||||
|
||||
// note: we use a FieldType to articulate the options we want on the field. We don't use it as-is with a Field, we
|
||||
// create more than one Field.
|
||||
|
||||
/**
|
||||
* pointValues, docValues, and nothing else.
|
||||
*/
|
||||
public static FieldType DEFAULT_FIELDTYPE;
|
||||
|
||||
@Deprecated
|
||||
public static LegacyFieldType LEGACY_FIELDTYPE;
|
||||
static {
|
||||
// Default: pointValues + docValues
|
||||
FieldType type = new FieldType();
|
||||
type.setDimensions(1, Double.BYTES);//pointValues (assume Double)
|
||||
type.setDocValuesType(DocValuesType.NUMERIC);//docValues
|
||||
type.setStored(false);
|
||||
type.freeze();
|
||||
DEFAULT_FIELDTYPE = type;
|
||||
// Legacy default: legacyNumerics
|
||||
LegacyFieldType legacyType = new LegacyFieldType();
|
||||
legacyType.setIndexOptions(IndexOptions.DOCS);
|
||||
legacyType.setNumericType(LegacyNumericType.DOUBLE);
|
||||
legacyType.setNumericPrecisionStep(8);// same as solr default
|
||||
legacyType.setDocValuesType(DocValuesType.NONE);//no docValues!
|
||||
legacyType.setStored(false);
|
||||
legacyType.freeze();
|
||||
LEGACY_FIELDTYPE = legacyType;
|
||||
}
|
||||
|
||||
public static final String SUFFIX_X = "__x";
|
||||
public static final String SUFFIX_Y = "__y";
|
||||
|
||||
private final String fieldNameX;
|
||||
private final String fieldNameY;
|
||||
|
||||
private final int fieldsLen;
|
||||
private final boolean hasStored;
|
||||
private final boolean hasDocVals;
|
||||
private final boolean hasPointVals;
|
||||
// equiv to "hasLegacyNumerics":
|
||||
private final LegacyFieldType legacyNumericFieldType; // not stored; holds precision step.
|
||||
|
||||
/**
|
||||
* Create a new {@link PointVectorStrategy} instance that uses {@link DoublePoint} and {@link DoublePoint#newRangeQuery}
|
||||
*/
|
||||
public static PointVectorStrategy newInstance(SpatialContext ctx, String fieldNamePrefix) {
|
||||
return new PointVectorStrategy(ctx, fieldNamePrefix, DEFAULT_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link PointVectorStrategy} instance that uses {@link LegacyDoubleField} for backwards compatibility.
|
||||
* However, back-compat is limited; we don't support circle queries or {@link #makeDistanceValueSource(Point, double)}
|
||||
* since that requires docValues (the legacy config didn't have that).
|
||||
*
|
||||
* @deprecated LegacyNumerics will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public static PointVectorStrategy newLegacyInstance(SpatialContext ctx, String fieldNamePrefix) {
|
||||
return new PointVectorStrategy(ctx, fieldNamePrefix, LEGACY_FIELDTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance configured with the provided FieldType options. See {@link #DEFAULT_FIELDTYPE}.
|
||||
* a field type is used to articulate the desired options (namely pointValues, docValues, stored). Legacy numerics
|
||||
* is configurable this way too.
|
||||
*/
|
||||
public PointVectorStrategy(SpatialContext ctx, String fieldNamePrefix, FieldType fieldType) {
|
||||
super(ctx, fieldNamePrefix);
|
||||
this.fieldNameX = fieldNamePrefix+SUFFIX_X;
|
||||
this.fieldNameY = fieldNamePrefix+SUFFIX_Y;
|
||||
|
||||
int numPairs = 0;
|
||||
if ((this.hasStored = fieldType.stored())) {
|
||||
numPairs++;
|
||||
}
|
||||
if ((this.hasDocVals = fieldType.docValuesType() != DocValuesType.NONE)) {
|
||||
numPairs++;
|
||||
}
|
||||
if ((this.hasPointVals = fieldType.pointDimensionCount() > 0)) {
|
||||
numPairs++;
|
||||
}
|
||||
if (fieldType.indexOptions() != IndexOptions.NONE && fieldType instanceof LegacyFieldType && ((LegacyFieldType)fieldType).numericType() != null) {
|
||||
if (hasPointVals) {
|
||||
throw new IllegalArgumentException("pointValues and LegacyNumericType are mutually exclusive");
|
||||
}
|
||||
final LegacyFieldType legacyType = (LegacyFieldType) fieldType;
|
||||
if (legacyType.numericType() != LegacyNumericType.DOUBLE) {
|
||||
throw new IllegalArgumentException(getClass() + " does not support " + legacyType.numericType());
|
||||
}
|
||||
numPairs++;
|
||||
legacyNumericFieldType = new LegacyFieldType(LegacyDoubleField.TYPE_NOT_STORED);
|
||||
legacyNumericFieldType.setNumericPrecisionStep(legacyType.numericPrecisionStep());
|
||||
legacyNumericFieldType.freeze();
|
||||
} else {
|
||||
legacyNumericFieldType = null;
|
||||
}
|
||||
this.fieldsLen = numPairs * 2;
|
||||
}
|
||||
|
||||
|
||||
String getFieldNameX() {
|
||||
return fieldNameX;
|
||||
}
|
||||
|
||||
String getFieldNameY() {
|
||||
return fieldNameY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field[] createIndexableFields(Shape shape) {
|
||||
if (shape instanceof Point)
|
||||
return createIndexableFields((Point) shape);
|
||||
throw new UnsupportedOperationException("Can only index Point, not " + shape);
|
||||
}
|
||||
|
||||
/** @see #createIndexableFields(org.locationtech.spatial4j.shape.Shape) */
|
||||
public Field[] createIndexableFields(Point point) {
|
||||
Field[] fields = new Field[fieldsLen];
|
||||
int idx = -1;
|
||||
if (hasStored) {
|
||||
fields[++idx] = new StoredField(fieldNameX, point.getX());
|
||||
fields[++idx] = new StoredField(fieldNameY, point.getY());
|
||||
}
|
||||
if (hasDocVals) {
|
||||
fields[++idx] = new DoubleDocValuesField(fieldNameX, point.getX());
|
||||
fields[++idx] = new DoubleDocValuesField(fieldNameY, point.getY());
|
||||
}
|
||||
if (hasPointVals) {
|
||||
fields[++idx] = new DoublePoint(fieldNameX, point.getX());
|
||||
fields[++idx] = new DoublePoint(fieldNameY, point.getY());
|
||||
}
|
||||
if (legacyNumericFieldType != null) {
|
||||
fields[++idx] = new LegacyDoubleField(fieldNameX, point.getX(), legacyNumericFieldType);
|
||||
fields[++idx] = new LegacyDoubleField(fieldNameY, point.getY(), legacyNumericFieldType);
|
||||
}
|
||||
assert idx == fields.length - 1;
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSource makeDistanceValueSource(Point queryPoint, double multiplier) {
|
||||
return new DistanceValueSource(this, queryPoint, multiplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantScoreQuery makeQuery(SpatialArgs args) {
|
||||
if(! SpatialOperation.is( args.getOperation(),
|
||||
SpatialOperation.Intersects,
|
||||
SpatialOperation.IsWithin ))
|
||||
throw new UnsupportedSpatialOperation(args.getOperation());
|
||||
Shape shape = args.getShape();
|
||||
if (shape instanceof Rectangle) {
|
||||
Rectangle bbox = (Rectangle) shape;
|
||||
return new ConstantScoreQuery(makeWithin(bbox));
|
||||
} else if (shape instanceof Circle) {
|
||||
Circle circle = (Circle)shape;
|
||||
Rectangle bbox = circle.getBoundingBox();
|
||||
Query approxQuery = makeWithin(bbox);
|
||||
BooleanQuery.Builder bqBuilder = new BooleanQuery.Builder();
|
||||
FunctionRangeQuery vsRangeQuery =
|
||||
new FunctionRangeQuery(makeDistanceValueSource(circle.getCenter()), 0.0, circle.getRadius(), true, true);
|
||||
bqBuilder.add(approxQuery, BooleanClause.Occur.FILTER);//should have lowest "cost" value; will drive iteration
|
||||
bqBuilder.add(vsRangeQuery, BooleanClause.Occur.FILTER);
|
||||
return new ConstantScoreQuery(bqBuilder.build());
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Only Rectangles and Circles are currently supported, " +
|
||||
"found [" + shape.getClass() + "]");//TODO
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a query to retrieve documents that fully contain the input envelope.
|
||||
*/
|
||||
private Query makeWithin(Rectangle bbox) {
|
||||
BooleanQuery.Builder bq = new BooleanQuery.Builder();
|
||||
BooleanClause.Occur MUST = BooleanClause.Occur.MUST;
|
||||
if (bbox.getCrossesDateLine()) {
|
||||
//use null as performance trick since no data will be beyond the world bounds
|
||||
bq.add(rangeQuery(fieldNameX, null/*-180*/, bbox.getMaxX()), BooleanClause.Occur.SHOULD );
|
||||
bq.add(rangeQuery(fieldNameX, bbox.getMinX(), null/*+180*/), BooleanClause.Occur.SHOULD );
|
||||
bq.setMinimumNumberShouldMatch(1);//must match at least one of the SHOULD
|
||||
} else {
|
||||
bq.add(rangeQuery(fieldNameX, bbox.getMinX(), bbox.getMaxX()), MUST);
|
||||
}
|
||||
bq.add(rangeQuery(fieldNameY, bbox.getMinY(), bbox.getMaxY()), MUST);
|
||||
return bq.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric range query based on FieldType
|
||||
* {@link LegacyNumericRangeQuery} is used for indexes created using {@code FieldType.LegacyNumericType}
|
||||
* {@link DoublePoint#newRangeQuery} is used for indexes created using {@link DoublePoint} fields
|
||||
*/
|
||||
private Query rangeQuery(String fieldName, Double min, Double max) {
|
||||
if (hasPointVals) {
|
||||
if (min == null) {
|
||||
min = Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
if (max == null) {
|
||||
max = Double.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
return DoublePoint.newRangeQuery(fieldName, min, max);
|
||||
|
||||
} else if (legacyNumericFieldType != null) {// todo remove legacy numeric support in 7.0
|
||||
return LegacyNumericRangeQuery.newDoubleRange(fieldName, legacyNumericFieldType.numericPrecisionStep(), min, max, true, true);//inclusive
|
||||
}
|
||||
//TODO try doc-value range query?
|
||||
throw new UnsupportedOperationException("An index is required for this operation.");
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
@ -18,4 +18,4 @@
|
|||
/**
|
||||
* Deprecated stuff!
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
|
@ -23,10 +23,10 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.spatial.bbox.BBoxOverlapRatioValueSource;
|
||||
import org.apache.lucene.spatial.bbox.BBoxStrategy;
|
||||
import org.apache.solr.legacy.BBoxStrategy;
|
||||
import org.apache.lucene.spatial.query.SpatialArgs;
|
||||
import org.apache.lucene.spatial.util.ShapeAreaValueSource;
|
||||
import org.apache.solr.common.SolrException;
|
||||
|
|
|
@ -35,11 +35,11 @@ import javax.xml.xpath.XPathFactory;
|
|||
import org.apache.lucene.document.NumericDocValuesField;
|
||||
import org.apache.lucene.document.SortedSetDocValuesField;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.legacy.LegacyNumericType;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericType;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.valuesource.EnumFieldSource;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
|
|
|
@ -20,8 +20,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.spatial.vector.PointVectorStrategy;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.PointVectorStrategy;
|
||||
|
||||
/**
|
||||
* @see PointVectorStrategy
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
|
||||
|
|
|
@ -30,14 +30,14 @@ import org.apache.lucene.document.NumericDocValuesField;
|
|||
import org.apache.lucene.document.SortedSetDocValuesField;
|
||||
import org.apache.lucene.index.DocValuesType;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.legacy.LegacyDoubleField;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyFloatField;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.legacy.LegacyNumericType;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyDoubleField;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyFloatField;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericType;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
|
||||
import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
|
||||
|
@ -63,9 +63,9 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
/**
|
||||
* Provides field types to support for Lucene's {@link
|
||||
* org.apache.lucene.legacy.LegacyIntField}, {@link org.apache.lucene.legacy.LegacyLongField}, {@link org.apache.lucene.legacy.LegacyFloatField} and
|
||||
* {@link org.apache.lucene.legacy.LegacyDoubleField}.
|
||||
* See {@link org.apache.lucene.legacy.LegacyNumericRangeQuery} for more details.
|
||||
* org.apache.solr.legacy.LegacyIntField}, {@link org.apache.solr.legacy.LegacyLongField}, {@link org.apache.solr.legacy.LegacyFloatField} and
|
||||
* {@link org.apache.solr.legacy.LegacyDoubleField}.
|
||||
* See {@link org.apache.solr.legacy.LegacyNumericRangeQuery} for more details.
|
||||
* It supports integer, float, long, double and date types.
|
||||
* <p>
|
||||
* For each number being added to this field, multiple terms are generated as per the algorithm described in the above
|
||||
|
@ -78,7 +78,7 @@ import org.slf4j.LoggerFactory;
|
|||
* generated, range search will be no faster than any other number field, but sorting will still be possible.
|
||||
*
|
||||
*
|
||||
* @see org.apache.lucene.legacy.LegacyNumericRangeQuery
|
||||
* @see org.apache.solr.legacy.LegacyNumericRangeQuery
|
||||
* @since solr 1.4
|
||||
*/
|
||||
public class TrieField extends NumericFieldType {
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.docvalues.FloatDocValues;
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.docvalues.IntDocValues;
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.docvalues.LongDocValues;
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queryparser.xml.DOMUtils;
|
||||
import org.apache.lucene.queryparser.xml.ParserException;
|
||||
import org.apache.lucene.queryparser.xml.QueryBuilder;
|
||||
|
@ -26,10 +26,10 @@ import org.apache.lucene.queryparser.xml.builders.PointRangeQueryBuilder;
|
|||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Creates a {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The table below specifies the required
|
||||
* Creates a {@link org.apache.solr.legacy.LegacyNumericRangeQuery}. The table below specifies the required
|
||||
* attributes and the defaults if optional attributes are omitted. For more
|
||||
* detail on what each of the attributes actually do, consult the documentation
|
||||
* for {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}:
|
||||
* for {@link org.apache.solr.legacy.LegacyNumericRangeQuery}:
|
||||
* <table summary="supported attributes">
|
||||
* <tr>
|
||||
* <th>Attribute name</th>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.BoostQuery;
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.apache.lucene.util.Bits;
|
|||
* Constrains search results to only match those which also match a provided
|
||||
* query.
|
||||
*
|
||||
* <p> This could be used, for example, with a {@link org.apache.lucene.legacy.LegacyNumericRangeQuery} on a suitably
|
||||
* <p> This could be used, for example, with a {@link org.apache.solr.legacy.LegacyNumericRangeQuery} on a suitably
|
||||
* formatted date field to implement date filtering. One could re-use a single
|
||||
* CachingWrapperFilter(QueryWrapperFilter) that matches, e.g., only documents modified
|
||||
* within the last week. This would only need to be reconstructed once per day.
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.mlt.MoreLikeThis;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.apache.solr.search.mlt;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.mlt.MoreLikeThis;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.apache.lucene.index.SortedDocValues;
|
|||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.index.Terms;
|
||||
import org.apache.lucene.index.TermsEnum;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.util.Accountable;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
@ -159,8 +159,8 @@ public interface FieldCache {
|
|||
};
|
||||
|
||||
/**
|
||||
* A parser instance for int values encoded by {@link org.apache.lucene.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.lucene.legacy.LegacyIntField}/{@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
* A parser instance for int values encoded by {@link org.apache.solr.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.solr.legacy.LegacyIntField}/{@link org.apache.solr.legacy.LegacyNumericTokenStream}.
|
||||
* @deprecated Index with points and use {@link #INT_POINT_PARSER} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -182,8 +182,8 @@ public interface FieldCache {
|
|||
};
|
||||
|
||||
/**
|
||||
* A parser instance for float values encoded with {@link org.apache.lucene.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.lucene.legacy.LegacyFloatField}/{@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
* A parser instance for float values encoded with {@link org.apache.solr.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.solr.legacy.LegacyFloatField}/{@link org.apache.solr.legacy.LegacyNumericTokenStream}.
|
||||
* @deprecated Index with points and use {@link #FLOAT_POINT_PARSER} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -207,8 +207,8 @@ public interface FieldCache {
|
|||
};
|
||||
|
||||
/**
|
||||
* A parser instance for long values encoded by {@link org.apache.lucene.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.lucene.legacy.LegacyLongField}/{@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
* A parser instance for long values encoded by {@link org.apache.solr.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.solr.legacy.LegacyLongField}/{@link org.apache.solr.legacy.LegacyNumericTokenStream}.
|
||||
* @deprecated Index with points and use {@link #LONG_POINT_PARSER} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -229,8 +229,8 @@ public interface FieldCache {
|
|||
};
|
||||
|
||||
/**
|
||||
* A parser instance for double values encoded with {@link org.apache.lucene.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.lucene.legacy.LegacyDoubleField}/{@link org.apache.lucene.legacy.LegacyNumericTokenStream}.
|
||||
* A parser instance for double values encoded with {@link org.apache.solr.legacy.LegacyNumericUtils}, e.g. when indexed
|
||||
* via {@link org.apache.solr.legacy.LegacyDoubleField}/{@link org.apache.solr.legacy.LegacyNumericTokenStream}.
|
||||
* @deprecated Index with points and use {@link #DOUBLE_POINT_PARSER} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -277,7 +277,7 @@ public interface FieldCache {
|
|||
* @param parser
|
||||
* Computes long for string values. May be {@code null} if the
|
||||
* requested field was indexed as {@link NumericDocValuesField} or
|
||||
* {@link org.apache.lucene.legacy.LegacyLongField}.
|
||||
* {@link org.apache.solr.legacy.LegacyLongField}.
|
||||
* @return The values in the given field for each document.
|
||||
* @throws IOException
|
||||
* If any error occurs.
|
||||
|
|
|
@ -87,7 +87,7 @@ public class UninvertingReader extends FilterLeafReader {
|
|||
*/
|
||||
DOUBLE_POINT,
|
||||
/**
|
||||
* Single-valued Integer, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyIntField})
|
||||
* Single-valued Integer, (e.g. indexed with {@link org.apache.solr.legacy.LegacyIntField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link NumericDocValuesField}.
|
||||
|
@ -96,7 +96,7 @@ public class UninvertingReader extends FilterLeafReader {
|
|||
@Deprecated
|
||||
LEGACY_INTEGER,
|
||||
/**
|
||||
* Single-valued Long, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyLongField})
|
||||
* Single-valued Long, (e.g. indexed with {@link org.apache.solr.legacy.LegacyLongField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link NumericDocValuesField}.
|
||||
|
@ -105,7 +105,7 @@ public class UninvertingReader extends FilterLeafReader {
|
|||
@Deprecated
|
||||
LEGACY_LONG,
|
||||
/**
|
||||
* Single-valued Float, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyFloatField})
|
||||
* Single-valued Float, (e.g. indexed with {@link org.apache.solr.legacy.LegacyFloatField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link NumericDocValuesField}.
|
||||
|
@ -114,7 +114,7 @@ public class UninvertingReader extends FilterLeafReader {
|
|||
@Deprecated
|
||||
LEGACY_FLOAT,
|
||||
/**
|
||||
* Single-valued Double, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyDoubleField})
|
||||
* Single-valued Double, (e.g. indexed with {@link org.apache.solr.legacy.LegacyDoubleField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link NumericDocValuesField}.
|
||||
|
@ -144,28 +144,28 @@ public class UninvertingReader extends FilterLeafReader {
|
|||
*/
|
||||
SORTED_SET_BINARY,
|
||||
/**
|
||||
* Multi-valued Integer, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyIntField})
|
||||
* Multi-valued Integer, (e.g. indexed with {@link org.apache.solr.legacy.LegacyIntField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link SortedSetDocValuesField}.
|
||||
*/
|
||||
SORTED_SET_INTEGER,
|
||||
/**
|
||||
* Multi-valued Float, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyFloatField})
|
||||
* Multi-valued Float, (e.g. indexed with {@link org.apache.solr.legacy.LegacyFloatField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link SortedSetDocValuesField}.
|
||||
*/
|
||||
SORTED_SET_FLOAT,
|
||||
/**
|
||||
* Multi-valued Long, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyLongField})
|
||||
* Multi-valued Long, (e.g. indexed with {@link org.apache.solr.legacy.LegacyLongField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link SortedSetDocValuesField}.
|
||||
*/
|
||||
SORTED_SET_LONG,
|
||||
/**
|
||||
* Multi-valued Double, (e.g. indexed with {@link org.apache.lucene.legacy.LegacyDoubleField})
|
||||
* Multi-valued Double, (e.g. indexed with {@link org.apache.solr.legacy.LegacyDoubleField})
|
||||
* <p>
|
||||
* Fields with this type act as if they were indexed with
|
||||
* {@link SortedSetDocValuesField}.
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.Terms;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -24,10 +24,10 @@ import org.apache.lucene.analysis.CannedTokenStream;
|
|||
import org.apache.lucene.analysis.Token;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyNumericTokenStream;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.legacy.LegacyNumericTokenStream.LegacyNumericTermAttribute;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyNumericTokenStream;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericTokenStream.LegacyNumericTermAttribute;
|
||||
|
||||
/** test tokenstream reuse by DefaultIndexingChain */
|
||||
public class TestLegacyFieldReuse extends BaseTokenStreamTestCase {
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -22,7 +22,7 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.lucene.util.FixedBitSet;
|
||||
import org.apache.lucene.util.LongBitSet;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
|
@ -23,11 +23,11 @@ import org.apache.lucene.index.MultiFields;
|
|||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.index.Terms;
|
||||
import org.apache.lucene.index.TermsEnum;
|
||||
import org.apache.lucene.legacy.LegacyDoubleField;
|
||||
import org.apache.lucene.legacy.LegacyFloatField;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyDoubleField;
|
||||
import org.apache.solr.legacy.LegacyFloatField;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.NumericUtils;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import java.util.Locale;
|
||||
|
@ -26,8 +26,8 @@ import org.apache.lucene.document.Document;
|
|||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.TermRangeQuery;
|
||||
import org.apache.lucene.search.TopDocs;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import org.apache.lucene.analysis.MockAnalyzer;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import org.apache.lucene.analysis.MockAnalyzer;
|
|
@ -14,16 +14,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.legacy;
|
||||
package org.apache.solr.legacy;
|
||||
|
||||
|
||||
import org.apache.lucene.util.AttributeImpl;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
|
||||
import org.apache.lucene.legacy.LegacyNumericTokenStream;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.legacy.LegacyNumericTokenStream.LegacyNumericTermAttributeImpl;
|
||||
import org.apache.solr.legacy.LegacyNumericTokenStream;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyNumericTokenStream.LegacyNumericTermAttributeImpl;
|
||||
import org.apache.lucene.analysis.BaseTokenStreamTestCase;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttributeImpl;
|
|
@ -18,7 +18,7 @@ package org.apache.solr.search;
|
|||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.queryparser.xml.ParserException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.apache.solr.common.params.MapSolrParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.locationtech.spatial4j.context.SpatialContext;
|
|||
import org.locationtech.spatial4j.distance.DistanceUtils;
|
||||
import org.locationtech.spatial4j.shape.Point;
|
||||
import org.locationtech.spatial4j.shape.Rectangle;
|
||||
import org.apache.lucene.spatial.bbox.BBoxStrategy;
|
||||
import org.apache.solr.legacy.BBoxStrategy;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
|
|
|
@ -29,8 +29,8 @@ import org.apache.lucene.index.DirectoryReader;
|
|||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.IndexWriterConfig;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.legacy.LegacyFloatField;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyFloatField;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.lucene.queries.function.FunctionQuery;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
|
||||
|
|
|
@ -43,9 +43,9 @@ import org.apache.lucene.index.SortedSetDocValues;
|
|||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.index.Terms;
|
||||
import org.apache.lucene.index.TermsEnum.SeekStatus;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.index.TermsEnum;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
|
|
@ -37,10 +37,10 @@ import org.apache.lucene.index.IndexWriterConfig;
|
|||
import org.apache.lucene.index.MultiReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.legacy.LegacyDoubleField;
|
||||
import org.apache.lucene.legacy.LegacyFloatField;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyDoubleField;
|
||||
import org.apache.solr.legacy.LegacyFloatField;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
|
|
|
@ -32,10 +32,10 @@ import org.apache.lucene.index.IndexWriterConfig;
|
|||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.NumericDocValues;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.legacy.LegacyDoubleField;
|
||||
import org.apache.lucene.legacy.LegacyFloatField;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyDoubleField;
|
||||
import org.apache.solr.legacy.LegacyFloatField;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
|
|
@ -23,9 +23,9 @@ import org.apache.lucene.analysis.MockAnalyzer;
|
|||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
|
|
|
@ -23,9 +23,9 @@ import org.apache.lucene.analysis.MockAnalyzer;
|
|||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
|
|
|
@ -40,10 +40,10 @@ import org.apache.lucene.index.IndexWriter;
|
|||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.legacy.LegacyFieldType;
|
||||
import org.apache.lucene.legacy.LegacyIntField;
|
||||
import org.apache.lucene.legacy.LegacyLongField;
|
||||
import org.apache.lucene.legacy.LegacyNumericUtils;
|
||||
import org.apache.solr.legacy.LegacyFieldType;
|
||||
import org.apache.solr.legacy.LegacyIntField;
|
||||
import org.apache.solr.legacy.LegacyLongField;
|
||||
import org.apache.solr.legacy.LegacyNumericUtils;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
|
Loading…
Reference in New Issue