MongoDB How to find which polygon contains a specified Point? - mongodb

I insert many polygons into MongoDB(2.4.8), and hope find the polygon a specified Point sits in. It seems a common question. But after reading all docs from google, I didn't get the result. So create this question.
e.g.
db.addr_poly.insert(
{ loc :
{ type : "Polygon" ,
coordinates : [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ] ]
} })
db.addr_poly.insert(
{ loc :
{ type : "Polygon" ,
coordinates : [ [ [ 0 , 0 ] , [ -3 , -6 ] , [ -6 , -1 ] , [ 0 , 0 ] ] ]
} })
Now how to find the polygon which contains Point(1,1)?
Anybody can help me? Thanks a lot!

Use the $geoIntersects operator. It queries for all shapes which intersect the GeoJSON object you pass. When you pass a point to it, it should return all shapes which include that point. Keep in mind that the $geoIntersects operator only works for 2dsphere indexes, not for 2d indexes.

As #philipp said, you should use the $geoIntesects operator. I was having the hardest time trying to figure out the query. I figured I would share what it looks and it might save someone the trouble later.
db.addr_poly.find({
loc:{
$geoIntersects: {
$geometry: {
type: "Point" ,
coordinates: [1, 1]
}
}
}
});

Related

mongoDB Geospatial Query $geoWithin got error 'Loop is not closed'

i am newbie for Geospatial Query of mongodb and i try search for point within polygon which have code like below :
db.properties.find({
location:{
$geoWithin : {
$geometry : {
type:"Polygon",
coordinates: [[
[104.9172382, 11.57934524],
[104.9146632, 11.5724502],
[104.92753788, 11.57976566]
]]
}
}
}
})
and my data table look like below :
i want to get result of all point is inside polygon.but i really have no clue
this error alway popup
|____/ Mongo Server error (MongoQueryException): Query failed with
error code 2 and error message 'Loop is not closed: [ [ 104.9172382,
11.57934524 ], [ 104.9146632, 11.5724502 ], [ 104.92753788, 11.57976566 ] ]' on server
thank for any idea !
i found answer that we need to start coordinate and close coordinates are the same value.
db.properties.find({
location:{
$geoWithin : {
$geometry : {
type:"Polygon",
coordinates:[
[
[ 104.9212999921292 , 11.575955591122819 ] , // start loop
[ 104.92129194550216 , 11.575198826419006 ] ,
[ 104.92298978380859 , 11.575238241297862 ] ,
[ 104.92291736416519 , 11.576023910057827 ] ,
[ 104.9212999921292 , 11.575955591122819 ] // close loop
]
]
}
}
}
})

How to run geosaptial Query in Mongo compass UI?

I have used Mongo Compass.. i want run following geospatial query in Mongo compass
db.restaurants.find( { location : { $geoWithin :
{ $centerSphere :
[ [ 88 , 30 ] , 10 / 3963.2 ]
} } } )
Above Query is actual query. and also i have 2 collection these are restaurants and neighborhoods..
see following image
You can also click at any point on the map, hold shift key and drag the pointer to somewhere else. It will build a query for you. So you can use it as a sample for building your own.
Try to enter only the query object into the input field, without db.restaurants.find... like so:
{ location : { $geoWithin :
{ $centerSphere :
[ [ 88 , 30 ] , 10 / 3963.2 ]
} } }

Geo-query using a circle as area to match at least one of the points of MultiPoint object in MongoDB

I have the following document in the entities collection at Mongo (a 2dsphere index for location.coords is in place):
> db.entities.find({},{location: 1}).pretty()
{
"_id" : {
"id" : "en3",
"type" : "t",
"servicePath" : "/"
},
"location" : {
"attrName" : "position",
"coords" : {
"type" : "MultiPoint",
"coordinates" : [
[
-3.691944,
40.418889
],
[
4.691944,
45.418889
]
]
}
}
}
As far as I have checked, $geoWithin only matches when the geometry includes all the points of the MultiPoint, e.g:
> db.entities.find({"location.coords": { $geoWithin: { $centerSphere: [ [ -3.691944, 40.418889 ], 0.002118976612776644 ] } } })
// Small circle centered at first point, but without covering the second point: it doesn't matchh
> db.entities.find({"location.coords": { $geoWithin: { $centerSphere: [ [ -3.691944, 40.418889 ], 2 ] } } })
// Big circle centered at first point covering also the second point: it matches
However, I would like to have a query to match if at least one point of the MultiPoint matches. I have read about the $geoIntersects operator. I have tried just replace $geoWithin by $geoIntersect in my query, but it doesn't work:
> db.entities.find({"location.coords": { $geoIntersects: { $centerSphere: [ [ -3.691944, 40.418889 ], 0.002118976612776644 ] } } })
error: {
"$err" : "Can't canonicalize query: BadValue bad geo query",
"code" : 17287
}
Reading the $geoIntersects operator, it seems that it can be only used with polygons or multi-polygons, but it doesn't mention circles. I wonder if I'm missing something, because this "asymmetry" between $geoWithin and $geoIntersects seems to be a bit weird...
Thus, is there any way of doing a geo-query using a circle as area to match at least one of the points of MultiPoint object?
I think I have found the answer at the end. It can be done with the $near operator, in the following way:
db.entities.find({"location.coords": { $near: { $geometry: { type: "Point", "coordinates": [ -3.691944, 40.418889 ] }, $maxDistance: 0.5 } }})

