Reputation: 1645
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.
Upvotes: 4
Views: 2561
Reputation: 1645
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 ]
}
}
Upvotes: 3