Point in array of polygons, if true get name of polygon mongodb - mongodb

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.

Related

Strange problem when storing and querying GeoJson in MongoDB

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.

MongoDB Geospacial Query on MultiPolygon

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 :)

MongoDB not properly 2DIndex-ing

I have a dataset of ~400k objects in the format:
{
"trip": {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
-73.9615,
40.6823
],
[
-73.9704,
40.7849
]
]
},
"properties": {
......
}
}
}
I tried making a 2dsphere index on mLab like so:
{"trip.geometry" : "2dsphere"}
Which I assume just calls:
db.collection.createIndex( {"trip.geometry" : "2dsphere"} )
When I try to do a $geoWithin query like so (about 500 hits):
db.collection.find(
{
"trip.geometry": {
$geoWithin: {
$geometry: {
type : "Polygon" ,
coordinates: [
[
[-74.0345,40.7267],
[-73.9824,40.7174],
[-73.9934,40.7105],
[-74.0345,40.7267]
]
]
}
}
}}
)
I noticed it was very slow, ~2 seconds. I then tried deleting the index entirely, and the time increase was very slight. ~0.5 seconds. Is it possible that this query is not using the index the I had set? I've included the explain() here.
By my interpretation, the winning plan first fetches all the data based on a simple filter, then uses the 2dindex. Shouldn't it start out using the 2dindex, given that the lat and lon data aren't indexed directly?

MongoDB: Select all polygons within the radius of a point

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

Does MongoDB support GIS geofencing with $geoWithin?

I would like to have a MongoDB collection and each document contains a geospatial polygon defined by latitude/longitude points (in GeoJSON). Then, I would like to take any given longitude/latitude point and check if it resides within any of the MongoDB polygons defined in the documents. Hypothetically, this is what the documents would look like.
{
"type" : "congressional",
"points" : [
{ "coords" : [
-141.0205,
70.0187 ]
},
...
{ "coords" : [
-141.0205,
70.0187 ]
}
]
}
Or maybe like so:
{ loc :
{ type : "Polygon" ,
coordinates : [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ] ]
} }
And then I would query it, hypothetically, like so (most likely with Mongo's $geoWithin):
db.places.find( { loc : { $geoWithin : { $geometry : "EACH DOCUMENT IN COLLECTION"} } } )
Is geofencing, or something similar, possible to do with the current MongoDB feature-set? If so, how would it be done?
I believe you would have to first find every document from the collection., and then make a "$geoWithin" query for every document, passing in the Polygon to test against for each case.
Depending on the number of documents in your collection, that may or may not provide sufficient performance.
MongoDB has full support for geofencing or finding documents whose geometry intersects with a given geometry (point, polygon). The query below is an example. geometry of Collection is the field containing the geometry.
Document Example:
{ "geometry": {
"type": "Polygon",
"coordinates": [
[
[
-74.001487,
40.692346
],
[
-74.001755,
40.692057
],
[
-74.000977,
40.691951
],
[
-74.000827,
40.692297
],
[
-74.001487,
40.692346
]
]
]
}
}
JS Query:
//find quests bots that matches the users location
await Collection.find({ geometry:
{ $geoIntersects:
{
{
type: "Point",
coordinates: [
-73.99460599999999,
40.7347229
]
}
}
}
});