Query Location With kilometer Radius in Mongodb? - mongodb

I have a collection called restaurants.. and also i have formatted into geoJSON and I tried to query the following way
db.restaurants.find({ location:
{ $geoWithin:
{ $centerSphere: [ [ -73.93414657, 40.82302903 ], 5 / 3963.2 ] } } })
I have mentioned radius 5/3963.2 (calculation in miles).. but I need radius distance in kilometer like { $centerSphere: [ [ -73.93414657, 40.82302903 ], 5] }
I need to mentioned radius in kilometer
How to do it?

MongoDB expects values in radians.
To convert distance to radians, simply divide the distance value to the radius of the sphere (earth), where:
3963.2 is radius of earth in Miles.
6378.1 is radius of earth in Km.
db.restaurants.find({ location:
{ $geoWithin:
{ $centerSphere: [ [ -73.93414657, 40.82302903 ], 5 / 6378.1 ] } } })

Related

How to dynamically filter datasets based on their location

I'm trying to achieve the following behaviour with a mongodb query:
I have documents which have a field location and a 2dshere geospatial index on that field
The documents also have a field maxdistance
The location of the user is available in the variable user.gps as a GeoJSON point
The query currently looks like this:
query["location"] = {
$nearSphere: {
$geometry: user.gps,
$maxDistance: filterDistance
}
};
This query successfully selects all the datasets in a given filterDistance relative to the user.
What i'd like to have now is "If document.maxdistance field > 0 and the distance to the user is greater than document.maxdistance" do not select the dataset.
So i have documents that should not be found if the user lives in a distance greater than a given distance saved inside the document.
I don't know hot to express this in a mongodb query and i couldn't find any example of such a query.
$near/$nearSphere don't support per-document distance. Only per query. The main reason is sorting by distance. If you need only filtering you can use $geoIntersects/$geoWithin, but you will need to change documents to contain a polygon of the covered area, like a circle Pi*2*distance around it's location.
Example:
Assuming you have a document:
{
loc: { type: "Point", coordinates: [ 10, 20 ] },
distance: 10
}
So that it is returned when user's coordinate is within the radius, e.g. [12, 25], and is not returned when user's coordinate is outside, e.g. [12,30].
For that documents should be updated to convert loc/distance pair to a polygon. For the sake of simplicity I'll use octagon, but you may want to increase number of vertices for more accurate results:
{
loc: { type: "Point", coordinates: [ 10, 20 ] },
distance: 10,
area: {
type : "Polygon",
coordinates : [[
[ 17, 27 ],
[ 10, 30 ],
[ 3, 27 ],
[ 0, 20 ],
[ 3, 13 ],
[ 10, 10 ],
[ 17, 13 ],
[ 20, 20 ],
[ 17, 27 ]
]]
}
}
Then you can use $geoIntersects to find documents which area includes user's coordinates:
db.collection.find({
area: {
$geoIntersects: {
$geometry: { type: "Point" , coordinates: [ 12, 25] }
}
}
})

How to Calculate the LineString distance in kilometers?

Assuming I have the following LineString in any document:
{
type: "LineString",
coordinates: [
[ 53.3477, -6.2597 ], [ 51.5008, -0.1224 ],
[48.8567, 2.3508], [52.5166, 13.3833]
]
}
When rendering this line on a map the result is:
How can I get the total distance of this LineString in kilometers, using the mongodb GeoQuery features?

Difference between $center and $centerSphere in Mongo?

