Index: lucene/spatial/src/test/org/apache/lucene/spatial/vector/TestTwoDoublesStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/test/org/apache/lucene/spatial/vector/TestTwoDoublesStrategy.java (revision 1384918)
+++ lucene/spatial/src/test/org/apache/lucene/spatial/vector/TestTwoDoublesStrategy.java (revision )
@@ -1,0 +1,0 @@
Index: lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java (revision 1384918)
+++ lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java (revision )
@@ -24,10 +24,6 @@
import com.spatial4j.core.io.ShapeReadWriter;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.StoredField;
-import org.apache.lucene.document.StringField;
import org.apache.lucene.search.FilteredQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
@@ -38,6 +34,7 @@
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.query.SpatialOperation;
+import org.apache.lucene.spatial.vector.TwoDoublesStrategy;
import org.junit.Test;
import java.io.IOException;
@@ -71,6 +68,9 @@
strategy = new TermQueryPrefixTreeStrategy(grid, "termquery_geohash");
ctorArgs.add(new Object[]{new Param(strategy, "termquery_geohash")});
+ strategy = new TwoDoublesStrategy(ctx, "twodoubles");
+ ctorArgs.add(new Object[]{new Param(strategy, "twodoubles")});
+
return ctorArgs;
}
@@ -157,51 +157,7 @@
checkHitsBBox("43.517030,-96.789603", 110, 1, 17);
}
- /**
- * This test is similar to a Solr 3 spatial test.
- */
- @Test
- public void testDistanceOrder() throws IOException {
- adoc("100","1,2");
- adoc("101","4,-1");
- commit();
- double km1000inDeg = DistanceUtils.dist2Degrees(1000, DistanceUtils.EARTH_MEAN_RADIUS_KM);
-
- //query closer to #100
- checkHitsOrdered("Intersects(Circle(3,4 d="+km1000inDeg+"))", "101", "100");
- //query closer to #101
- checkHitsOrdered("Intersects(Circle(4,0 d="+km1000inDeg+"))", "100", "101");
- }
-
- private void checkHitsOrdered(String spatialQ, String... ids) {
- SpatialArgs args = this.argsParser.parse(spatialQ,ctx);
- Query query = strategy.makeQuery(args);
- SearchResults results = executeQuery(query, 100);
- String[] resultIds = new String[results.numFound];
- int i = 0;
- for (SearchResult result : results.results) {
- resultIds[i++] = result.document.get("id");
- }
- assertArrayEquals("order matters",ids, resultIds);
- }
-
//---- these are similar to Solr test methods
-
- private void adoc(String idStr, String shapeStr) throws IOException {
- Shape shape = new ShapeReadWriter(ctx).readShape(shapeStr);
- addDocument(newDoc(idStr,shape));
- }
-
- private Document newDoc(String id, Shape shape) {
- Document doc = new Document();
- doc.add(new StringField("id", id, Field.Store.YES));
- for (Field f : strategy.createIndexableFields(shape)) {
- doc.add(f);
- }
- if (storeShape)
- doc.add(new StoredField(strategy.getFieldName(), ctx.toString(shape)));
- return doc;
- }
private void checkHitsCircle(String ptStr, double distKM, int assertNumFound, int... assertIds) {
_checkHits(false, ptStr, distKM, assertNumFound, assertIds);
Index: lucene/spatial/src/java/org/apache/lucene/spatial/util/ValueSourceFilter.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/util/ValueSourceFilter.java (revision 1384918)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/util/ValueSourceFilter.java (revision )
@@ -29,7 +29,7 @@
/**
* Filter that matches all documents where a valuesource is
- * in between a range of min and max
+ * in between a range of min and max inclusive.
* @lucene.internal
*/
public class ValueSourceFilter extends Filter {
@@ -57,7 +57,7 @@
@Override
public boolean match(int doc) {
double val = values.doubleVal( doc );
- return val > min && val < max;
+ return val >= min && val <= max;
}
};
}
Index: lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java (revision 1384918)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java (revision )
@@ -30,6 +30,7 @@
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.Filter;
import org.apache.lucene.search.FilteredQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
@@ -94,32 +95,47 @@
}
@Override
- public ValueSource makeValueSource(SpatialArgs args) {
- Point p = args.getShape().getCenter();
- return new DistanceValueSource(this, p, ctx.getDistCalc());
+ public ValueSource makeDistanceValueSource(Point queryPoint) {
+ return new DistanceValueSource(this, queryPoint);
}
@Override
public Filter makeFilter(SpatialArgs args) {
- if( args.getShape() instanceof Circle) {
- if( SpatialOperation.is( args.getOperation(),
- SpatialOperation.Intersects,
- SpatialOperation.IsWithin )) {
- Circle circle = (Circle)args.getShape();
- Query bbox = makeWithin(circle.getBoundingBox());
+ //unwrap the CSQ from makeQuery
+ ConstantScoreQuery csq = makeQuery(args);
+ Filter filter = csq.getFilter();
+ if (filter != null)
+ return filter;
+ else
+ return new QueryWrapperFilter(csq.getQuery());
+ }
- // Make the ValueSource
- ValueSource valueSource = makeValueSource(args);
-
- return new ValueSourceFilter(
- new QueryWrapperFilter( bbox ), valueSource, 0, circle.getRadius() );
+ @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();
+ ValueSourceFilter vsf = new ValueSourceFilter(
+ new QueryWrapperFilter(makeWithin(bbox)),
+ makeDistanceValueSource(circle.getCenter()),
+ 0,
+ circle.getRadius() );
+ return new ConstantScoreQuery(vsf);
+ } else {
+ throw new InvalidShapeException("Only Rectangles and Circles are currently supported, " +
+ "found [" + shape.getClass() + "]");//TODO
- }
- }
+ }
+ }
- return new QueryWrapperFilter( makeQuery(args) );
- }
- @Override
- public Query makeQuery(SpatialArgs args) {
+ public Query makeQueryDistanceScore(SpatialArgs args) {
// For starters, just limit the bbox
Shape shape = args.getShape();
if (!(shape instanceof Rectangle || shape instanceof Circle)) {
@@ -151,7 +167,7 @@
Circle circle = (Circle)args.getShape();
// Make the ValueSource
- valueSource = makeValueSource(args);
+ valueSource = makeDistanceValueSource(shape.getCenter());
ValueSourceFilter vsf = new ValueSourceFilter(
new QueryWrapperFilter( spatial ), valueSource, 0, circle.getRadius() );
@@ -171,7 +187,7 @@
valueSource = new CachingDoubleValueSource(valueSource);
}
else {
- valueSource = makeValueSource(args);
+ valueSource = makeDistanceValueSource(shape.getCenter());
}
Query spatialRankingQuery = new FunctionQuery(valueSource);
BooleanQuery bq = new BooleanQuery();
@@ -182,49 +198,39 @@
/**
* Constructs a query to retrieve documents that fully contain the input envelope.
- * @return the spatial query
*/
private Query makeWithin(Rectangle bbox) {
- Query qX = NumericRangeQuery.newDoubleRange(
- fieldNameX,
- precisionStep,
- bbox.getMinX(),
- bbox.getMaxX(),
- true,
- true);
- Query qY = NumericRangeQuery.newDoubleRange(
- fieldNameY,
- precisionStep,
- bbox.getMinY(),
- bbox.getMaxY(),
- true,
- true);
-
BooleanQuery bq = new BooleanQuery();
- bq.add(qX,BooleanClause.Occur.MUST);
- bq.add(qY,BooleanClause.Occur.MUST);
+ 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;
}
+ private NumericRangeQuery rangeQuery(String fieldName, Double min, Double max) {
+ return NumericRangeQuery.newDoubleRange(
+ fieldName,
+ precisionStep,
+ min,
+ max,
+ true,
+ true);//inclusive
+ }
+
/**
* Constructs a query to retrieve documents that fully contain the input envelope.
* @return the spatial query
*/
Query makeDisjoint(Rectangle bbox) {
- Query qX = NumericRangeQuery.newDoubleRange(
- fieldNameX,
- precisionStep,
- bbox.getMinX(),
- bbox.getMaxX(),
- true,
- true);
- Query qY = NumericRangeQuery.newDoubleRange(
- fieldNameY,
- precisionStep,
- bbox.getMinY(),
- bbox.getMaxY(),
- true,
- true);
+ Query qX = rangeQuery(fieldNameX, bbox.getMinX(), bbox.getMaxX());
+ Query qY = rangeQuery(fieldNameY, bbox.getMinY(), bbox.getMaxY());
BooleanQuery bq = new BooleanQuery();
bq.add(qX,BooleanClause.Occur.MUST_NOT);