2

I am trying to locate all the points within a set of polygons given a certain condition on the polygon in MongoDB using Python 3x.

This question differs from the other ones because i) it requires multiple points to be returned and has MULTIPLE polygons to search through, and ii) the polygons are cross-collection search.

Essentially, this is something along the lines that I need, where $geometry: is replaced by all the polygons it needs to search through in my other collection while applying the condition 'class' : 'B'.

db.locations.find({'geo_coordinate' :
                    { $geoWithin :
                    { $geometry :
                        db.polygons.geometry: {'class': 'B'}

                } } } } )

Locations structure (21k documents):

{
  "la": 43.57386,
  "lo": -79.5736,
  "address": "123 Stack Dr.",
  "geo_coordinate": {
    "type": "Point",
    "coordinates": [-79.5736, 43.57386]
  }
}

Polygon Structure (w/ coordinates removed | 16k documents):

{
  "type": "Feature",
  "properties": {  },
  "geometry": {
    "type": "MultiPolygon",
    "coordinates": [
    ]
  },
  "class": "A",

}
0

For closure:

I got 90% of the way there with method #1, first finding all polygons that satisfied my filter, and then using shapely to recreate them into objects and use GeoPandas to dissolve into one MultiPolygon. I then converted the single shapely object into geojson by applying using shapely.geometry.mapped() and fed this back into the original filter like so:

db.locations.find({'geo_coordinate' :
                    { $geoWithin :
                    { $geometry :
                        dissolved_polygon_filtered

                } } } } )

However, this approach ran into issues as dissolving 5k polygons into one MultiPolygon was not smooth using MongoDB as it inherently spit out "Invalid loop, duplicate vertices, edges crossing" etc. errors. I decided to leave the geoprocessing to the proper libraries that can handle it.

Method #2:

  • Loop through all json polygon features stored in MongoDB and recreate as shapely object (shapely.geometry.asShape)
  • Loop through all points/locations stored in MongoDB and recreate as shapely object (shapely.geometry.asShape(point_geometry).buffer(0.0000001)
  • Perform a spatial overlay using GeoPandas and pull out ids from the intersection to go back to db and query further data on it as needed / display out on front-end

    res_union = gpd.overlay(gdf_p, gdf, how='intersection') ids = list(res_union._id)

I agree this isn't the most efficient way for completing the task, as it has pretty significant latency with the number of polygons it processed, however, it works for in the time being and I will update my answer once a more efficient solution using solely MongoDB is solved.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.