lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dsmi...@apache.org
Subject lucene-solr:branch_7x: SOLR-11382: Solr support for Lucene spatial Geo3D.
Date Sat, 23 Sep 2017 15:06:01 GMT
Repository: lucene-solr
Updated Branches:
  refs/heads/branch_7x 9c2c4bdb9 -> 058429f41


SOLR-11382: Solr support for Lucene spatial Geo3D.

(cherry picked from commit d6fa057)


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/058429f4
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/058429f4
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/058429f4

Branch: refs/heads/branch_7x
Commit: 058429f410e1fe9accdf9ff186ac5ae799a704dc
Parents: 9c2c4bd
Author: David Smiley <dsmiley@apache.org>
Authored: Sat Sep 23 11:03:39 2017 -0400
Committer: David Smiley <dsmiley@apache.org>
Committed: Sat Sep 23 11:05:55 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  3 +
 .../solr/schema/AbstractSpatialFieldType.java   |  5 ++
 .../solr/collection1/conf/schema-spatial.xml    |  4 ++
 .../collection1/conf/solrconfig-spatial.xml     |  6 ++
 .../solr/schema/SpatialRPTFieldTypeTest.java    | 12 ++--
 .../apache/solr/search/TestSolr4Spatial2.java   | 21 ++++++-
 solr/solr-ref-guide/src/spatial-search.adoc     | 65 +++++++++++++++++---
 7 files changed, 100 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 4798ccf..a93e627 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -71,6 +71,9 @@ New Features
 * SOLR-11316: JSON Facet API: min/max aggregations are now supported on single-valued date
fields.
   (yonik)
 
+* SOLR-11382: Lucene's Geo3D (surface of sphere & ellipsoid) is now supported on spatial
RPT fields by
+  setting spatialContextFactory="Geo3D".  Furthermore, this is the first time Solr has out
of the box
+  support for polygons. (David Smiley)
 
 Bug Fixes
 ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java b/solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java
index 2cd1c16..404dae2 100644
--- a/solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java
@@ -46,6 +46,7 @@ import org.apache.lucene.spatial.SpatialStrategy;
 import org.apache.lucene.spatial.query.SpatialArgs;
 import org.apache.lucene.spatial.query.SpatialArgsParser;
 import org.apache.lucene.spatial.query.SpatialOperation;
+import org.apache.lucene.spatial.spatial4j.Geo3dSpatialContextFactory;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.response.TextResponseWriter;
@@ -131,6 +132,10 @@ public abstract class AbstractSpatialFieldType<T extends SpatialStrategy>
extend
           argEntry.setValue("org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory");
           continue;
         }
+        if (argEntry.getKey().equals(CTX_PARAM) && argEntry.getValue().equals("Geo3D"))
{
+          argEntry.setValue(Geo3dSpatialContextFactory.class.getName());
+          continue;
+        }
         // Warn about using old Spatial4j class names
         if (argEntry.getValue().contains(OLD_SPATIAL4J_PREFIX)) {
           log.warn("Replace '" + OLD_SPATIAL4J_PREFIX + "' with '" + NEW_SPATIAL4J_PREFIX
+ "' in your schema.");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/core/src/test-files/solr/collection1/conf/schema-spatial.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-spatial.xml b/solr/core/src/test-files/solr/collection1/conf/schema-spatial.xml
index 9b482bd..19b2d9c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-spatial.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-spatial.xml
@@ -56,6 +56,9 @@
 
   <fieldType name="srptgeom" class="solr.RptWithGeometrySpatialField"/>
 
+  <fieldType name="srptgeom_geo3d" class="solr.RptWithGeometrySpatialField"
+             spatialContextFactory="Geo3D" planetModel="wgs84"/><!-- or sphere -->
+
   <fieldType name="bbox" class="solr.BBoxField"
              numberType="tdoubleDV" distanceUnits="degrees" storeSubFields="false"/>
 
@@ -75,6 +78,7 @@
   <field name="stqpt_geohash" type="stqpt_geohash" multiValued="true"/>
   <field name="pointvector" type="pointvector"/>
   <field name="srptgeom" type="srptgeom"/>
+  <field name="srptgeom_geo3d" type="srptgeom_geo3d"/>
   <field name="bbox" type="bbox"/>
   <field name="pbbox" type="pbbox"/>
   <field name="bbox_ndv" type="bbox_ndv"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
index 646a9eb..968575a 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
@@ -32,5 +32,11 @@
            initialSize="0"
            autowarmCount="100%"
            regenerator="solr.NoOpRegenerator"/>
+    <cache name="perSegSpatialFieldCache_srptgeom_geo3d"
+           class="solr.LRUCache"
+           size="3"
+           initialSize="0"
+           autowarmCount="100%"
+           regenerator="solr.NoOpRegenerator"/>
   </query>
 </config>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/core/src/test/org/apache/solr/schema/SpatialRPTFieldTypeTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/SpatialRPTFieldTypeTest.java b/solr/core/src/test/org/apache/solr/schema/SpatialRPTFieldTypeTest.java
index 0ff9e3a..60e47ca 100644
--- a/solr/core/src/test/org/apache/solr/schema/SpatialRPTFieldTypeTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/SpatialRPTFieldTypeTest.java
@@ -76,16 +76,16 @@ public class SpatialRPTFieldTypeTest extends AbstractBadConfigTestBase
{
     assertU(commit());
     String q;
     
-    q = "geo:{!geofilt score=distance filter=false sfield=geo pt="+QUERY_COORDINATES+" d=1000}";
+    q = "geo:{!geofilt score=distance filter=false sfield=geo pt="+QUERY_COORDINATES+" d=180}";
     assertQ(req("q", q, "fl", "*,score"), "//result/doc/float[@name='score'][.='"+DISTANCE_DEGREES+"']");
     
-    q = "geo:{!geofilt score=degrees filter=false sfield=geo pt="+QUERY_COORDINATES+" d=1000}";
+    q = "geo:{!geofilt score=degrees filter=false sfield=geo pt="+QUERY_COORDINATES+" d=180}";
     assertQ(req("q", q, "fl", "*,score"), "//result/doc/float[@name='score'][.='"+DISTANCE_DEGREES+"']");
     
-    q = "geo:{!geofilt score=kilometers filter=false sfield=geo pt="+QUERY_COORDINATES+"
d=1000}";
+    q = "geo:{!geofilt score=kilometers filter=false sfield=geo pt="+QUERY_COORDINATES+"
d=180}";
     assertQ(req("q", q, "fl", "*,score"), "//result/doc/float[@name='score'][.='"+DISTANCE_KILOMETERS+"']");
     
