Gets sub documents by geoNear - MongoDB

蹲街弑〆低调 提交于 2019-12-10 11:24:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!