Currently, we are using $centerSphere to find nearby cities. One example is that for the locality Bee Cave in Texas, USA, $centerSphere correctly found the only city Austin in a radius of 30 kilometers (As per documentation, it was converted in radians). Now, for the city Lautoka in Fiji (Lat: -17.6169618, Long: 177.4504609) it is giving the error "Spherical distance would require (unimplemented) wrapping". This is question one: what does this error mean?
We tried implementing the same by using $center. I'm aware we need to give distance in miles rather than radians. After implementing, for Bee Cave, I got US cities that were thousands or hundreds of miles away. One example is Albuquerque. I'm unable to understand why these cities are coming even after following Mongo documentation properly.
I'm using the query (for Bee Cave, TX)
db.places.find{
"geo": {
$geoWithin: { $center: [ [ -97.9524, 30.3061 ] , 18.64 ] }
}
}
$centerSphere can't handle large distances, especially if it has to wrap around the poles, see this JIRA ticket.
Regarding $geoWithin it does not accept the distance in miles, but rather the circle’s radius as measured in the units used by the coordinate system, so latitude and longitude as per the documentation. That results in a very large bounding box that does include Albuquerque
You use $near instead that allows to specify a radius in meters. For example if you use this as your test data:
db.places.insert( {
name: "Bee Cave, Texas",
location: { type: "Point", coordinates: [ -97.9524, 30.3061 ] }
} );
db.places.insert( {
name: "Austin, Texas",
location: { type: "Point", coordinates: [ -97.654724, 30.210768 ] }
} );
db.places.insert( {
name: "Albuquerque",
location: { type: "Point", coordinates: [ -106.621216, 35.113281 ] }
} );
db.places.createIndex( { location: "2dsphere" } )
You can write the following query using the factor 1609.344 to convert miles to meter
db.places.find(
{
location:
{ $near:
{
$geometry: { type: "Point", coordinates: [-97.9524, 30.3061 ] },
$maxDistance: 20*1609.344
}
}
}
)
This query returns both Bee Cave,TX and Austin, TX:
{
"_id":ObjectId("5a7190124f0cd7075d349bbc"),
"name":"Bee Cave, Texas",
"location":{
"type":"Point",
"coordinates":[
-97.9524,
30.3061
]
}
}{
"_id":ObjectId("5a7190124f0cd7075d349bbd"),
"name":"Austin, Texas",
"location":{
"type":"Point",
"coordinates":[
-97.654724,
30.210768
]
}
}

Find users in mongodb based on distance with geospatial query

I am working on some project in which I have to find some users of one particular region, like greater than 20 km and less than 40 km, for which I have written query
query.location = {
$nearSphere:
{
$geometry:
{
type:'Point',
coordinates:
[
bookingData.bookingAddress.location.coordinates[0],
bookingData.bookingAddress.location.coordinates[1]
]
},
$minDistance: (20*1000),
$maxDistance: (40*1000) // this distance should be in meters (in our case I have set 40 km)
}
};
But the result doesn't show anything, even if I have the users of that latitude and longitude in my database.
When I run query
query.location = {
$nearSphere:
{
$geometry:
{
type:'Point',
coordinates:
[
bookingData.bookingAddress.location.coordinates[0],
bookingData.bookingAddress.location.coordinates[1]
]
},
$maxDistance: (40*1000) // this distance should be in meters (in our case I have set 40 km)
}
};
it shows correct result.
This is the model I have made for storing location :
bookingAddress : {
location : {
'type':{type:String,enum:CONST.GEO_JSON_TYPES.Point,default: CONST.GEO_JSON_TYPES.Point},
coordinates: {type: [Number], default: [0, 0],required: true}
},
address : {type : String,default:null}
},
Where am I going wrong?

MongoDB 2dsphere index error

Error creating index for table 'MSParcels': WriteConcern detected an error 'Can't extract geo keys from object, malformed geometry?:
{ type: "Polygon", coordinates:
[ [ [ -122.118466012, 47.6511409501, 0.0 ],
[ -122.118687874, 47.6508529655, 0.0 ],
[ -122.118817718, 47.650852731, 0.0 ],
[ -122.118890754, 47.650852592, 0.0 ],
[ -122.118891979, 47.651140118, 0.0 ],
[ -122.118703033, 47.6511404878, 0.0 ],
[ -122.118466012, 47.6511409501, 0.0 ] ] ] }
Problem is, I'm copying from SQL Server where identical coordinates pass STIsValid
Using C# driver MongoDB.Driver.Builders.IndexKeys.GeoSpatialSpherical
Mongo version 2.4.4
Any advice?
The geojson isn't valid for mongodb- it only accepts x,y and not z coordinates (altitude). This is because it only has 2D indexing / querying capabilities.
You need to remove the z coordinates from the geojson document to be something like:
{ type: "Polygon", coordinates:
[ [ [ -122.118466012, 47.6511409501],
[ -122.118687874, 47.6508529655],
[ -122.118817718, 47.650852731],
[ -122.118890754, 47.650852592],
[ -122.118891979, 47.651140118],
[ -122.118703033, 47.6511404878],
[ -122.118466012, 47.6511409501] ] ] }
There has been a feature request to improve this - please vote for: SERVER-9220
Your coordinates invalid. A geojson polygon is a array of arrays of arrays with two coordinates not three (the additional 0.0)