You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ds...@apache.org on 2013/07/26 21:37:14 UTC
svn commit: r1507409 - in /lucene/dev/trunk/solr: ./
core/src/java/org/apache/solr/search/function/distance/
core/src/test-files/solr/collection1/conf/
core/src/test/org/apache/solr/search/function/distance/
Author: dsmiley
Date: Fri Jul 26 19:37:14 2013
New Revision: 1507409
URL: http://svn.apache.org/r1507409
Log:
SOLR-2345: geodist support for RPT
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/function/distance/GeoDistValueSourceParser.java
lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema12.xml
lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1507409&r1=1507408&r2=1507409&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Fri Jul 26 19:37:14 2013
@@ -64,13 +64,20 @@ Upgrading from Solr 4.4.0
Detailed Change List
----------------------
+New Features
+----------------------
+
+* SOLR-2345: Enhanced geodist() to work with an RPT field, provided that the
+ field is referenced via 'sfield' and the query point is constant.
+ (David Smiley)
+
Bug Fixes
----------------------
-* SOLR-3633 - web UI reports an error if CoreAdminHandler says there are no
+* SOLR-3633: web UI reports an error if CoreAdminHandler says there are no
SolrCores (steffkes)
-* SOLR-4489 - SpellCheckComponent can throw StringIndexOutOfBoundsException
+* SOLR-4489: SpellCheckComponent can throw StringIndexOutOfBoundsException
when generating collations involving multiple word-break corrections.
(James Dyer)
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/function/distance/GeoDistValueSourceParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/function/distance/GeoDistValueSourceParser.java?rev=1507409&r1=1507408&r2=1507409&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/function/distance/GeoDistValueSourceParser.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/function/distance/GeoDistValueSourceParser.java Fri Jul 26 19:37:14 2013
@@ -20,28 +20,37 @@ package org.apache.solr.search.function.
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 org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.ConstNumberSource;
import org.apache.lucene.queries.function.valuesource.DoubleConstValueSource;
import org.apache.lucene.queries.function.valuesource.MultiValueSource;
import org.apache.lucene.queries.function.valuesource.VectorValueSource;
+import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.solr.common.params.SpatialParams;
+import org.apache.solr.schema.AbstractSpatialFieldType;
+import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.FunctionQParser;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.ValueSourceParser;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
- * Parses "geodist" creating {@link HaversineConstFunction} or {@link HaversineFunction}.
+ * Parses "geodist" creating {@link HaversineConstFunction} or {@link HaversineFunction}
+ * or calling {@link SpatialStrategy#makeDistanceValueSource(com.spatial4j.core.shape.Point,double)}.
*/
public class GeoDistValueSourceParser extends ValueSourceParser {
@Override
public ValueSource parse(FunctionQParser fp) throws SyntaxError {
// TODO: dispatch through SpatialQueryable in the future?
+
+ //note: parseValueSourceList can't handle a field reference to an AbstractSpatialFieldType,
+ // so those fields are expressly handled via sfield=
List<ValueSource> sources = fp.parseValueSourceList();
// "m" is a multi-value source, "x" is a single-value source
@@ -104,7 +113,7 @@ public class GeoDistValueSourceParser ex
}
// We have all the parameters at this point, now check if one of the points is constant
- double[] constants;
+ double[] constants;//latLon
constants = getConstants(mv1);
MultiValueSource other = mv2;
if (constants == null) {
@@ -112,6 +121,24 @@ public class GeoDistValueSourceParser ex
other = mv1;
}
+ // At this point we dispatch to one of:
+ // * SpatialStrategy.makeDistanceValueSource
+ // * HaversineConstFunction
+ // * HaversineFunction
+
+ // sfield can only be in mv2, according to the logic above
+ if (mv2 instanceof SpatialStrategyMultiValueSource) {
+ if (constants == null)
+ throw new SyntaxError("When using AbstractSpatialFieldType (e.g. RPT not LatLonType)," +
+ " the point must be supplied as constants");
+ // note: uses Haversine by default but can be changed via distCalc=...
+ SpatialStrategy strategy = ((SpatialStrategyMultiValueSource) mv2).strategy;
+ Point queryPoint = strategy.getSpatialContext().makePoint(constants[1], constants[0]);
+ //TODO Spatial4j 0.4 will have a direct constant
+ double multiplier = DistanceUtils.degrees2Dist(1, DistanceUtils.EARTH_MEAN_RADIUS_KM);
+ return strategy.makeDistanceValueSource(queryPoint, multiplier);
+ }
+
if (constants != null && other instanceof VectorValueSource) {
return new HaversineConstFunction(constants[0], constants[1], (VectorValueSource)other);
}
@@ -155,11 +182,33 @@ public class GeoDistValueSourceParser ex
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 SyntaxError("Spatial field must implement MultiValueSource:" + sf);
+ FieldType type = sf.getType();
+ if (type instanceof AbstractSpatialFieldType) {
+ AbstractSpatialFieldType asft = (AbstractSpatialFieldType) type;
+ return new SpatialStrategyMultiValueSource(asft.getStrategy(sfield));
+ }
+ ValueSource vs = type.getValueSource(sf, fp);
+ if (vs instanceof MultiValueSource) {
+ return (MultiValueSource)vs;
+ }
+ throw new SyntaxError("Spatial field must implement MultiValueSource or extend AbstractSpatialFieldType:" + sf);
+ }
+
+ /** An unfortunate hack to use a {@link SpatialStrategy} instead of
+ * a ValueSource. */
+ private static class SpatialStrategyMultiValueSource extends VectorValueSource {
+
+ final SpatialStrategy strategy;
+
+ public SpatialStrategyMultiValueSource(SpatialStrategy strategy) {
+ super(Collections.EMPTY_LIST);
+ this.strategy = strategy;
+ }
+
+ @Override
+ public List<ValueSource> getSources() {
+ throw new IllegalStateException();
}
- return (MultiValueSource)vs;
}
}
Modified: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema12.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema12.xml?rev=1507409&r1=1507408&r2=1507409&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema12.xml (original)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema12.xml Fri Jul 26 19:37:14 2013
@@ -420,6 +420,9 @@
<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"/>
+ <!-- sub-centimeter accuracy for RPT; distance calcs -->
+ <fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
+ geo="true" distErrPct="0.025" maxDistErr="0.00000009" units="degrees" />
<fieldType name="currency" class="solr.CurrencyField" currencyConfig="currency.xml" multiValued="false" />
</types>
@@ -517,6 +520,7 @@
<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"/>
+ <field name="store_rpt" type="location_rpt" indexed="true" stored="false" />
<!-- Test currency field -->
<field name="amount_c" type="currency" indexed="true" stored="true" multiValued="false"/>
@@ -609,5 +613,6 @@
<copyField source="subject" dest="text"/>
<copyField source="foo_copysource_*" dest="bar_copydest_*" />
+ <copyField source="store" dest="store_rpt" />
</schema>
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java?rev=1507409&r1=1507408&r2=1507409&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java Fri Jul 26 19:37:14 2013
@@ -76,7 +76,7 @@ public class DistanceFunctionTest extend
@Test
public void testLatLon() throws Exception {
- assertU(adoc("id", "100", "store", "1,2"));
+ assertU(adoc("id", "100", "store", "1,2"));//copied to store_rpt
assertU(commit());
assertJQ(req("defType","func",
@@ -126,6 +126,16 @@ public class DistanceFunctionTest extend
, 1e-5
,"/response/docs/[0]/score==314.40338"
);
+
+ // if pt missing, use sfield (RPT)
+ assertJQ(req("defType","func",
+ "q","geodist(3,4)",
+ "sfield","store_rpt",
+ "fq","id:100",
+ "fl","id,score")
+ , 1e-5
+ ,"/response/docs/[0]/score==314.40338"
+ );
// read both pt and sfield
assertJQ(req("defType","func",
@@ -137,6 +147,16 @@ public class DistanceFunctionTest extend
,"/response/docs/[0]/score==314.40338"
);
+ // read both pt and sfield (RPT)
+ assertJQ(req("defType","func",
+ "q","geodist()","pt","3,4",
+ "sfield","store_rpt",
+ "fq","id:100",
+ "fl","id,score")
+ , 1e-5
+ ,"/response/docs/[0]/score==314.40338"
+ );
+
// param substitution
assertJQ(req("defType","func",
"q","geodist($a,$b)",