Test data:
db.test.insert({ "locs" : [
{ "name" : "a", "address" : { "type" : "Point", "coordinates" : [ 0, 0 ] } },
{ "name" : "b", "address" : { "type" : "Point", "coordinates" : [ 1, 1 ] } },
{ "name" : "c", "address" : { "type" : "Point", "coordinates" : [ 2, 2 ] } }
]})
db.test.insert({ "locs" : [
{ "name" : "h", "address" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } }
]})
db.test.ensureIndex( { "locs.address" : "2dsphere" } )
Query:
db.test.aggregate([
{ "$geoNear" : { near : { "type" : "Point", "coordinates" : [ 1, 1 ] }, distanceField: "dist.calculated", maxDistance: 5000, includeLocs: "dist.location", num: 5, limit: 200, spherical: true } },
{ "$unwind" : "$locs" },
{ "$redact" : {
"$cond" : {
if : { "$eq" : [ { "$cmp" : [ "$locs.address", "$dist.location" ] }, 0 ] },
then : "$$KEEP",
else : "$$PRUNE"
}
}
}
])
The geoNear stage will output the entire documents with a "dist" field showing the distance and matching location field:
{
"_id" : ObjectId("5786fa0ddeb382a191a43122"),
"locs" : [ { "name" : "h", "address" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } } ],
"dist" : {
"calculated" : 0,
"location" : { "type" : "Point", "coordinates" : [ 1, 1 ] }
}
}
We $unwind the "locs" array to allow for accessing individual array elements. The dist field is preserved.
The $redact field can then be used to remove any array elements where the address does not match the location returned by the $geoNear stage.
Results:
{
"_id" : ObjectId("5786fa0ddeb382a191a43121"),
"locs" : { "name" : "b", "address" : { "type" : "Point", "coordinates" : [ 1, 1 ] } },
"dist" : { "calculated" : 0, "location" : { "type" : "Point", "coordinates" : [ 1, 1 ] } }
}
{
"_id" : ObjectId("5786fa0ddeb382a191a43122"),
"locs" : { "name" : "h", "address" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } },
"dist" : { "calculated" : 1574.1651198970692, "location" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } }
}
references:
https://stackoverflow.com/questions/38339995/mongodb-geonear-with-multiple-matches-in-same-document
No comments:
Post a Comment