How to dynamically filter datasets based on their location - mongodb

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

Related

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?

$centerSphere is not returning any geojson polygons (mongoDB)

I am having a lot of trouble with the following Mongo query
location: { $geoWithin: { $centerSphere: [[lon,lat],radians] } }
It only returns geoJSON Points and ignores all my geoJSON Polygons for some reason. The documentation states:
You can use the $centerSphere operator on both GeoJSON objects and legacy coordinate pairs.
I am using Mongoose to run the queries and my geoJSON is coverted from WellKnown Text by the NPM module wellknown. This is how my geoJSON looks after the wellknown module has converted them:
"location": {
"coordinates": [
22.1,
33.3
],
"type": "Point"
}
and
"location": {
"coordinates": [
[
[
43,
30
],
[
40,
28
],
[
49,
27
],
[
43,
30
]
],
[
[
44,
28
],
[
44.7,
28.8
],
[
46,
28
],
[
44,
28
]
]
],
"type": "Polygon"
}
My Mongoose schema is defined as:
location: {
type: schema.Types.Mixed,
index: '2dsphere',
required: false
}
I should add that the withinPolygon methods work as expected and I get both the Points and Polygons returned. The following works completely fine:
location: { $geoWithin: { $geometry: geoJSON } }
Thank you for any help. I have read the documentation and can't see anywhere where it mentions that the $centerSphere only returns geoJSON Points.
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 more information about the update.

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?

Proximity query doesn't match LineString points between the ends

I have defined a "2dsphere" index for field loc in collection c:
db.c.createIndex( { loc : "2dsphere" } )
I have the following document in c collection. It is a LineString from [0, 0] to [10, 10]:
db.c.insert({"name": "myLine", "loc": { type: "LineString", coordinates: [ [ 0, 0 ], [ 10, 10 ] ] }})
Note that [5, 5] would be a point on the line. However, a proximity query (using the $near operator) centered at [5, 5] doesn't match the document:
db.c.find({
loc: {
$near: {
$geometry: {
type: "Point" ,
coordinates: [ 5, 5 ]
},
$maxDistance: 0.1,
}
}
})
Maybe LineString doesn't work that way and only the end points ([0, 0] and [10, 10] in this case) are relevant from geo spatial queries point of view? In that case, is a limitation in MongoDB geo spacial queries implementation or is a limitation in the GJSON standard?
(Until I did this little experiment I thought that the difference between LineString and MultiPoint was that the former takes into account the line connecting the points while the later only takes into account the points at the ends of lines. After this experiment, I don't see the differences...).
I have to chosen between mongodb and postgis. But mongodb has this negative point. See the case: Find points near LineString in mongodb sorted by distance

MongoDB: Select all polygons within the radius of a point

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