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
]
}
}
Related
I'm using MongoDB to store about 1 million documents representing regions.
Each document contains a coordinates record in the following format
"coordinates" : {
"longitude" : -77.02687,
"latitude" : 38.888565
}
Given a set of coordinates { x, y }, what query should I run to find the region ( document ) that is closest to it?
Based on the MongoDB geospatial-queries documentation the answer is quite simple.
In order to query for locations near a region you should follow these steps
Step 1
Create an index on the location field
db.places.createIndex( { location: "2dsphere" } )
Step 2
Find regions close to { -73.9667, 40.78 } ordered by closest locations
db.places.aggregate( [
{
$geoNear: {
near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
spherical: true,
query: { category: "Parks" },
distanceField: "calcDistance"
}
}
] )
I am not sure if there is a way to do this. I need to have a circle in mongodb and run a query against that with a box using $box to see if these two shapes overlap or not. However, Geojson does not support circles. What would be the best way to get this done?
The circle is stored like this:
places = {
...
"location": {
"type": "Point",
"coordinates": [
-79.390756,
43.706685
]
},
"radius": 100
}
I have two specific problems:
The first issue is that maxDistance is stored in the same object as the Geojson object and cannot be used in a $near query with $maxDistance; it only takes a number.
I do a partial postal code/ zip code search on Google Geocoding Api which returns a box with two corner coordinates like this:
"geometry": {
"bounds": {
"northeast": {
"lat": 43.710565,
"lng": -79.37363479999999
},
"southwest": {
"lat": 43.690848,
"lng": -79.40025399999999
}
}
As far as I know,I cannot use $box as it only works with $geoWithin.
Edit 1:
My initial plan with the circle and the box changed mainly because I did not find a suitable and efficient solution to this problem. Instead of checking if the circle overlaps with the box, now I check if a Geojson point is inside the circle as follows:
db.places.aggregate([
{"$geoNear": {near: { type: "Point", coordinates: [ -80.459293, 40.713640] },
distanceField: "dist.calculated", maxDistance: 100000,
key: 'myLocation', query: { 'SomeField': "..." }, spherical: true}},
{ "$match" : {$expr:{ $lte:['$dist.calculated', 'radius']}}}])
The problem here is that I d have to run a query within 100 KM first and then in another stage of the aggregation check the distance.
Is there a more efficient way to implement this? Thanks.
You can store a circle as point and radius. And you can use a $near query with a point and $maxDistance in meters which is the radius of the circle. See MongoDB Documentation.
Query to find all location, geometry field of the collection, at a certain distance from a point.
db.places.find(
{
location:
{ $near :
{
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$maxDistance: 5000
}
}
}
)
Query to find if a given geometry (point, polygon(rect too)) in a query intersects with a geometry of a field in the collection.
//find quests bots that matches the users location
await Collection.find({ geometry:
{ $geoIntersects:
{
{
type: "Point",
coordinates: [
-73.99460599999999,
40.7347229
]
}
}
}
});
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?
I have a model like the following:
var locSchema = new Schema({
loc:{
type:[Number],
index: '2dsphere'
}
});
And, I'm using $geoNear command like this:
Location.aggregate([{
"$geoNear": {
"near": {
"type": "Point",
"coordinates": [parseInt(req.query.longitude), parseInt(req.query.latitude)]
},
"spherical": true,
"distanceField": "distance"
}
});
I'm uploading the longitude and latitude from a location and saving it in the model. And, I'm retrieving the models using the same location in geoNear command. That is same longitude and latitude.
But, in the result, I have distance as a big float where I should get 0 (or at least near 0).
{
_id: "578ca6613525d44b3f5171b8",
loc: [
79.9811093,
14.450403300000001
],
distance: 117139.297675591
}
I tried the distanceMultiplier but that does not seem to work. Where am I mistaken?
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