问题
i have this situation.
In our database have "stores" documents, and "branch offices" as subdocuments ( One to Many ).
Each branch office have a location attribute, which is indexed for geolocation searching.
So, the problem is:
{store:{"name":"store1", branchoffices:[{"name":"bo1","location":[ -70.64341379999999, -33.4268697 ]}, {"name":"bo2","location":[80.4,43.3]}]}}
If i do this aggregation:
Store.collection.aggregate(
[{
"$geoNear"=>{"near"=>[ -70.64341379999999, -33.4268697 ],
"distanceField"=>"distance",
"maxDistance"=>0.0900899926955034}
},
{ "$unwind" => "$branchoffices"}
]
The result it's each branch office with the distance field repeated in both rows or records returned. When just found one branchoffice in geoNear.
Exists some way for just return the subdocument or subdocuments that result for the geolocation searchs ?
Thanks.
回答1:
The option under $geoNear is includeLocs
as follows:
Store.aggregate([
{ "$geoNear": {
"near": [ -70.64341379999999, -33.4268697 ],
"distanceField": "distance",
"maxDistance": 0.0900899926955034,
"includeLocs": "location"
}}
])
The output has the matched "location" to the "distance" in the output field:
{
"_id" : ObjectId("5507b18d1c3bdce0535aecd0"),
"name" : "store1",
"branchoffices" : [
{
"name" : "bo1",
"location" : [
-70.64341379999999,
-33.4268697
]
},
{
"name" : "bo2",
"location" : [
80.4,
43.3
]
}
],
"distance" : 0,
"location" : [
-70.64341379999999,
-33.4268697
]
}
If you wanted the specific sub-document in the array that was used in the match in full detail then you could continue with a filter using $redact:
Store.aggregate([
{ "$geoNear": {
"near": [ -70.64341379999999, -33.4268697 ],
"distanceField": "distance",
"maxDistance": 0.0900899926955034,
"includeLocs": "location"
}},
{ "$redact": {
"$cond": [
{ "$eq": [ "$location", "$$ROOT.location" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
Or in versions prior to MongoDB 2.6 like this:
Store.aggregate([
{ "$geoNear": {
"near": [ -70.64341379999999, -33.4268697 ],
"distanceField": "distance",
"maxDistance": 0.0900899926955034,
"includeLocs": "location"
}},
{ "$unwind": "$branchoffices" },
{ "$project": {
"name": 1,
"branchoffices": 1,
"matched": {
"$eq": [ "$location", "$branchoffices.location" ]
}
}},
{ "$match": { "matched": 1 } },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"branchoffices": { "$push": "$branchoffices" },
"distance": { "$first" "$distance" }
}}
])
You should probably note that using objects within a sub-document is not always an optimal solution and is generally not suited to a variety of tasks. For example, if your data in the array possibly contained "multiple" locations that would be "near" the queried point, then only the singular "nearest" point would be able to be matched like this.
So whilst you can do this, it is best to consider how you are using it and the results you expect. In most cases, location data should be listed in it's own document rather than under a sub-document array as is done here.
来源:https://stackoverflow.com/questions/29091420/gets-sub-documents-by-geonear-mongodb