-    q = "geo:{!geofilt score=miles filter=false sfield=geo pt="+QUERY_COORDINATES+" d=1000}";
+    q = "geo:{!geofilt score=miles filter=false sfield=geo pt="+QUERY_COORDINATES+" d=180}";
     assertQ(req("q", q, "fl", "*,score"), "//result/doc/float[@name='score'][.='"+DISTANCE_MILES+"']");
   }
   
@@ -264,6 +264,10 @@ public class SpatialRPTFieldTypeTest extends AbstractBadConfigTestBase
{
     if(format!=null) {
       rptMap.put("format", format);
     }
+    if (random().nextBoolean()) {
+      // use Geo3D sometimes
+      rptMap.put("spatialContextFactory", "Geo3D");
+    }
     fieldType.init(oldSchema, rptMap);
     fieldType.setTypeName("location_rpt");
     SchemaField newField = new SchemaField("geo", fieldType, SchemaField.STORED | SchemaField.INDEXED,
null);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
index b909f15..5cdb170 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolr4Spatial2.java
@@ -103,7 +103,22 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
 
   @Test
   public void testRptWithGeometryField() throws Exception {
-    String fieldName = "srptgeom"; //note: fails with "srpt_geohash" because it's not as
precise
+    testRptWithGeometryField("srptgeom");//note: fails with "srpt_geohash" because it's not
as precise
+  }
+
+  @Test
+  public void testRptWithGeometryGeo3dField() throws Exception {
+    String fieldName = "srptgeom_geo3d";
+    testRptWithGeometryField(fieldName);
+
+    // show off that Geo3D supports polygons
+    String polygonWKT = "POLYGON((-11 12, 10.5 12, -11 11, -11 12))"; //right-angle triangle
+    assertJQ(req(
+        "q", "{!cache=false field f=" + fieldName + "}Intersects(" + polygonWKT + ")",
+        "sort", "id asc"), "/response/numFound==2");
+  }
+
+  private void testRptWithGeometryField(String fieldName) throws Exception {
     assertU(adoc("id", "0", fieldName, "ENVELOPE(-10, 20, 15, 10)"));
     assertU(adoc("id", "1", fieldName, "BUFFER(POINT(-10 15), 5)"));//circle at top-left
corner
     assertU(optimize());// one segment.
@@ -118,7 +133,7 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
 
     // The tricky thing is verifying the cache works correctly...
 
-    MetricsMap cacheMetrics = (MetricsMap) h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.perSegSpatialFieldCache_srptgeom");
+    MetricsMap cacheMetrics = (MetricsMap) h.getCore().getCoreMetricManager().getRegistry().getMetrics().get("CACHE.searcher.perSegSpatialFieldCache_"
+ fieldName);
     assertEquals("1", cacheMetrics.getValue().get("cumulative_inserts").toString());
     assertEquals("0", cacheMetrics.getValue().get("cumulative_hits").toString());
 
@@ -140,7 +155,7 @@ public class TestSolr4Spatial2 extends SolrTestCaseJ4 {
     assertJQ(sameReq, "/response/numFound==1", "/response/docs/[0]/id=='1'");
 
     // When there are new segments, we accumulate another hit. This tests the cache was not
blown away on commit.
-    // Checking equality for the first reader's cache key indicates wether the cache should
still be valid.
+    // Checking equality for the first reader's cache key indicates whether the cache should
still be valid.
     Object leafKey2 = getFirstLeafReaderKey();
     assertEquals(leafKey1.equals(leafKey2) ? "2" : "1", cacheMetrics.getValue().get("cumulative_hits").toString());
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/058429f4/solr/solr-ref-guide/src/spatial-search.adoc
----------------------------------------------------------------------
diff --git a/solr/solr-ref-guide/src/spatial-search.adoc b/solr/solr-ref-guide/src/spatial-search.adoc
index 9625b43..2070465 100644
--- a/solr/solr-ref-guide/src/spatial-search.adoc
+++ b/solr/solr-ref-guide/src/spatial-search.adoc
@@ -187,9 +187,11 @@ Using the <<the-dismax-query-parser.adoc#the-dismax-query-parser,DisMax>>
or <<t
 
 == RPT
 
-RPT refers to either `SpatialRecursivePrefixTreeFieldType` (aka simply RPT) and an extended
version: `RptWithGeometrySpatialField` (aka RPT with Geometry). RPT offers several functional
improvements over LatLonPointSpatialField:
+RPT refers to either `SpatialRecursivePrefixTreeFieldType` (aka simply RPT) and an extended
version:
+  `RptWithGeometrySpatialField` (aka RPT with Geometry).
+RPT offers several functional improvements over LatLonPointSpatialField:
 
-* Non-geodetic – geo=false general x & y (_not_ latitude and longitude)
+* Non-geodetic – geo=false general x & y (_not_ latitude and longitude) -- if desired
 * Query by polygons and other complex shapes, in addition to circles & rectangles
 * Ability to index non-point shapes (e.g. polygons) as well as points – see RptWithGeometrySpatialField
 * Heatmap grid faceting
@@ -198,8 +200,16 @@ RPT _shares_ various features in common with `LatLonPointSpatialField`.
Some are
 
 * Latitude/Longitude indexed point data; possibly multi-valued
 * Fast filtering with `geofilt`, `bbox` filters, and range query syntax (dateline crossing
is supported)
-* Sort/boost via `geodist`
-* Well-Known-Text (WKT) shape syntax (required for specifying polygons & other complex
shapes), and GeoJSON too. In addition to indexing and searching, this works with the `wt=geojson`
(GeoJSON Solr response-writer) and `[geo f=myfield]` (geo Solr document-transformer).
+* Well-Known-Text (WKT) shape syntax (required for specifying polygons & other complex
shapes), and GeoJSON too.
+  In addition to indexing and searching, this works with the `wt=geojson` (GeoJSON Solr response-writer)
and `[geo f=myfield]` (geo Solr document-transformer).
+* Sort/boost via `geodist` -- _although not recommended_
+
+[TIP]
+====
+*Important*: Although RPT supports distance sorting/boosting, it is so inefficient at doing
this that it might be
+ removed in the future.  Fortunately, you can use LatLonPointSpatialField _as well_ as RPT.
 Use LLPSF for the distance
+ sorting/boosting; it only needs to have docValues for this; the index attribute can be disabled
as it won't be used.
+====
 
 === Schema Configuration for RPT
 
@@ -251,18 +261,36 @@ A third choice is `packedQuad`, which is generally more efficient than
`quad`, p
 
 *_And there are others:_* `normWrapLongitude`, `datelineRule`, `validationRule`, `autoIndex`,
`allowMultiOverlap`, `precisionModel`. For further info, see notes below about `spatialContextFactory`
implementations referenced above, especially the link to the JTS based one.
 
-=== JTS and Polygons
+=== Standard Shapes
 
-As indicated above, `spatialContextFactory` must be set to `JTS` for polygon support, including
multi-polygon.
+The RPT field types support a set of standard shapes:
+points, circles (aka buffered points), envelopes (aka rectangles or bounding boxes), line
strings,
+polygons, and "multi" variants of these.  The envelopes and line strings are Euclidean/cartesian
(flat 2D) shapes.
+Underlying Solr is the Spatial4j library which implements them.  To support other shapes,
you can configure the
+`spatialContextFactory` attribute on the field type to reference other options.  Two are
available: JTS and Geo3D.
 
-All other shapes, including even line-strings, are supported without JTS. JTS stands for
http://sourceforge.net/projects/jts-topo-suite/[JTS Topology Suite], which does not come with
Solr due to its LGPL license. You must download it (a JAR file) and put that in a special
location internal to Solr: `SOLR_INSTALL/server/solr-webapp/webapp/WEB-INF/lib/`. You can
readily download it here: https://repo1.maven.org/maven2/com/vividsolutions/jts-core/. It
will not work if placed in other more typical Solr lib directories, unfortunately.
+=== JTS and Polygons (flat)
 
-When activated, there are additional configuration attributes available; see https://locationtech.github.io/spatial4j/apidocs/org/locationtech/spatial4j/context/jts/JtsSpatialContextFactory.html[org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory]
for the Javadocs, and remember to look at the superclass's options in as well. One option
in particular you should most likely enable is `autoIndex` (i.e., use JTS's PreparedGeometry)
as it's been shown to be a major performance boost for non-trivial polygons.
+The https://github.com/locationtech/jts[JTS Topology Suite] is a popular computational geometry
library with a Euclidean/cartesian (flat 2D) model.
+It supports a variety of shapes including polygons, buffering shapes, and some invalid polygon
repair fall-backs.
+With the help of Spatial4j, included with Solr, the polygons support dateline (anti-meridian)
crossing.
+Unfortunately Solr cannot include JTS due to its LGPL license.
+You must download it (a JAR file) and put that in a special location internal to Solr:  `SOLR_INSTALL/server/solr-webapp/webapp/WEB-INF/lib/`.
+You can readily download it here: https://repo1.maven.org/maven2/com/vividsolutions/jts-core/.
+_It will not work if placed in other more typical Solr lib directories, unfortunately._
+JTS's license is expected to be transitioned to BSD by the end of 2017.
+
+Set the `spatialContextFactory` attribute on the field type to `JTS`.
+
+When activated, there are additional configuration attributes available; see
+  https://locationtech.github.io/spatial4j/apidocs/org/locationtech/spatial4j/context/jts/JtsSpatialContextFactory.html[org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory]
+  for the Javadocs, and remember to look at the superclass's options as well.
+One option in particular you should most likely enable is `autoIndex` (i.e., use JTS's PreparedGeometry)
as it's been shown to be a major performance boost for non-trivial polygons.
 
 [source,xml]
 ----
 <fieldType name="location_rpt"   class="solr.SpatialRecursivePrefixTreeFieldType"
-               spatialContextFactory="org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory"
+               spatialContextFactory="JTS"
                autoIndex="true"
                validationRule="repairBuffer0"
                distErrPct="0.025"
@@ -281,6 +309,25 @@ Inside the parenthesis following the search predicate is the shape definition.
T
 
 Beyond this Reference Guide and Spatila4j's docs, there are some details that remain at the
Solr Wiki at http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4.
 
+=== Geo3D and Polygons (on the ellipsoid)
+
+Geo3D is the colloquial name of the Lucene spatial-3d module, included with Solr.
+It's a computational geometry library implementing a variety of shapes (including polygons)
on a sphere or WGS84 ellipsoid.
+Geo3D is particularly suited for spatial applications where the geometries cover large distances
across the globe.
+Geo3D is named as-such due to its internal implementation that uses geocentric coordinates
(X,Y,Z),
+  *not* for 3-dimensional geometry, which it does not support.
+Despite these internal details, you still supply latitude and longitude as you would normally
in Solr.
+
+Set the `spatialContextFactory` attribute on the field type to `Geo3D`.
+
+[source,xml]
+----
+<fieldType name="geom" class="solr.SpatialRecursivePrefixTreeFieldType"
+             spatialContextFactory="Geo3D" planetModel="WGS84"/><!-- or "sphere" -->
+----
+
+Once the field type has been defined, define a field that uses it.
+
 === RptWithGeometrySpatialField
 
 The `RptWithGeometrySpatialField` field type is a derivative of `SpatialRecursivePrefixTreeFieldType`
that also stores the original geometry internally in Lucene DocValues, which it uses to achieve
accurate search. It can also be used for indexed point fields. The Intersects predicate (the
default) is particularly fast, since many search results can be returned as an accurate hit
without requiring a geometry check. This field type is configured just like RPT except that
the default `distErrPct` is 0.15 (higher than 0.025) because the grid squares are purely for
performance and not to fundamentally represent the shape.


Mime
View raw message