1
votes

I have a collection of geoJSON data in a mongoDB database (v2.6.10 ). The data consists of thousands of polygons, mostly squares that represent 500mx500m land claims. This data is being used on a web app that displays the data on a map.

The web app performance is really slow due to the huge number of polygons. To improve performance I want to limit the queries to the bounds of the current map window. We are using the Mapbox API and I am able to get map bounds from the API to be used in a mongodb geo-query.

So far I have been unable to get the mongo queries to cooperate.

Here is a sample record of the geoJSON data that is stored in the DB:

{
  "_id" : ObjectId("56ca94e0336aac299182442f"),
  "type" : "Feature",
  "properties" : {
    "TNRTPCD" : "P",
   ## some fields ommitted for privacy reasons ##
    "TRMNTNDT" : null,
    "RNHCTRS" : 20.3496,
    "TTLTPCD" : "PCX"
  },
  "geometry" : {
    "type" : "Polygon",
    "coordinates" : [
      [
        [
          [
            -121.88883540217063,
            50.97489195799901,
            0
          ],
          [
            -121.88883523174192,
            50.97072525131302,
            0
          ],
          [
            -121.8950854466247,
            50.97072527980969,
            0
          ],
          [
            -121.89508560169767,
            50.97489198254216,
            0
          ],
          [
            -121.88883540217063,
            50.97489195799901,
            0
          ]
        ]
      ]
    ]
  }
}

I have tried the following query and it returns no records and no errors:

db.docs.find(
   {
     'geometry.coordinates': {
       $geoWithin: {
          $geometry: {
             type : "Polygon" ,
             coordinates: [[
             [ -121.26571655273438, 49.56352444783811 ], 
             [ -121.26571655273438, 52.719152198289635 ], 
             [ -120.97492218017578, 52.719152198289635 ], 
             [ -120.9749221801757, 49.56352444783811 ],
             [ -121.26571655273438, 49.56352444783811 ]
              ]]
          }
       }
     }
   }
)

I know that there is data within the defined boundary and yet noting returns. I have tried playing around with the target column. I tried switching 'geometry.coordinates' to just coordinates, I tried with quotes and without. I also messed around with the polygon AOI coordinates. When the first point is not repeated I get an error.

I have also tried switching $geoWithin for $near, $box and $geoIntersects. With similar results.

I'm guessing that the issue has to do with the geographical index but that's just a hunch. I tried to put a 2dsphere index on the geometry column using the following command:

db.docs.ensureIndex( { "geometry" : "2dsphere" } );

That fails and gives the following error:

"createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "ok" : 0,
    "errmsg" : "Can't extract geo keys from object, malformed geometry?:

When I try putting an index on just the coordinates it seems to work. I used this command:

db.docs.ensureIndex( { "coordinates" : "2dsphere" } );

And got the following output:

    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

To be honest I am new to mongodb so this feedback doesn't mean much to me. I am not new to GIS and mapping but I can't figure this out. Please help. To summarize, I'm trying to narrow my query results by using mongo's geo filtering functions.

2
Yup it means what it says. Your GeoJSON is invalid, at least for MongoDB. Problem is you have x/y/z values, and you can only have x/y values. So drop of the 0 values for z that you would not be using anyway. - Blakes Seven
FYI, even when corrected the Polygon shown as an example in your question does not lie within the bounds of the Polygon in your query. So another future tip of asking questions is to make sure that the sample you provide is something that you would expect to be matched by any such query you can make. This document would not match, even with all the z-indexes removed. - Blakes Seven
Hi Blakes, thanks for taking the time to help. The Z coordinates are not needed. It makes sense that they might not work properly with a "2D Sphere". I've recreated the geoJSON file with the z coordinates removed. Then imported to mongo as a separate collection. I got the same error when trying to add the 2d index: > db.docs4.ensureIndex( { "geometry" : "2dsphere" } ); { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "ok" : 0, "errmsg" : "Can't extract geo keys from object, malformed geometry? - ngust
Also I am aware that the sample record does not lie in the test AOI. It was just a random sample of the database. I know that there are polygons that lie in that AOI though. In future questions I'll choose a more relevant sample record. - ngust
Take another look at the Polygon definitions. The two things wrong I see are 1. z-index entries to be removed. 2. Extra brace on the coordinates, being three and not two at present. Fix those things and you an 2dshpere index, or even just $geoWithin without an index, though an index does help speed the search. - Blakes Seven

2 Answers

0
votes

OK, I got it working now. The Z coordinates appears to have been the problem. Thanks Blakes Seven for catching that. I have spent many hours of frustration trying to figure out why the queries would not work.

I recreated the geoJSON this time stripping out the Z values. Otherwise the geoJSON files are identical. I then imported the X,Y only file into mongo as a different collection.

I was still unable to create a 2dsphere index on the geometry column but I was able to create one on the coordinates directly using the following command:

db.docs.ensureIndex( { "coordinates" : "2dsphere" } );

From examples online it seemed like the index should have been on the geometry column but the queries work with this setup.

I now return the expected results with this query:

db.docs4.find(
   {
     "geometry": {
       $geoWithin: {
          $geometry: {
             type : "Polygon" ,
             coordinates: [[
             [-121.57814025878906, 49.651181832527826 ], 
             [ -121.57814025878906, 49.80652967700498 ], 
             [ 121.28734588623047, 49.80652967700498 ], 
             [ -121.28734588623047, 49.651181832527826],
             [ -121.57814025878906, 49.651181832527826 ]
              ]]
          }
       }
     }
   }
)
0
votes

The cause of this error is caused by intersecting polygons. This will prevent you from building 2D sphere indexes.

You can test if you have any intersecting by uploading your geojson file to the following site: mapshaper

If any are reported, you can fix them on the site by using the simplify function. This is OK to fix a couple of files but if you need to fix lot, then you'll need to use ogr2ogr within the GDAL tools set.