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

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.

Related

What is the correct way to query this document? (If the index is correct)

I've a BigChainDB docker container running in my machine and I'm trying to store and retrieve geospatial data.
I've created through the MongoDB interface a 2dsphere index "location" in the "metadata" collection.
I've checked with the command:
db.people.getIndexes()
And I think that everything it's ok, in fact the result is this:
{
"v" : 2,
"key" : {
"loc" : "2dsphere"
},
"name" : "loc_2dsphere",
"ns" : "bigchain.metadata",
"2dsphereIndexVersion" : 3
}
The document that I've inserted to try some spatial queries is (this is the result of a db.metadata.findOne() query):
{
"_id" : ObjectId("5ccab10a2ce1b70022823a0f"),
"id" : "752ee9abccf83c7fd25d86c9a7d12229ae292fa27544f6881f1dbf97ccd8b413",
"metadata" : {
"location" : {
"type" : "Point",
"coordinates" : [
22.170872,
113.578749
]
}
}
}
But when I use this spatial query nothing is retrieved:
db.metadata.find(
{
"metadata": {
"location": {
$near: {
$geometry: {
type: "Point" ,
coordinates: [ 22 , 113 ]
},
}
}
}
})
I'm doing anything wrong, or is there the possibility that the index doesn't work?
There are a couple of issues here.
The first is that the index is on the field loc whereas your query is querying metadata.location.
If you try creating a 2dsphere index on metadata.location you will see the 2nd error:
"errmsg" : "invalid point in geo near query $geometry argument: { type: \"Point\", coordinates: [ 22.0, 113.0 ] } longitude/latitude is out of bounds, lng: 22 lat: 113",
This error shows that the GEOJSON point defined in your document is invalid, as the latitude value of 113 is outside the acceptable range of [-90, 90].
You would need to correct the data to be valid GEOJSON before indexing.

How do I query a GeometryCollection in 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"
}
}

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

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 2.4.9 $geoWithin query on very simple dataset returning no results. Why?

Here is the output from my mongodb shell of a very simple example of a $geoWithin query. As you can see, I have only a single GeoJson Polygon in my collection, and each of its coordinates lies within the described $box. Furthermore, the GeoJson seems valid, as the 2dsphere index was created without error.
> db.Townships.find()
{ "_id" : ObjectId("5310f13c9f3a313af872530c"), "geometry" : { "type" : "Polygon", "coordinates" : [ [ [ -96.74084500000001, 36.99911500000002 ], [ -96.74975600000002, 36.99916100000001 ], [ -96.74953099999998, 36.99916000000002 ], [ -96.74084500000001, 36.99911500000002 ] ] ] }, "type" : "Feature" }
> db.Townships.ensureIndex( { "geometry" : "2dsphere"})
> db.Townships.find( { "geometry" : { $geoWithin : { "$box" : [[-97, 36], [-96, 37]] } } } ).count()
0
Thanks for any advice.
From documentation:
The $box operator specifies a rectangle for a geospatial $geoWithin query. The query returns documents that are within the bounds of the rectangle, according to their point-based location data. The $box operator returns documents based on grid coordinates and does not query for GeoJSON shapes.
If you insert this document...
db.Townships.insert(
{ "geometry" : [ -96.74084500000001, 36.99911500000002 ],
"type" : "Feature"
})
...your query will found it (but without index support).