How do I query a GeometryCollection in Mongodb? - mongodb

I am trying to run a mongoldb query on a GEOjson collection of points and polygons but I'm struggling. I am new to GEOjson and Mongodb and haven't been able to find any examples on how to do this via google search and S.O. search so I'm hoping someone can shed some light on my issue.
I have created a 2DSphere index on geometry.coordinates - not sure if that's correct or not.
My overall objective is to return all points within the current map view and add both the point and the polygon associated to the map. I am using Leaflet.js and understand how to add to the map, but I can't figure out the query on Mongodb to get the results.
Just looking to find out if my GEOjson is correct and maybe an example on how I would perform the search on my GeometryCollection and get the point using $geowithin and then get the associated polygon.
Here's an example of my GEOjson-
{
"_id" : ObjectId("5709722f4044ccc4b8291651"),
"type" : "Feature",
"geometry" : {
"type" : "GeometryCollection",
"geometries" : [
{
"type" : "Point",
"coordinates" : [
-105.960805584616,
39.4671896545181
]
},
{
"type" : "Polygon",
"coordinates" : [
[
[
-105.96110187372227,
39.463449804295806
],
[
-105.96602244670311,
39.462956063632134
],
[
-105.96577627486317,
39.46671592928652
],
[
-105.96553007974012,
39.470475771657675
],
[
-105.96047434857059,
39.47089761421853
],
[
-105.95541854755197,
39.471319247231634
],
[
-105.95579990086372,
39.46763141937862
],
[
-105.95618125417559,
39.463943568242485
],
[
-105.96110187372227,
39.463449804295806
]
]
]
}
]
},
"properties" : {
"processed" : "Yes"
}
}

Related

Creating a Geospatial Index on MongoDB

I am using the Geospatial Feature of MongoDB and my typical document looks like:
{
"_id" : ObjectId("574ebe5f9985eb31a9bdbe39"),
"geoareaName" : "GEOAREA2",
"loc" : {
"type" : "Polygon",
"coordinates" : [
[
[
13.870663396091308,
3.481292724609375
],
[
13.875996314658366,
3.482236862182617
],
[
13.872746581997381,
3.484210968017578
],
[
13.871829982503106,
3.484961986541748
],
[
13.870663396091308,
3.481292724609375
]
]
]
},
"color" : "#ff0000",
"_version" : 4,
"active" : false
}
and then there are some point locations which I query using the $geoIntersects keyword and it works like a charm. However, to optimally use the geospatial feature of mongo I want to put indexes around the location.
Can someone please suggest what should be the correct approach for that.
Create a 2dsphere index on loc.
db.collection.createIndex( { loc : "2dsphere" } )
It's pretty basic but it works great!

Can't extract geo keys' even though the GeoJSON is valid

I have a collection in MongoDB with a 2dsphere index. The object I want to save looks like this:
{
"type" : "Polygon",
"coordinates" : [
[
[
5.052617929724351,
52.64653192570052
],
[
5.051738165167465,
52.64765805672784
],
[
5.054162882116928,
52.64831549553909
],
[
5.054592035559312,
52.64780777138566
],
[
5.055364511755601,
52.64790541110375
],
[
5.056094072607651,
52.64688343792051
],
[
5.054237983969346,
52.64661654927096
],
[
5.052617929724351,
52.64653192570052
]
]
]
}
According to http://geojsonlint.com/ this is perfectly valid GeoJSON. However MongoDB says it can't extract the geo keys because the GeoJSON might be malformed.
Can anyone help me out and spot the mistake?
This is the MongoDB error I get:
insertDocument :: caused by :: 16755 Can't extract geo keys from object, malformed geometry?
The problem is that you are not providing the name of the top level object that the GeoJSON would be assigned to.
You must have created the "2dsphere" index on the "coordinates" field. Instead you want to create it on the field that this entire GeoJSON value will be assigned to.
db.geo.createIndex({"location":"2dsphere"})
db.geo.insert({"location" : {
"type" : "Polygon",
"coordinates" : [
[ <list of your-coord-pairs> ]
]
}})
WriteResult({ "nInserted" : 1 })

Why am I getting values outside polygon with geoIntersect

