LUCENE-7850: Move support for legacy numerics to solr/.

This commit is contained in:
Adrien Grand 2017-05-24 16:30:25 +02:00
parent 412e4ae2c1
commit 759fa42b62
63 changed files with 1451 additions and 373 deletions

View File

@ -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

View File

@ -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.

View File

@ -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) {

View File

@ -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.");
}

View File

@ -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 {

View File

@ -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.");

View File

@ -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});

View File

@ -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));

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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.");
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 &lt; 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

View File

@ -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;

View File

@ -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

View File

@ -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 &lt; 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

View File

@ -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 &lt; 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

View File

@ -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 &lt; 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

View File

@ -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">
* &nbsp;&nbsp;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>&ge;64</b> for <em>long/double</em> and <b>&ge;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 &lt;/&le; or &gt;/&ge; 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 &lt;/&le; or &gt;/&ge; 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 &lt;/&le; or &gt;/&ge; 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 &lt;/&le; or &gt;/&ge; 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 {

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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 &amp; 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.");
}
}

View File

@ -18,4 +18,4 @@
/**
* Deprecated stuff!
*/
package org.apache.lucene.legacy;
package org.apache.solr.legacy;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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>

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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}.

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;