mirror of https://github.com/apache/lucene.git
SOLR-4230 geofilt and bbox support for Solr 4 spatial
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1428063 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
463d10dc4a
commit
35caf2c6bd
|
@ -22,7 +22,9 @@ import com.google.common.cache.Cache;
|
|||
import com.google.common.cache.CacheBuilder;
|
||||
import com.spatial4j.core.context.SpatialContext;
|
||||
import com.spatial4j.core.context.SpatialContextFactory;
|
||||
import com.spatial4j.core.distance.DistanceUtils;
|
||||
import com.spatial4j.core.exception.InvalidShapeException;
|
||||
import com.spatial4j.core.io.ParseUtils;
|
||||
import com.spatial4j.core.shape.Point;
|
||||
import com.spatial4j.core.shape.Rectangle;
|
||||
import com.spatial4j.core.shape.Shape;
|
||||
|
@ -43,6 +45,7 @@ import org.apache.solr.common.SolrException;
|
|||
import org.apache.solr.common.params.SolrParams;
|
||||
import org.apache.solr.response.TextResponseWriter;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.SpatialOptions;
|
||||
import org.apache.solr.util.MapListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -57,7 +60,7 @@ import java.util.concurrent.ExecutionException;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class AbstractSpatialFieldType<T extends SpatialStrategy> extends FieldType {
|
||||
public abstract class AbstractSpatialFieldType<T extends SpatialStrategy> extends FieldType implements SpatialQueryable {
|
||||
|
||||
/** A local-param with one of "none" (default), "distance", or "recipDistance". */
|
||||
public static final String SCORE_PARAM = "score";
|
||||
|
@ -160,6 +163,35 @@ public abstract class AbstractSpatialFieldType<T extends SpatialStrategy> extend
|
|||
// Query Support
|
||||
//--------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Implemented for compatibility with Solr 3 spatial geofilt & bbox query parsers:
|
||||
* {@link SpatialQueryable}.
|
||||
*/
|
||||
@Override
|
||||
public Query createSpatialQuery(QParser parser, SpatialOptions options) {
|
||||
//--WARNING: the code from here to the next marker is identical to LatLonType's impl.
|
||||
double[] point = null;
|
||||
try {
|
||||
point = ParseUtils.parseLatitudeLongitude(options.pointStr);
|
||||
} catch (InvalidShapeException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
|
||||
}
|
||||
|
||||
// lat & lon in degrees
|
||||
double latCenter = point[0];
|
||||
double lonCenter = point[1];
|
||||
|
||||
double distDeg = DistanceUtils.dist2Degrees(options.distance, options.radius);
|
||||
//--END-WARNING
|
||||
|
||||
Shape shape = ctx.makeCircle(lonCenter, latCenter, distDeg);
|
||||
if (options.bbox)
|
||||
shape = shape.getBoundingBox();
|
||||
|
||||
SpatialArgs spatialArgs = new SpatialArgs(SpatialOperation.Intersects, shape);
|
||||
return getQueryFromSpatialArgs(parser, options.field, spatialArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String part1, String part2, boolean minInclusive, boolean maxInclusive) {
|
||||
if (!minInclusive || !maxInclusive)
|
||||
|
|
|
@ -149,7 +149,7 @@ public class TestSolr4Spatial extends SolrTestCaseJ4 {
|
|||
|
||||
assertQ(req(
|
||||
"fl", "id," + fieldName, "q", "*:*", "rows", "1000",
|
||||
"fq", "{!field needScore=false f="+fieldName+"}Intersects(Circle(89.9,-130 d=9))"),
|
||||
"fq", "{!field f="+fieldName+"}Intersects(Circle(89.9,-130 d=9))"),
|
||||
"//result/doc/*[@name='" + fieldName + "']//text()='" + OUT + "'");
|
||||
}
|
||||
|
||||
|
@ -175,26 +175,37 @@ public class TestSolr4Spatial extends SolrTestCaseJ4 {
|
|||
// that there may be a more specific detailed id to investigate.
|
||||
tests[i++] = "*[count(//doc)=" + count + "]";
|
||||
|
||||
//never actually need the score but lets test
|
||||
String score = new String[]{null, "none","distance","recipDistance"}[random().nextInt(4)];
|
||||
//Test using the Solr 4 syntax
|
||||
{
|
||||
//never actually need the score but lets test
|
||||
String score = new String[]{null, "none","distance","recipDistance"}[random().nextInt(4)];
|
||||
|
||||
double distDEG = DistanceUtils.dist2Degrees(distKM, DistanceUtils.EARTH_MEAN_RADIUS_KM);
|
||||
String circleStr = "Circle(" + ptStr.replaceAll(" ", "") + " d=" + distDEG + ")";
|
||||
String shapeStr;
|
||||
if (exact) {
|
||||
shapeStr = circleStr;
|
||||
} else {//bbox
|
||||
//the GEO is an assumption
|
||||
SpatialContext ctx = SpatialContext.GEO;
|
||||
shapeStr = ctx.toString( ctx.readShape(circleStr).getBoundingBox() );
|
||||
double distDEG = DistanceUtils.dist2Degrees(distKM, DistanceUtils.EARTH_MEAN_RADIUS_KM);
|
||||
String circleStr = "Circle(" + ptStr.replaceAll(" ", "") + " d=" + distDEG + ")";
|
||||
String shapeStr;
|
||||
if (exact) {
|
||||
shapeStr = circleStr;
|
||||
} else {//bbox
|
||||
//the GEO is an assumption
|
||||
SpatialContext ctx = SpatialContext.GEO;
|
||||
shapeStr = ctx.toString( ctx.readShape(circleStr).getBoundingBox() );
|
||||
}
|
||||
|
||||
//FYI default distErrPct=0.025 works with the tests in this file
|
||||
assertQ(req(
|
||||
"fl", "id", "q","*:*", "rows", "1000",
|
||||
"fq", "{!field f=" + fieldName + (score==null?"":" score="+score)
|
||||
+ "}Intersects(" + shapeStr + ")"),
|
||||
tests);
|
||||
}
|
||||
//Test using the Solr 3 syntax
|
||||
{
|
||||
assertQ(req(
|
||||
"fl", "id", "q", "*:*", "rows", "1000",
|
||||
"fq", "{!" + (exact ? "geofilt" : "bbox") + " sfield=" + fieldName + " pt='" + ptStr + "' d=" + distKM + "}"),
|
||||
tests);
|
||||
}
|
||||
|
||||
//FYI default distErrPct=0.025 works with the tests in this file
|
||||
assertQ(req(
|
||||
"fl", "id", "q","*:*", "rows", "1000",
|
||||
"fq", "{!field f=" + fieldName + (score==null?"":" score="+score)
|
||||
+ "}Intersects(" + shapeStr + ")"),
|
||||
tests);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -203,10 +214,11 @@ public class TestSolr4Spatial extends SolrTestCaseJ4 {
|
|||
//match docId 1
|
||||
int docId = 1;
|
||||
int count = 1;
|
||||
boolean needScore = random().nextBoolean();//never actually need the score but lets test
|
||||
|
||||
String score = random().nextBoolean() ? "none" : "distance";//never actually need the score but lets test
|
||||
assertQ(req(
|
||||
"fl", "id", "q","*:*", "rows", "1000",
|
||||
"fq", "{! needScore="+needScore+" df="+fieldName+"}[32,-80 TO 33,-79]"),//lower-left to upper-right
|
||||
"fq", "{! score="+score+" df="+fieldName+"}[32,-80 TO 33,-79]"),//lower-left to upper-right
|
||||
|
||||
"//result/doc/*[@name='id'][.='" + docId + "']",
|
||||
"*[count(//doc)=" + count + "]");
|
||||
|
|
Loading…
Reference in New Issue