I would like to query for all documents that have a polygon that a point is contained in and then for that result set, order it based on closeness of that point to the location of the document.
So imagine I have a database of friends because I'm just that cool, and would like to see which friends are within the my range and would be willing to come play. (each friend has a play-date polygon which is the range they are willing to travel for a play-date)
For all matches I would like to them proceed to see which friend I should call to come based on his actual address and its distance to my point (which is my address) so that I can determine if I am ok with them coming from far away. (lets say 300 meters)
So far I have below a query to find polygons that my point is contained within but I do not know how to include the $near operator of mongodb
For JSON:
{ "_id" : "objid", "FRIEND_NAME" : "Bobby", "GEOMETRY" :
{"type":"Polygon","coordinates":[[[-73.98779153823898,40.718233223261],[-74.004946447098,40.723575517498],[-74.006771211624,40.730592217474],[-73.99010896682698,40.746712376146],
[-73.973135948181,40.73974615047701],[-73.975120782852,40.736128627654],[-73.973997695541,40.730787341083],[-73.983317613602,40.716639396436],[-73.98779153823898,40.718233223261]]]},
"FRIEND_POSITON" : { "lon" : -73.992188, "lat" : 40.729359 } }
This works:
db.friends.find({
"PLAYDATE_RANGE":{
"$geoIntersects":{
"$geometry":{
"type":"Point",
"coordinates":[
-73.98652,
40.752044
]
}
}
}
})
This does not:
db.friends.find([
{
"PLAYDATE_RANGE":{
"$geoIntersects":{
"$geometry":{
"type":"Point",
"coordinates":[
-73.98652,
40.752044
]
}
}
}
},
{
"FRIEND_POSITON":{
"$geoNear":{
"near":{
"type":"Point",
"coordinates":[
-73.98652,
40.752044
]
},
"maxDistance":300
}
}
}
])
Please help me with the query above that does not work.
This requires an aggregate pipeline. As per mogodb doc for $geoNear, You can only use $geoNear as the first stage of a pipeline. The aggregate function has an entry for an additional query which is where the polygon query will be used to narraw down results based on inclusion in the PLAYDATE_RANGE field of the document.
db.friends.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [ -73.98652 , 40.752044 ] },
maxDistance: 300,
distanceField: "friends.calculated_distance",
query: {
"PLAYDATE_RANGE":{
"$geoIntersects":{
"$geometry":{
"type":"Point",
"coordinates":[
-73.98652,
40.752044
]
}
}
}
},
spherical: true
}
}
])
P.S. note that only one geospatial index can be used so put it on the FRIEND_POSITION field. If adding a 2sphere index that requires a correctly formed GeoJSON value, specifically,
"FRIEND_POSITION" : { "type" : "Point", "coordinates" : [ -73.992188, 40.729359 ] }
So the document should look like:
{ "_id" : "objid", "FRIEND_NAME" : "Bobby", "GEOMETRY" : {"type":"Polygon","coordinates":[[[-73.98779153823898,40.718233223261],[-74.004946447098,40.723575517498],[-74.006771211624,40.730592217474],[-73.99010896682698,40.746712376146], [-73.973135948181,40.73974615047701],[-73.975120782852,40.736128627654],[-73.973997695541,40.730787341083],[-73.983317613602,40.716639396436],[-73.98779153823898,40.718233223261]]]}, "FRIEND_POSITION" : { "type" : "Point", "coordinates" : [ -73.992188, 40.729359 ] } }