I've been reading through mongo's docs on geospacial querying, and have things working well for singl Polygon types but am having trouble with MultiPolygon. What I want to do is essentially this:
Given a MultiPolygon outlining areas of exclusion:
{
"type" : "MultiPolygon",
"coordinates" : [
[
[
[
-117.873730659485,
33.6152089844919
],
[
-117.873065471649,
33.615048159758
],
[
-117.873044013977,
33.614690770386
],
[
-117.873666286469,
33.6146729008785
],
[
-117.873730659485,
33.6152089844919
]
]
]
]
}
I simply want to be able to pass in a Point to see if it is excluded. I've tried $geoIntersects just to see if it even can determine if a Point is included or not, but that doesn't work. In the end, I want to check that a point is not included within the exclusion list, but the query is simpler without the additional $not operator... Here's what I've been trying:
var geoPoint = {type: 'Point', coordinates: [-117.8731230, 33.6150696]};
db.myCollection.aggregate([
{$match: {'exclusionsPolygons': {$geoIntersects: {$geometry: geoPoint}}}}
]);
Note that if I do the same exact thing with a GeoJSON type of Polygon then it works just fine:
Given this single polygon:
{
"type" : "Polygon",
"coordinates" : [
[
[
-117.8711744,
33.6129677
],
[
-117.8751744,
33.6129677
],
[
-117.874444839148,
33.6162171973226
],
[
-117.87287399259,
33.6172714730352
],
[
-117.871410434393,
33.6165209730032
],
[
-117.8711744,
33.6129677
]
]
]
}
This query works just find and returns the item(s) whose singular polygon contains the point:
var geoPoint = {type: 'Point', coordinates: [-117.8731230, 33.6150696]};
db.myCollection.aggregate([
{$match: {'singularPolygon': {$geoIntersects: {$geometry: geoPoint}}}}
]);
After some tinkering, it turns out the result set was right and I was wrong...
I was using the areas of interest on the map to get addresses to try to query against. One such place was, I thought, in an exclusion polygon:
However, once I made the polygon larger the result set started coming back as I expected it to... So, I reset the polygon and double-checked the map content, finding that if I zoom in further the area of interest was actually excluded from the polygon as there are multiple areas of interest contained:
Whoops - my bad :)
Related
in my polygons collection I have many kinds of polygons, let's say type A, B and C.
Also, I have a points collection where I have stored last lat,lng of those points. What I want, is to know if that last position of points are inside a polygons and if its true, bring the type of the polygon where my point is.
My points collection documents looks like this:
{
"_id": "KYBV21",
"lat": -33.389222,
"lng": -70.692958,
"date_time": "2020-06-22 17:00:55",
"cod_plate": "KYBV21"
}
My polygons collection looks like this:
{
"geoJson": {
"geometry": {
"coordinates": [
[
[
-106.134222,
28.72389
],
[
-106.134222,
28.725734
],
[
-106.131669,
28.725734
],
[
-106.131669,
28.72389
],
[
-106.134222,
28.72389
]
]
]
}
},
"zone_type": "origin"
}
I have tried bringing both separately, but it takes longer than I expected. So I want to know if there is another solution doing both queries in just one.
I want to store GeoJson data for an area using MongoDB. The data comes from an official website. Each area is represented as MultiPolygon. In the end, I want to find all areas that contain a lng/lat pairs using a $intersect like that:
db.areas.find({
"location.geometry": {
"$geoIntersects": {
"$geometry": {
"type": "Point",
"coordinates": [
<lng>,
<lat>
]
}
}
}
}
In principle, it seems to work just fine. However, I've encountered problems with some areas seemingly with respect to the set of polygons of a MultiPolygon. I could boil down my problem to an individual case:
An area (being a GeoJson MultiPolygon) has six polygons, say [A, B, C, D, E, F]. Also the point <lng>,<lat> I query for lies within polygon A. Now the query above only works if the area does not contain the polygons D and F (A has to be included always, of course) -- that is, I get the expected search result. Otherwise, the query is empty (but no error). In short
What works: [A], [A,B], [A,B,C], [A,B,C,E], [A,C], ... (any combination with A and without D & F)
What doesn't work: [A,D], [A,B,F], ... (any combination that contains D or F)
What is the problem with polygons D and F? Are they not allowed to overlap with other polygons in the MultiPolygon? Are they maybe too small? I've tried the GeoJson definition but couldn't see any issues. Could it be because the GeoJson support of MongoDB.
You are correct that without any special considerations, you can insert a Polygonor MultiPolygon into MongoDB that has deformed GeoJSON structure. This is because unless you specifically create a geo index on the field, MongoDB doesn't know it is GeoJSON at all. The geo engine will silently not match a target intersect geometry, much as it would if you pointed it at a simple scalar field like {"name":"buzz"}.
If you add an index thusly:
db.geo.createIndex({loc:"2dsphere"})
Then this will activate the geo-aware machinery and if you try to insert or update a deformed GeoJSON shape, it will produce an error (scroll to see the Loop not closed part):
{
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16755,
"errmsg" : "Can't extract geo keys: { _id: 0.0, loc: { type: \"MultiPolygon\", coordinates: [ [ [ [ -83.0, 40.0 ], [ -83.0, 41.0 ], [ -82.0, 41.0 ], [ -82.0, 40.0 ], [ -83.0, 40.0 ] ] ], [ [ [ -93.0, 40.0 ], [ -93.0, 41.0 ], [ -92.0, 41.0 ], [ -92.0, 40.0 ], [ -93.0, 40.0 ] ] ], [ [ [ -73.0, 49.0 ], [ -72.0, 41.0 ], [ -72.0, 40.0 ], [ -73.0, 40.0 ], [ -73.0, 41.0 ] ] ] ] } } Loop is not closed: [ [ -73.0, 49.0 ], [ -72.0, 41.0 ], [ -72.0, 40.0 ], [ -73.0, 40.0 ], [ -73.0, 41.0 ] ]"
}
}
In other words, the geo index becomes the guard at the door and ensures that all shapes written are GeoJSON compliant. This is also why it is very useful to ensure the index is created before inserts and updates because trying to create a geo index on many docs with potentially 100s or 1000s of deformed shapes will lead to much tedious work trying to isolate and fix the bad shapes one at a time.
After some more digging, I figured out that the polygons causing the issues contained duplicate coordinates (apart from the first and last coordinate). Online GeoJson validator didn't raise an error, but it seems that MongoDB doesn't handle it.
After removing all duplicates, everything works fine -- at least I hope that removing duplicates alter the shape of the polygons too much (but that's not overly crucial for my case). It's just a bit unfortunate that MongoDB doesn't raise an error but simply returns an empty result.
Guys I am trying to query all the polygons inside by bounding box but it simply returns 0.. It should be returning many polygons!
Alternatively I try to query a much larger bounding box and nothing happens!
My query is:
{
geometry:
{ $geoWithin:
{ $box:
[ [-73.995762,40.764826], [-73.934034,40.802038] ]
}
}
}
Notice that the very same query returns a valid result for geometries of type Point
to query all the polygons inside by bounding box but it simply returns 0
The $box operator for $geoWithin only supports documents based on grid coordinates and does not support GeoJSON shapes format.
the very same query returns a valid result for geometries of type Point
Depending on your documents structure, and how you are querying them, this is probably treated as being grid coordinates i.e. {geometry: [<long>, <lat>]}
This may not have worked for your polygons document because GeoJSON Polygons require an extra array wrapper. i.e. [[ [<long>, <lat>] ]] invalidating the grid coordinates format.
If your documents are in GeoJSON format, and you would like to select an area, you could utilise $geometry instead.
db.places.find(
{
'geometry': {
$geoWithin: {
$geometry: {
type : "Polygon" ,
coordinates: [ [ [ 0, 0 ], [ 3, 6 ], [ 6, 1 ], [ 0, 0 ] ] ]
}
}
}
}
)
Worth noting that MongoDB Compass geospatial visualisation currently (v1.6) does not support GeoJSON yet.
Here goes the answer:
$box do work with GeoJSON, but not with polygons! You need to generate a geometry with the $box instead.
Also, it always has to has the start point and point, so a 4-point polygon will have 5 coordinate tuples
BUT it gets trickier, it has to follow the right hand rule (anticlockwise).
TESTING GEOJSON WITH $BOX AND POINTS
my query:
{
geometry: {
$geoWithin: {
$box: [
[ -71.934034, 38.764826 ],
[ -75.995762, 43.802038 ]
]
}
}
}
I have two collections in my database: Post and Gallery. A Post has a single GeoJSON Point location, and a gallery is a collection of posts. The gallery's location is a GeoJSON Polygon bounding the gallery's posts (using quickhull algorithm). I now need to query for all galleries within x miles of a certain point, however I'm not getting any results even if I query from right next to my polygon.
I would like the behavior to be exactly the same as the following:
db.posts.find({
'location': {
$geoWithin: {
$centerSphere: [[-70, 30], 1000/3959]
}
}
});
Here, all posts within a the radius are returned. However, when I run the same type of function in this way, I am returned nothing, which is not correct:
db.galleries.find({
'location': {
$geoWithin: {
$centerSphere: [[-70, 30], 1000/3959]
}
}
});
One of my galleries has the following location (is 2dsphere index with 2dsphereIndexVersion = 2):
"location": {
"type": "Polygon",
"coordinates": [
[
[
-73.986882,
40.682829
],
[
-73.971089,
40.6672045
],
[
-73.955296,
40.65158
],
[
-73.986882,
40.682829
]
]
]
}
How do I query for location polygons that at least intersect with my radius?
I had the same problem and tried the exact same query that you initially tried. I'm not sure why it didn't work, but I was eventually able to get $near to do the job. Keep in mind that $near uses meters when calculating $maxDistance, so I had to convert my 10 mile desired distance to meters by multiplying by 1609.34. Here's the query that I ended up using:
db.maTowns.find(
{
'geometry': {
$near: {
$geometry: {
'type': "Point",
'coordinates': [ -71, 42 ]
},
$maxDistance: 10 * 1609.34
}
}
}
)
Select all polygons within the radius of a point
With the recent release of MongoDB version 3.6.0-rc0, you can now query GeoJSON LineStrings and Polygons with $geoWithin geospatial operator $centerSphere.
See also SERVER-27968 for more information about the change. Note that this change is pending to be backported.
Also maybe related for $geoIntersects and $centerSphere is ticket SERVER-30390
I am writing a nodejs app involving geocodes ( ~50million places) stored in mongodb (using mongo native driver). For development I am testing with sample data (airports of the world ~45k locations http://www.ourairports.com/data/airports.csv ). I am following GeoJSON format and building 2dsphere index on location field(named "geometry"). Then I am doing a $geowithin query to find locations.
Evrything works as expected. The issue is that when I am querying for a polygon containing US, the query is taking around 4-6sec for returning 22845 locations.
db. airports.ensureIndex({ geometry: '2dsphere' })
db.airports.find({ geometry: { '$geoWithin': { '$geometry': { type: 'Polygon', coordinates: [ [ [ -127.32917843921399, 75.11297289119061 ], [ -71.32126356078601, 75.11297289119061 ], [ -71.32126356078601, 12.305525108809391 ], [ -127.32917843921399, 12.305525108809391 ], [ -127.32917843921399, 75.11297289119061 ] ] ] } } } })
I am sure that this cant be correct. This way I cant imagine response times with 50million points.
Would appreciate if someone can point me in direction to improve the performance of this.