You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by yo...@apache.org on 2010/09/29 19:05:29 UTC
svn commit: r1002739 - in /lucene/dev/trunk/solr: ./
src/java/org/apache/solr/schema/ src/java/org/apache/solr/search/
src/java/org/apache/solr/search/function/
src/java/org/apache/solr/search/function/distance/
src/test/org/apache/solr/search/ src/tes...
Author: yonik
Date: Wed Sep 29 17:05:29 2010
New Revision: 1002739
URL: http://svn.apache.org/viewvc?rev=1002739&view=rev
Log:
SOLR-1568: friendly geodist function
Added:
lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java (with props)
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/src/java/org/apache/solr/schema/LatLonType.java
lucene/dev/trunk/solr/src/java/org/apache/solr/schema/PointType.java
lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SpatialQueryable.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/QParser.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParser.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParserPlugin.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java
lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/VectorValueSource.java
lucene/dev/trunk/solr/src/test/org/apache/solr/search/SpatialFilterTest.java
lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java
lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema11.xml
lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema12.xml
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Wed Sep 29 17:05:29 2010
@@ -95,10 +95,10 @@ New Features
----------------------
* SOLR-1302: Added several new distance based functions, including
- Great Circle (haversine), Manhattan, Euclidean and String (using the
- StringDistance methods in the Lucene spellchecker).
+ Great Circle (haversine) for geo search, Manhattan, Euclidean
+ and String (using the StringDistance methods in the Lucene spellchecker).
Also added geohash(), deg() and rad() convenience functions.
- See http://wiki.apache.org/solr/FunctionQuery. (gsingers)
+ See http://wiki.apache.org/solr/FunctionQuery. (yonik, gsingers)
* SOLR-1553: New dismax parser implementation (accessible as "edismax")
that supports full lucene syntax, improved reserved char escaping,
@@ -130,8 +130,10 @@ New Features
* SOLR-1653: Add PatternReplaceCharFilter (koji)
-* SOLR-1131: FieldTypes can now output multiple Fields per Type and still be searched. This can be handy for hiding the details of a particular
- implementation such as in the spatial case. (Chris Mattmann, shalin, noble, gsingers, yonik)
+* SOLR-1131: FieldTypes can now output multiple Fields per Type and still be
+ searched. This can be handy for hiding the details of a particular
+ implementation such as in the spatial case.
+ (Chris Mattmann, shalin, noble, gsingers, yonik)
* SOLR-1586: Add support for Geohash FieldType (Chris Mattmann, gsingers)
@@ -210,9 +212,10 @@ New Features
* SOLR-1984: Add HyphenationCompoundWordTokenFilterFactory. (PB via rmuir)
-* SOLR-1568: Added "native" filtering support for PointType, GeohashField. Added LatLonType with filtering support too. See
- http://wiki.apache.org/solr/SpatialSearch and the example. Refactored some items in Lucene spatial.
- Removed SpatialTileField as the underlying CartesianTier is broken beyond repair and is going to be moved. (gsingers)
+* SOLR-1568: Added native filtering support via geofilt for spatial field
+ types LatLonType, PointType, GeohashField.
+ See http://wiki.apache.org/solr/SpatialSearch for examples.
+ (yonik, gsingers)
* SOLR-2015: Add a boolean attribute autoGeneratePhraseQueries to TextField.
autoGeneratePhraseQueries="true" (the default) causes the query parser to
@@ -494,8 +497,6 @@ Bug Fixes
substitution/dereferencing. Properly encode local params in
distributed faceting. (yonik)
-* SOLR-2114: Fixed parsing error in hsin function. The function signature has changed slightly. (gsingers)
-
* SOLR-2083: SpellCheckComponent misreports suggestions when distributed (James Dyer via gsingers)
* SOLR-2108: Fixed false positives when using wildcard queries on fields with reversed
@@ -516,8 +517,6 @@ Other Changes
* SOLR-1592: Refactor XMLWriter startTag to allow arbitrary attributes to be written
(Chris A. Mattmann via noble)
-* SOLR-1561: Added Lucene 2.9.1 spatial contrib jar to lib. (gsingers)
-
* SOLR-1570: Log warnings if uniqueKey is multi-valued or not stored (hossman, shalin)
* SOLR-1558: QueryElevationComponent only works if the uniqueKey field is
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/LatLonType.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/LatLonType.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/LatLonType.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/LatLonType.java Wed Sep 29 17:05:29 2010
@@ -43,8 +43,6 @@ import java.util.Set;
/**
* Represents a Latitude/Longitude as a 2 dimensional point. Latitude is <b>always</b> specified first.
- * Can also, optionally, integrate in Spatial Tile capabilities. The default is for tile fields from 4 - 15,
- * just as in the SpatialTileField that we are extending.
*/
public class LatLonType extends AbstractSubTypeFieldType implements SpatialQueryable {
protected static final int LAT = 0;
@@ -511,7 +509,7 @@ class SpatialDistanceQuery extends Query
{
float boost = getBoost();
return (boost!=1.0?"(":"") +
- "sfilt(latlonSource="+origField +"(" + latSource + "," + lonSource + ")"
+ "geofilt(latlonSource="+origField +"(" + latSource + "," + lonSource + ")"
+",latCenter="+latCenter+",lonCenter="+lonCenter
+",dist=" + dist
+",latMin=" + latMin + ",latMax="+latMax
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/PointType.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/PointType.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/PointType.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/PointType.java Wed Sep 29 17:05:29 2010
@@ -41,11 +41,8 @@ import java.util.List;
import java.util.ArrayList;
/**
- * A point type that indexes a point in an n-dimensional space as separate fields and uses
- * range queries for bounding box calculations.
- * <p/>
- * <p/>
- * NOTE: There can only be one sub type
+ * A point type that indexes a point in an n-dimensional space as separate fields and supports range queries.
+ * See {@link LatLonType} for geo-spatial queries.
*/
public class PointType extends CoordinateFieldType implements SpatialQueryable {
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SpatialQueryable.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SpatialQueryable.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SpatialQueryable.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SpatialQueryable.java Wed Sep 29 17:05:29 2010
@@ -25,8 +25,8 @@ import org.apache.solr.search.SpatialOpt
/**
* Indicate that the implementing class is capable of generating a Query against spatial resources.
- * For example, the PointType is capable of creating a query that restricts the document space down
- * to documents that are within a certain distance of a given point. *
+ * For example, the LatLonType is capable of creating a query that restricts the document space down
+ * to documents that are within a certain distance of a given point on Earth. *
*
**/
public interface SpatialQueryable {
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/QParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/QParser.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/QParser.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/QParser.java Wed Sep 29 17:05:29 2010
@@ -152,7 +152,7 @@ public abstract class QParser {
// $x+=foo (append to global for limited scope)
/** check both local and global params */
- protected String getParam(String name) {
+ public String getParam(String name) {
String val;
if (localParams != null) {
val = localParams.get(name);
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParser.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParser.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParser.java Wed Sep 29 17:05:29 2010
@@ -33,24 +33,7 @@ import org.apache.solr.schema.SpatialQue
/**
- * Creates a spatial Filter based on the type of spatial point used.
- * <p/>
- * The field must implement {@link org.apache.solr.schema.SpatialQueryable}
- * <p/>
- * All units are in Kilometers
- * <p/>
- * <p/>
- * Syntax:
- * <pre>{!sfilt fl=location [units=[K|M]] [meas=[0-INF|hsin|sqe]] }&pt=49.32,-79.0&d=20</pre>
- * <p/>
- * Parameters:
- * <ul>
- * <li>fl - The fields to filter on. Must implement XXXX. Required. If more than one, XXXX</li>
- * <li>pt - The point to use as a reference. Must match the dimension of the field. Required.</li>
- * <li>d - The distance in the units specified. Required.</li>
- * <li>meas - The distance measure to use. Default is Euclidean (2-norm). If a number between 0-INF is used, then the Vector Distance is used. hsin = Haversine, sqe = Squared Euclidean</li>
- * </ul> *
- *
+ * @see {@link SpatialFilterQParserPlugin}
*/
public class SpatialFilterQParser extends QParser {
boolean bbox; // do bounding box only
@@ -66,17 +49,17 @@ public class SpatialFilterQParser extend
public Query parse() throws ParseException {
//if more than one, we need to treat them as a point...
//TODO: Should we accept multiple fields
- String[] fields = localParams.getParams(CommonParams.FL);
+ String[] fields = localParams.getParams("f");
if (fields == null || fields.length == 0) {
String field = getParam(SpatialParams.FIELD);
if (field == null)
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, " missing field for spatial request");
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, " missing sfield for spatial request");
fields = new String[] {field};
}
String pointStr = getParam(SpatialParams.POINT);
if (pointStr == null) {
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, SpatialParams.POINT + " is not properly specified");
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, SpatialParams.POINT + " missing.");
}
double dist = -1;
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParserPlugin.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParserPlugin.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/SpatialFilterQParserPlugin.java Wed Sep 29 17:05:29 2010
@@ -21,11 +21,35 @@ import org.apache.solr.common.util.Named
import org.apache.solr.request.SolrQueryRequest;
/**
- * Creates a {@link org.apache.solr.search.QParser} that can create Spatial {@link org.apache.lucene.search.Filter}s.
- * The filters are tied to implementations of {@link org.apache.solr.schema.SpatialQueryable}
+ * Creates a spatial Filter based on the type of spatial point used.
+ * <p/>
+ * The field must implement {@link org.apache.solr.schema.SpatialQueryable}
+ * <p/>
+ * All units are in Kilometers
+ * <p/>
+ * <p/>
+ * Syntax:
+ * <pre>{!geofilt sfield=<location_field> pt=<lat,lon> d=<distance>}</pre>
+ * <p/>
+ * Parameters:
+ * <ul>
+ * <li>sfield - The field to filter on. Required.</li>
+ * <li>pt - The point to use as a reference. Must match the dimension of the field. Required.</li>
+ * <li>d - The distance in km. Requited.</li>
+ * </ul>
+ * The distance measure used currently depends on the FieldType. LatLonType defaults to using haversine, PointType defaults to Euclidean (2-norm).
+ *
+ * <p/>
+ * Examples:
+ * <pre>fq={!geofilt sfield=store pt=10.312,-20.556 d=3.5}</pre>
+ * <pre>fq={!geofilt sfield=store}&pt=10.312,-20&d=3.5</pre>
+ * <pre>fq={!geofilt}&sfield=store&pt=10.312,-20&d=3.5</pre>
+ * <p/>
+ * Note: The geofilt for LatLonType is capable of also producing scores equal to the computed distance from the point
+ * to the field, making it useful as a component of the main query or a boosting query.
*/
public class SpatialFilterQParserPlugin extends QParserPlugin {
- public static String NAME = "sfilt";
+ public static String NAME = "geofilt";
@Override
public QParser createParser(String qstr, SolrParams localParams,
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/ValueSourceParser.java Wed Sep 29 17:05:29 2010
@@ -38,12 +38,7 @@ import org.apache.solr.search.function.d
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Collections;
+import java.util.*;
/**
* A factory that parses user queries to generate ValueSource instances.
@@ -236,7 +231,9 @@ public abstract class ValueSourceParser
return new JoinDocFreqValueSource( f0, qf );
}
});
-
+
+ addParser("geodist", HaversineConstFunction.parser);
+
addParser("hsin", new ValueSourceParser() {
public ValueSource parse(FunctionQParser fp) throws ParseException {
@@ -699,7 +696,7 @@ class DateValueSourceParser extends Valu
// Private for now - we need to revisit how to handle typing in function queries
-class LongConstValueSource extends ValueSource {
+class LongConstValueSource extends ConstNumberSource {
final long constant;
final double dv;
final float fv;
@@ -751,61 +748,30 @@ class LongConstValueSource extends Value
LongConstValueSource other = (LongConstValueSource) o;
return this.constant == other.constant;
}
-}
-// Private for now - we need to revisit how to handle typing in function queries
-class DoubleConstValueSource extends ValueSource {
- final double constant;
- private final float fv;
- private final long lv;
-
- public DoubleConstValueSource(double constant) {
- this.constant = constant;
- this.fv = (float)constant;
- this.lv = (long)constant;
+ @Override
+ public int getInt() {
+ return (int)constant;
}
- public String description() {
- return "const(" + constant + ")";
+ @Override
+ public long getLong() {
+ return constant;
}
- public DocValues getValues(Map context, IndexReader reader) throws IOException {
- return new DocValues() {
- public float floatVal(int doc) {
- return fv;
- }
-
- public int intVal(int doc) {
- return (int) lv;
- }
-
- public long longVal(int doc) {
- return lv;
- }
-
- public double doubleVal(int doc) {
- return constant;
- }
-
- public String strVal(int doc) {
- return Double.toString(constant);
- }
-
- public String toString(int doc) {
- return description();
- }
- };
+ @Override
+ public float getFloat() {
+ return fv;
}
- public int hashCode() {
- long bits = Double.doubleToRawLongBits(constant);
- return (int)(bits ^ (bits >>> 32));
+ @Override
+ public double getDouble() {
+ return dv;
}
- public boolean equals(Object o) {
- if (DoubleConstValueSource.class != o.getClass()) return false;
- DoubleConstValueSource other = (DoubleConstValueSource) o;
- return this.constant == other.constant;
+ @Override
+ public Number getNumber() {
+ return constant;
}
}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java?rev=1002739&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java Wed Sep 29 17:05:29 2010
@@ -0,0 +1,34 @@
+/**
+ * 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.search.function;
+
+import org.apache.lucene.index.IndexReader;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <code>ConstNumberSource</code> is the base class for all constant numbers
+ */
+public abstract class ConstNumberSource extends ValueSource {
+ public abstract int getInt();
+ public abstract long getLong();
+ public abstract float getFloat();
+ public abstract double getDouble();
+ public abstract Number getNumber();
+}
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstNumberSource.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/ConstValueSource.java Wed Sep 29 17:05:29 2010
@@ -25,7 +25,7 @@ import java.util.Map;
/**
* <code>ConstValueSource</code> returns a constant for all documents
*/
-public class ConstValueSource extends ValueSource {
+public class ConstValueSource extends ConstNumberSource {
final float constant;
private final double dv;
@@ -66,8 +66,33 @@ public class ConstValueSource extends Va
}
public boolean equals(Object o) {
- if (ConstValueSource.class != o.getClass()) return false;
+ if (!(o instanceof ConstValueSource)) return false;
ConstValueSource other = (ConstValueSource)o;
return this.constant == other.constant;
}
+
+ @Override
+ public int getInt() {
+ return (int)constant;
+ }
+
+ @Override
+ public long getLong() {
+ return (long)constant;
+ }
+
+ @Override
+ public float getFloat() {
+ return constant;
+ }
+
+ @Override
+ public double getDouble() {
+ return dv;
+ }
+
+ @Override
+ public Number getNumber() {
+ return constant;
+ }
}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java?rev=1002739&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java Wed Sep 29 17:05:29 2010
@@ -0,0 +1,103 @@
+/**
+ * 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.search.function;
+
+import org.apache.lucene.index.IndexReader;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class DoubleConstValueSource extends ConstNumberSource {
+ final double constant;
+ private final float fv;
+ private final long lv;
+
+ public DoubleConstValueSource(double constant) {
+ this.constant = constant;
+ this.fv = (float)constant;
+ this.lv = (long)constant;
+ }
+
+ public String description() {
+ return "const(" + constant + ")";
+ }
+
+ public DocValues getValues(Map context, IndexReader reader) throws IOException {
+ return new DocValues() {
+ public float floatVal(int doc) {
+ return fv;
+ }
+
+ public int intVal(int doc) {
+ return (int) lv;
+ }
+
+ public long longVal(int doc) {
+ return lv;
+ }
+
+ public double doubleVal(int doc) {
+ return constant;
+ }
+
+ public String strVal(int doc) {
+ return Double.toString(constant);
+ }
+
+ public String toString(int doc) {
+ return description();
+ }
+ };
+ }
+
+ public int hashCode() {
+ long bits = Double.doubleToRawLongBits(constant);
+ return (int)(bits ^ (bits >>> 32));
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof DoubleConstValueSource)) return false;
+ DoubleConstValueSource other = (DoubleConstValueSource) o;
+ return this.constant == other.constant;
+ }
+
+ @Override
+ public int getInt() {
+ return (int)lv;
+ }
+
+ @Override
+ public long getLong() {
+ return lv;
+ }
+
+ @Override
+ public float getFloat() {
+ return fv;
+ }
+
+ @Override
+ public double getDouble() {
+ return constant;
+ }
+
+ @Override
+ public Number getNumber() {
+ return constant;
+ }
+}
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/DoubleConstValueSource.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/VectorValueSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/VectorValueSource.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/VectorValueSource.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/VectorValueSource.java Wed Sep 29 17:05:29 2010
@@ -33,7 +33,7 @@ import java.util.Map;
*/
//Not crazy about the name, but...
public class VectorValueSource extends MultiValueSource {
- protected List<ValueSource> sources;
+ protected final List<ValueSource> sources;
public VectorValueSource(List<ValueSource> sources) {
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java?rev=1002739&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java Wed Sep 29 17:05:29 2010
@@ -0,0 +1,266 @@
+package org.apache.solr.search.function.distance;
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.spatial.DistanceUtils;
+import org.apache.lucene.spatial.tier.InvalidGeoException;
+import org.apache.solr.common.params.SpatialParams;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.search.FunctionQParser;
+import org.apache.solr.search.ValueSourceParser;
+import org.apache.solr.search.function.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Haversine function with one point constant
+ */
+public class HaversineConstFunction extends ValueSource {
+
+ public static ValueSourceParser parser = new ValueSourceParser() {
+ public ValueSource parse(FunctionQParser fp) throws ParseException
+ {
+ // TODO: dispatch through SpatialQueriable in the future?
+ List<ValueSource> sources = fp.parseValueSourceList();
+
+ // "m" is a multi-value source, "x" is a single-value source
+ // allow (m,m) (m,x,x) (x,x,m) (x,x,x,x)
+ // if not enough points are present, "pt" will be checked first, followed by "sfield".
+
+ MultiValueSource mv1 = null;
+ MultiValueSource mv2 = null;
+
+ if (sources.size() == 0) {
+ // nothing to do now
+ } else if (sources.size() == 1) {
+ ValueSource vs = sources.get(0);
+ if (!(vs instanceof MultiValueSource)) {
+ throw new ParseException("geodist - invalid parameters:" + sources);
+ }
+ mv1 = (MultiValueSource)vs;
+ } else if (sources.size() == 2) {
+ ValueSource vs1 = sources.get(0);
+ ValueSource vs2 = sources.get(1);
+
+ if (vs1 instanceof MultiValueSource && vs2 instanceof MultiValueSource) {
+ mv1 = (MultiValueSource)vs1;
+ mv2 = (MultiValueSource)vs2;
+ } else {
+ mv1 = makeMV(sources, sources);
+ }
+ } else if (sources.size()==3) {
+ ValueSource vs1 = sources.get(0);
+ ValueSource vs2 = sources.get(1);
+ if (vs1 instanceof MultiValueSource) { // (m,x,x)
+ mv1 = (MultiValueSource)vs1;
+ mv2 = makeMV(sources.subList(1,3), sources);
+ } else { // (x,x,m)
+ mv1 = makeMV(sources.subList(0,2), sources);
+ vs1 = sources.get(2);
+ if (!(vs1 instanceof MultiValueSource)) {
+ throw new ParseException("geodist - invalid parameters:" + sources);
+ }
+ mv2 = (MultiValueSource)vs1;
+ }
+ } else if (sources.size()==4) {
+ mv1 = makeMV(sources.subList(0,2), sources);
+ mv2 = makeMV(sources.subList(2,4), sources);
+ } else if (sources.size() > 4) {
+ throw new ParseException("geodist - invalid parameters:" + sources);
+ }
+
+ if (mv1 == null) {
+ mv1 = parsePoint(fp);
+ mv2 = parseSfield(fp);
+ } else if (mv2 == null) {
+ mv2 = parsePoint(fp);
+ if (mv2 == null)
+ mv2 = parseSfield(fp);
+ }
+
+ if (mv1 == null || mv2 == null) {
+ throw new ParseException("geodist - not enough parameters:" + sources);
+ }
+
+ // We have all the parameters at this point, now check if one of the points is constant
+ double[] constants;
+ constants = getConstants(mv1);
+ MultiValueSource other = mv2;
+ if (constants == null) {
+ constants = getConstants(mv2);
+ other = mv1;
+ }
+
+ if (constants != null && other instanceof VectorValueSource) {
+ return new HaversineConstFunction(constants[0], constants[1], (VectorValueSource)other);
+ }
+
+ return new HaversineFunction(mv1, mv2, DistanceUtils.EARTH_MEAN_RADIUS_KM, true);
+ }
+ };
+
+ /** make a MultiValueSource from two non MultiValueSources */
+ private static VectorValueSource makeMV(List<ValueSource> sources, List<ValueSource> orig) throws ParseException {
+ ValueSource vs1 = sources.get(0);
+ ValueSource vs2 = sources.get(1);
+
+ if (vs1 instanceof MultiValueSource || vs2 instanceof MultiValueSource) {
+ throw new ParseException("geodist - invalid parameters:" + orig);
+ }
+ return new VectorValueSource(sources);
+ }
+
+ private static MultiValueSource parsePoint(FunctionQParser fp) throws ParseException {
+ String pt = fp.getParam(SpatialParams.POINT);
+ if (pt == null) return null;
+ double[] point = null;
+ try {
+ point = DistanceUtils.parseLatitudeLongitude(pt);
+ } catch (InvalidGeoException e) {
+ throw new ParseException("Bad spatial pt:" + pt);
+ }
+ return new VectorValueSource(Arrays.asList(new ValueSource[] {new DoubleConstValueSource(point[0]),new DoubleConstValueSource(point[1])}));
+ }
+
+ private static double[] getConstants(MultiValueSource vs) {
+ if (!(vs instanceof VectorValueSource)) return null;
+ List<ValueSource> sources = ((VectorValueSource)vs).getSources();
+ if (sources.get(0) instanceof ConstNumberSource && sources.get(1) instanceof ConstNumberSource) {
+ return new double[] { ((ConstNumberSource) sources.get(0)).getDouble(), ((ConstNumberSource) sources.get(1)).getDouble()};
+ }
+ return null;
+ }
+
+ private static MultiValueSource parseSfield(FunctionQParser fp) throws ParseException {
+ String sfield = fp.getParam(SpatialParams.FIELD);
+ if (sfield == null) return null;
+ SchemaField sf = fp.getReq().getSchema().getField(sfield);
+ ValueSource vs = sf.getType().getValueSource(sf, fp);
+ if (!(vs instanceof MultiValueSource)) {
+ throw new ParseException("Spatial field must implement MultiValueSource:" + sf);
+ }
+ return (MultiValueSource)vs;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ private final double latCenter;
+ private final double lonCenter;
+ private final VectorValueSource p2; // lat+lon, just saved for display/debugging
+ private final ValueSource latSource;
+ private final ValueSource lonSource;
+
+ private final double latCenterRad_cos; // cos(latCenter)
+ private static final double EARTH_MEAN_DIAMETER = DistanceUtils.EARTH_MEAN_RADIUS_KM * 2;
+
+
+ public HaversineConstFunction(double latCenter, double lonCenter, VectorValueSource vs) {
+ this.latCenter = latCenter;
+ this.lonCenter = lonCenter;
+ this.p2 = vs;
+ this.latSource = p2.getSources().get(0);
+ this.lonSource = p2.getSources().get(1);
+ this.latCenterRad_cos = Math.cos(latCenter * DistanceUtils.DEGREES_TO_RADIANS);
+ }
+
+ protected String name() {
+ return "geodist";
+ }
+
+ @Override
+ public DocValues getValues(Map context, IndexReader reader) throws IOException {
+ final DocValues latVals = latSource.getValues(context, reader);
+ final DocValues lonVals = lonSource.getValues(context, reader);
+ final double latCenterRad = this.latCenter * DistanceUtils.DEGREES_TO_RADIANS;
+ final double lonCenterRad = this.lonCenter * DistanceUtils.DEGREES_TO_RADIANS;
+ final double latCenterRad_cos = this.latCenterRad_cos;
+
+ return new DocValues() {
+ public float floatVal(int doc) {
+ return (float) doubleVal(doc);
+ }
+
+ public int intVal(int doc) {
+ return (int) doubleVal(doc);
+ }
+
+ public long longVal(int doc) {
+ return (long) doubleVal(doc);
+ }
+
+ public double doubleVal(int doc) {
+ double latRad = latVals.doubleVal(doc) * DistanceUtils.DEGREES_TO_RADIANS;
+ double lonRad = lonVals.doubleVal(doc) * DistanceUtils.DEGREES_TO_RADIANS;
+ double diffX = latCenterRad - latRad;
+ double diffY = lonCenterRad - lonRad;
+ double hsinX = Math.sin(diffX * 0.5);
+ double hsinY = Math.sin(diffY * 0.5);
+ double h = hsinX * hsinX +
+ (latCenterRad_cos * Math.cos(latRad) * hsinY * hsinY);
+ return (EARTH_MEAN_DIAMETER * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h)));
+ }
+
+ public String strVal(int doc) {
+ return Double.toString(doubleVal(doc));
+ }
+
+ @Override
+ public String toString(int doc) {
+ return name() + '(' + latVals.toString(doc) + ',' + lonVals.toString(doc) + ',' + latCenter + ',' + lonCenter + ')';
+ }
+ };
+ }
+
+ @Override
+ public void createWeight(Map context, Searcher searcher) throws IOException {
+ latSource.createWeight(context, searcher);
+ lonSource.createWeight(context, searcher);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof HaversineConstFunction)) return false;
+ HaversineConstFunction other = (HaversineConstFunction) o;
+ return this.latCenter == other.latCenter
+ && this.lonCenter == other.lonCenter
+ && this.p2.equals(other.p2);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = p2.hashCode();
+ long temp;
+ temp = Double.doubleToRawLongBits(latCenter);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToRawLongBits(lonCenter);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+
+ public String description() {
+ return name() + '(' + p2 + ',' + latCenter + ',' + lonCenter + ')';
+ }
+}
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: lucene/dev/trunk/solr/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/search/SpatialFilterTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/search/SpatialFilterTest.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/search/SpatialFilterTest.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/search/SpatialFilterTest.java Wed Sep 29 17:05:29 2010
@@ -134,9 +134,9 @@ public class SpatialFilterTest extends S
}
}
- String method = exact ? "sfilt" : "bbox";
+ String method = exact ? "geofilt" : "bbox";
- assertQ(req("fl", "id", "q","*:*", "rows", "1000", "fq", "{!"+method+" fl=" +fieldName +"}",
+ assertQ(req("fl", "id", "q","*:*", "rows", "1000", "fq", "{!"+method+" sfield=" +fieldName +"}",
"pt", pt, "d", String.valueOf(distance)),
tests);
}
Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java Wed Sep 29 17:05:29 2010
@@ -32,7 +32,7 @@ import static org.junit.Assert.*;
public class DistanceFunctionTest extends SolrTestCaseJ4 {
@BeforeClass
public static void beforeClass() throws Exception {
- initCore("solrconfig-functionquery.xml", "schema11.xml");
+ initCore("solrconfig.xml", "schema12.xml");
}
@Test
@@ -63,8 +63,8 @@ public class DistanceFunctionTest extend
assertQ(req("fl", "id,point_hash,score", "q", "{!func}recip(ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", point_hash, \"" + GeoHashUtils.encode(32, -79) + "\"), 1, 1, 0)"),
"//*[@numFound='7']",
- "//result/doc[1]/float[@name='id'][.='6.0']",
- "//result/doc[2]/float[@name='id'][.='7.0']"//all the rest don't matter
+ "//result/doc[1]/str[@name='id'][.='6']",
+ "//result/doc[2]/str[@name='id'][.='7']"//all the rest don't matter
);
@@ -72,6 +72,49 @@ public class DistanceFunctionTest extend
}
+
+ @Test
+ public void testLatLon() throws Exception {
+ assertU(adoc("id", "100", "store", "1,2"));
+ assertU(commit());
+
+ assertJQ(req("defType","func", "q","geodist(1,2,3,4)","fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ // throw in some decimal points
+ assertJQ(req("defType","func", "q","geodist(1.0,2,3,4.0)","fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ // default to reading pt
+ assertJQ(req("defType","func", "q","geodist(1,2)","pt","3,4", "fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ // default to reading pt first
+ assertJQ(req("defType","func", "q","geodist(1,2)","pt","3,4", "sfield","store", "fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ // if pt missing, use sfield
+ assertJQ(req("defType","func", "q","geodist(3,4)","sfield","store", "fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ // read both pt and sfield
+ assertJQ(req("defType","func", "q","geodist()","pt","3,4","sfield","store", "fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ // param substitution
+ assertJQ(req("defType","func", "q","geodist($a,$b)","a","3,4","b","store", "fq","id:100","fl","id,score")
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
+ }
+
+
@Test
public void testVector() throws Exception {
clearIndex();
Modified: lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema11.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema11.xml?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema11.xml (original)
+++ lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema11.xml Wed Sep 29 17:05:29 2010
@@ -257,9 +257,15 @@
<!-- Poly field -->
<fieldType name="xy" class="solr.PointType" dimension="2" subFieldType="double"/>
<fieldType name="xyd" class="solr.PointType" dimension="2" subFieldSuffix="*_d"/>
-
<fieldtype name="geohash" class="solr.GeoHashField"/>
+ <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+ <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multi
+valued. -->
+ <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
+
</types>
Modified: lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema12.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema12.xml?rev=1002739&r1=1002738&r2=1002739&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema12.xml (original)
+++ lucene/dev/trunk/solr/src/test/test-files/solr/conf/schema12.xml Wed Sep 29 17:05:29 2010
@@ -418,6 +418,15 @@
<fieldType name="random" class="solr.RandomSortField" indexed="true" />
+ <!-- Poly field -->
+ <fieldType name="xy" class="solr.PointType" dimension="2" subFieldType="double"/>
+ <fieldType name="xyd" class="solr.PointType" dimension="2" subFieldSuffix="*_d"/>
+ <fieldtype name="geohash" class="solr.GeoHashField"/>
+
+ <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+ <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
+ <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
</types>
@@ -508,7 +517,12 @@
-->
<field name="timestamp" type="date" indexed="true" stored="true"/>
-
+ <!-- Test a point field for distances -->
+ <field name="point" type="xy" indexed="true" stored="true" multiValued="false"/>
+ <field name="pointD" type="xyd" indexed="true" stored="true" multiValued="false"/>
+ <field name="point_hash" type="geohash" indexed="true" stored="true" multiValued="false"/>
+ <field name="store" type="location" indexed="true" stored="true"/>
+ <dynamicField name="*_coordinate" type="tdouble" indexed="true" stored="false"/>
<dynamicField name="*_si" type="sint" indexed="true" stored="true"/>