MongoDB Geospatial query areas overlapping a single point

I am trying to create a geospatial query in MongoDB that finds all circles (with different radii) that overlap a single point.

My data looks something like this:

{ name: "Pizza Hut", lat: <latitude> lon: <longitude> radius: 20 ... } 

Basically, I'm trying to do exactly what is described in this SO entry, but with MongoDB - Get all the points (circles with radius) that overlap a given point

geoIntersects ( http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/ ) looks like I need. But in my case, lat, lon and radius are saved with every mongodb document and are not a fixed radius, which is part of the request. It can be done?

Another approach would be to find all documents whose distance from my query point is less than the value of their radius field (i.e. - 20 km in the example above). How do you structure a MongoDB query where the estimated distance is part of the query filter criteria?

Thanks!

+5
source share
2 answers

It would be nice if you could use the GeoJSON object to represent the location, but the types currently supported are actually limited , so the Circle type, which would be ideal, is not supported.

The closest thing you can do is a “polygon” approaching a circle, but it's probably too much work to build a query just for this purpose. Another result with this, and then using $geoIntersects is that the results will not be sorted by distance from the query point. It seems to be the opposite of finding the “nearest pizza” at the origin.

Fortunately, the $geoNear operation has been added to the aggregation platform, starting with MongoDB 2.4 and higher. The good thing here is that it allows the "projection" of the distance field in the results. Then it allows you to perform logical filtering on the server with those points that are within the radius, at a distance from the origin. It also allows you to sort on the server.

But you still need to change the schema to support the index

 db.places.insert({ "name": "Pizza Hut", "location": { "type": "Point", "coordinates": [ 151.00211262702942, -33.81696995135973 ] }, "radius": 20 }) db.places.ensureIndex({ "location": "2dsphere" }) 

And for aggregation request:

 db.places.aggregate([ // Query and project distance { "$geoNear": { "near": { "type": "Point", "coordinates": [ 150.92094898223877, -33.77654333272719 ] }, "distanceField": "distance", "distanceMultiplier": 0.001, "maxDistance": 100000, "spherical": true }}, // Calculate if distance is within delivery sphere { "$project": { "name": 1, "location": 1, "radius": 1, "distance": 1, "within": { "$gt": [ "$radius", "$distance" ] } }}, // Filter any false results { "$match": { "within": true } }, // Sort by shortest distance from origin { "$sort": { "distance": -1 } } ]) 

It basically says

* "up to 100 kilometers from this place, find places with their distance from this point. If the distance is within your" delivery radius ", return them sorted by the nearest"

There are other options that you can pass $geoNear to refine the result, as well as return more than the default value. 100, if required, and basically pass on other parameters for the request, such as "type" or "name" or any other information contained in the document.

+7
source

Correction: MongoDB (since version 3.2.0) does not support the Circle GeoJSON type for 2dsphere indexes.

The following is the original and incorrect answer. Read the comments for details.


I do not think that using a specific scheme, you can decide what you are looking for.

With mongodb> = 2.4, you can store and index documents using GeoJSON, and then use the $geoIntersects , for example:

 db.places.insert({ name: "Pizza Hut", location: { "type": "Circle", "coordinates": [100,0], "radius": 20 } }) db.places.find({ location: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ 110, 10] } } } }) 

Otherwise, a combination of $geoWithin and manual application processing may work, although I would prefer to redefine my schema if possible.

-1
source

Source: https://habr.com/ru/post/1201687/


All Articles