Creating spatial index for polygons

Hello,

I’m trying to create a collection that has polygon geometries and an 2dsphere index but I’m getting the following error.

> db.microsoft.createIndex({geojson: "2dsphere"})
{
        "operationTime" : Timestamp(1590202707, 2),
        "ok" : 0,
        "errmsg" : "Can't extract geo keys: { _id: ObjectId('5ec875653962b8635f792c0c'), state: \"DistrictofColumbia\", id: 9303, geojson: { type: \"Polygon\", coordinates: [ [ [ -76.985101, 38.927718 ], [ -76.985095, 38.927589 ], [ -76.98518, 38.927586 ], [ -76.985178, 38.927538 ], [ -76.985096, 38.927541 ], [ -76.98509900000001, 38.927589 ], [ -76.984953, 38.927593 ], [ -76.984959, 38.927722 ], [ -76.985101, 38.927718 ] ] ], crs: { type: \"name\", properties: { name: \"EPSG:4326\" } } } }  Loop is not valid: [ [ -76.985101, 38.927718 ], [ -76.985095, 38.927589 ], [ -76.98518, 38.927586 ], [ -76.985178, 38.927538 ], [ -76.985096, 38.927541 ], [ -76.98509900000001, 38.927589 ], [ -76.984953, 38.927593 ], [ -76.984959, 38.927722 ], [ -76.985101, 38.927718 ] ] Edges 0 and 5 cross. Edge locations in degrees: [-76.9851010, 38.9277180]-[-76.9850950, 38.9275890] and [-76.9850990, 38.9275890]-[-76.9849530, 38.9275930]",
        "code" : 16755,
        "codeName" : "Location16755",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1590202707, 2),
                "signature" : {
                        "hash" : BinData(0,"hNRuE+AA5NSpSsamZRHT1/hS7AE="),
                        "keyId" : NumberLong("6828646414617149444")
                }
        }
}

I’ve successfully created geometries and indexes from this same data in postgres and I’ve converted it into jts geometries with org.locationtech.jts.io.geojson.GeoJsonReader and not had any problems on those fronts.

I don’t think this matters, because I’ve used this method for writing just points and the geometry field and been able to create indexes fine, but I’m writing the data to mongo via spark with the following code.

import com.mongodb.spark._
import com.mongodb.spark.config.{ReadConfig, WriteConfig}
import org.bson.Document
import com.google.gson.Gson
import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.io.geojson.GeoJsonReader
import org.locationtech.jts.io.geojson.GeoJsonWriter

case class FootprintSchema(state: String, id: Int, geojson: Document)

val connectionString = "..."
val writeConfig = WriteConfig(Map("uri" -> connectionString))
val inputPath = "..."

val data = spark
  .read
  .format("csv")
  .option("delimiter", "|")
  .load(inputPath)
  .as[(String, String, String)]
  .rdd
  .mapPartitions { it =>
    val gson = new Gson()
    val reader = new GeoJsonReader()
    val writer = new GeoJsonWriter()
    it.map { case (state, id, geojson) =>
      val fp = FootprintSchema(state, id.toInt, Document.parse(geojson))
      //val fp = FootprintSchema(state, id.toInt, Document.parse(writer.write(reader.read(geojson))))
      Document.parse(gson.toJson(fp))
    }
  }
data.saveToMongoDB(writeConfig)

Is there something different I need to do for mongo to understand the geojson?

Thanks!

Hi,

I believe the error Location16755 points that your polygon crosses the meridian (date line), or you have a polygon with coordinates >180 degrees or < -180 degrees.

This is discussed in SERVER-34673: Coordinates are considered out of bounds if the longitude falls outside of [-180, 180] or the latitude falls outside of [-90, 90].

SERVER-9948 shows a similar situation, especially this comment.

Unfortunately this is a tricky situation, and in this case MongoDB opts to be safe and tries to avoid any situation where it’s describing the wrong shape. Other tools may not be as conservative, so they will try to interpret what you mean using their own logic.

If you require further help with this, please post the document in question, and please describe how the polygon should be shaped.

Best regards,
Kevin

2 Likes

Thanks for getting back to me Kevin. I figured out the problem actually. The polygon was self-intersecting, which you’re correct all the other tools are much more lenient about. My solution ended up being to use jts to correct these polygons, following this code java - Is there a way to convert a self intersecting polygon to a multipolygon in JTS? - Stack Overflow, additionally I had an issue with mongo not liking the crs field that the jts GeoJsonWriter outputs, and was able to turn that off with writer.setEncodeCRS(false).

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.