I am using mongodb with polygons stored with geometry in this format
"geometry" : { "type" : "Polygon", "coordinates" : [ [ [ 2.0315, 85.8546219515 ], [ 2.0315, 86.1673780485 ], [ 1.7185, 86.1673780485 ], [ 1.7185, 85.8546219515 ], [ 2.0315, 85.8546219515 ] ] ] }
I am trying to use geoIntersect and query a rectangle polygon using something like this:
find({geometry:{$geoIntersects:{$geometry:{"type": "Polygon", "coordinates":[ [[12,20], [13,20], [13,18], [12,18], [12,20]]]}}}})
When I do small queries like that, the results are fine, but when I expand to really large boxes:
find({geometry:{$geoIntersects:{$geometry:{"type": "Polygon", "coordinates":[ [[-166.2890625,46.55886030311719], [-166.2890625,47.39834920035926], [12.12890625,47.39834920035926], [12.12890625,46.55886030311719], [-166.2890625,46.55886030311719]]]}}}})
then I start getting really odd results like
"geometry" : { "type" : "Polygon", "coordinates" : [ [ [ 2.9684999999999997, 85.54162195149999 ], [ 2.9684999999999997, 85.8543780485 ], [ 2.6555, 85.8543780485 ], [ 2.6555, 85.54162195149999 ], [ 2.9684999999999997, 85.54162195149999 ] ] ] }
I am only returned a few polygons (4 total) from the db that are actually inside my input polygon:
"geometry":{"type":"Polygon","coordinates":[[[12.343499999999999,47.1416219515],[12.343499999999999,47.454378048500004],[12.0305,47.454378048500004],[12.0305,47.1416219515],[12.343499999999999,47.1416219515]]]}}
"geometry":{"type":"Polygon","coordinates":[[[12.343499999999999,46.829621951499995],[12.343499999999999,47.1423780485],[12.0305,47.1423780485],[12.0305,46.829621951499995],[12.343499999999999,46.829621951499995]]]}}
"geometry":{"type":"Polygon","coordinates":[[[-166.0935,46.5166219515],[-166.0935,46.829378048500004],[-166.4065,46.829378048500004],[-166.4065,46.5166219515],[-166.0935,46.5166219515]]]}}
"geometry":{"type":"Polygon","coordinates":[[[-166.0935,46.829621951499995],[-166.0935,47.1423780485],[-166.4065,47.1423780485],[-166.4065,46.829621951499995],[-166.0935,46.829621951499995]]]}}
I shouldn't have any latitudes in the 80's with my input. I don't know where these are coming from. They make up the majority of what is returned. (847/851 results)
I don't think the polygon fits in one hemisphere. From the $geoIntersects docs,
Any geometry specified with GeoJSON to $geoIntersects queries, must fit within a single hemisphere.

determine which predefined graphical region a user is in using mongodb

using mongo, I would like to compare a user's geo coordinates to a collection of documents each representing a defined geographical boundary. This is what i have thought to do, but cant get working. Other suggestions to get the same result are also welcome.
A document from the collection looks like this (those are manhattan coordinates, if you draw a line in sequence from one coordinate to the next, it wraps manhattan)
{
"__v" : 1,
"_id" : ObjectId("53220803a74a16da9c729202"),
"name" : "Manhattan",
"boundary" : {
"type" : "Polygon",
"coordinates" : [
[
[
-74.01237999999999,
40.69967
],
[
-73.97895,
40.71076
],
[
-73.97169,
40.73049
],
[
-73.92828,
40.79605
],
[
-73.95547999999999,
40.82635
],
[
-74.00901,
40.75431
],
[
-74.01961,
40.7059
]
]
]
}
}
i then use the following query to make my check
db.collection.find( { boundary :
{ $geoIntersects :
{ $geometry :
{ type : "Point" ,
coordinates : [ [user_long, user_lat] ]
} } } } ).exec(function(err, city){
console.log(err, "error");
res.send({agent_count : city});
});

MongoDB can't parse query (2dsphere): $geoWithin:

I have the following objects in my Collection that look like the following:
{
"_id" : ObjectId("527d33a8623f6efd1c997440"),
"location" : {
"geometry" : {
"type" : "Point",
"coordinates" : [
-78.4067,
37.26725
]
},
"type" : "Feature",
"properties" : {
"name" : "Something here"
}
},
"name" : "Name of Object"
}
I have the following index:
{
"location.geometry" : "2dsphere"
}
I can do the following:
db.myCollection.find({'location.geometry':{'$near':{'$geometry':{'type':"Point", 'coordinates': [-78.406700,37.267250]}, '$maxDistance' : 1000 }}})
However, I can Not do the following:
db.myCollection.find( { 'location.geometry': { '$geoWithin':
{ '$geometry' :
{ 'type' : "Polygon",
'coordinates' : [ [ -118.108006, 34.046072], [ -117.978230, 34.041521] , [ -117.987328,33.913645 ]] } }
} } )
As it returns with the error:
error: {
"$err" : "can't parse query (2dsphere): { $geoWithin: { $geometry: { type: \"Polygon\", coordinates: [ [ -118.108006, 34.046072 ], [ -117.97823, 34.041521 ], [ -117.987328, 33.913645 ] ] } } }",
"code" : 16535
}
Am I using geoWithin wrong? Can it not be used on this index?
The polygon that you are providing for $geowithin query is incorrect. A polygon needs to have the same start and end point as per GeoJSON definition.
The correct query is:
db.myCollection.find( { 'location.geometry':
{ '$geoWithin':
{ '$geometry' :
{ 'type' : "Polygon",
'coordinates' : [
[ -118.108006, 34.046072],
[ -117.978230, 34.041521],
[ -117.987328,33.913645 ],
[ -118.108006, 34.046072]
]
}
}
}
}
);
Notice the updated coordinates array.
Clearly, what is mentioned here in MongoDB docs about implicit connection of Polygons is NOT incorrect. It says that when you define the polygon using $polygon in MongoDB, only then is the connection implicit. It says nothing about being smart and making an implicit connection in the GeoJSON polygon provided to the query.
In fact, if for some GeoJSON variable you are saying that its type is polygon and you are not connecting its start with the end, then you have not created a correct GeoJSON polygon in the first place.
There is an error in the MongoDB documentation on $geoWithin queries. While the documentation states that:
The last point specified is always implicitly connected to the first.
You can specify as many points, and therefore sides, as you like.
This is incorrect. The polygon needs to be closed. There is an open ticket about this in MongoDB Jira:
https://jira.mongodb.org/browse/DOCS-2029
So your first and last points need to be equal - you cannot depend on MongoDB to implicitly draw the last line of the polygon.