Different semantics in $not $geoWithin with Polygon geometries between MongoDB 2.4 and 2.6

I have run the following experiment, comparing how MongoDB 2.4 and MongoDB 2.6 behave regarding the $geoWithin selector combined with $not with Polygons (i.e. "outside polygon" query). I'm including the particular versions (three numbers), alghouth I guess it would happend the same with other minor versions of 2.4 and 2.6.
Two documents (A and B) are created in a given collection: A with p field set to coordinates [1, 1] and B without p field. Next, I create a 2dsphere index in p and do a query for the area outside a triangle which vertices are [0, 0], [0, 4]and [4, 0]. Note that A is inside that polygon (so it is not supposed to be got with this query).
With 2.4.9:
db.x.insert({k: "A", p: [1,1]})
db.x.insert({k: "B"})
db.x.ensureIndex({"p": "2dsphere"})
db.x.find({p: { $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] } } } }})
--> no result
Makes sense: A is not returned (as it is inside the polygon) and B is not returned (given that it doesn't have a p field).
Next, testing with 2.6.1 the same script:
db.x.insert({k: "A", p: [1,1]})
db.x.insert({k: "B"})
db.x.ensureIndex({"p": "2dsphere"})
db.x.find({p: { $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] } } } }})
-> result: B
It seems that in 2.6 semantics have changed, so when the 2dsphere-indexed field is not in a given document, that document is considered outside any possible polygon.
Changing semantics between versions is ok as long as some mechanism in the new version allows to configure behaviour in the old way. I thought that mechanism was using { "2dsphereIndexVersion" : 1 } at index creation time (based on what I read here, maybe I misunderstood that information...). However, the result (with 2.6.1 again) is the same:
db.x.insert({k: "A", p: [1,1]})
db.x.insert({k: "B"})
db.x.ensureIndex({"p": "2dsphere"}, { "2dsphereIndexVersion" : 1 })
db.x.find({p: { $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] } } } }})
-> result B
Thus, is there any way of using MongoDB 2.6 with the same semantics that MongoDB 2.4 in the sense that any document without the 2dsphere-indexed not to be returned in "outside poylgon" queries?
The query result in 2.6 is right - the query result in 2.4 I think I would call incorrect. Technically, your query asks for documents that do not match the $geoWithin condition. The "k" : "B" document does not match the $geoWithin condition, so it should be returned by the query. You can drop results without the p field using $exists:
db.x.find({
"p" : {
"$exists" : true,
"$not" : { "$geoWithin" : {
"$geometry" : {
"type": "Polygon",
"coordinates" : [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ]
}
} } }
})
Also note that 1) your $not query isn't actually using the geo index, as you can check with an explain, and 2) when using a 2dsphere index you should store points as GeoJSON
{
"k" : "A",
"p" : {
"type" : "Point",
"coordinates" : [1,1]
}
}
Technically it's required in MongoDB >= 2.6, and the docs say it should be an error not to use GeoJSON, but it seems to work for us.

Sorting on GeoWithin MongoDB

So I made this query:
db.zips.find( { loc : { $geoWithin : { $box :[ [ -90 , 30 ] , [ -80 , 40 ] ] } } } )
And here is one (out of many) outputs:
{ "city" : "APISON", "loc" : [ -85.016404, 35.014926 ], "pop" : 1614, "state" : "TN", "_id" : "37302" }
My question is how would i be able to sort this by population and limit it to 10? When i try {$sort{pop:1}} i get errors it doesn't know pop, also when i add {$limit:10} at the end or my query it doesn't limit it to 10 entries but only shows me the last column.
Any help would be greatly appreciated!
db.zips.find({loc:{$geoWithin:{$box:[[-90,30],[-80,40]]}}}).sort({pop:1}).limit(10)