首页 > 解决方案 > $geoNear 用于列表嵌入位置和列表中所有位置的返回距离

问题描述

我有一个user收藏:


{
    "name": "David",
    "age": 20,
    "addresses": [
        {
            "radius": 10000,
            "location": {
                "type": "Point",
                "coordinates": [106.785299, 20.999999]
            }
        },
        {
            "radius": 30000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            }
        }
    ]
}

每个用户将拥有一个或多个地址。我想用一个点计算这些地址之间的距离,然后使用计算出的距离与每个地址的半径进行比较。如果距离 < 半径,则保留地址,否则从addresses列表中删除地址。我正在使用以下查询:


db.collection.aggregrate(
    {
        "$geoNear": {
            "near": {"type": "Point", "coordinates": [ 105.823620, 21.006047 ]},
            "distanceField": "distance",
            "key": "addresses.location"
        }
    }
)

但是这个查询只返回最近地址的距离,像这样:


{
    "name": "David",
    "age": 20,
    "addresses": [
        {
            "radius": 10000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            }
        },
        {
            "radius": 30000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            }
        }
    ],
    "distance": 110000 // <--- distance is added here, just for nearest addrest
}

我的预期结果:


{
    "name": "David",
    "age": 20,
    "addresses": [
        {
            "radius": 10000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            },
            "distance": 2000``// <------ add distance here for each addesss`
        },
        {
            "radius": 30000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            },
            "distance": 30000 // <------ add distance here for each addesss
        }
    ]
}

所以下一阶段我可以比较distanceradius保持正确的地址有人知道怎么做吗?谢谢

标签: mongodbaggregation-framework

解决方案


您需要将每个地址存储在单独的文档中:

{
    "_id" : ObjectId("5ec77d127df107cd889d567d"),
    "name" : "David",
    "age" : 20,
    "addresses" : {
        "radius" : 10000,
        "location" : {
            "type" : "Point",
            "coordinates" : [ 
                105.785299, 
                20.979733
            ]
        }
    }
},
{
    "_id" : ObjectId("5ec77f7843732e8f9a63bf67"),
    "name" : "David",
    "age" : 20,
    "addresses" : {
        "radius" : 30000,
        "location" : {
            "type" : "Point",
            "coordinates" : [ 
                105.795299, 
                20.989733
            ]
        }
    }
}

现在,我们执行$geoNear$group阶段:

db.user.aggregate([
  {
    "$geoNear": {
      "near": {
        "type": "Point",
        "coordinates": [
          105.823620,
          21.006047
        ]
      },
      "distanceField": "distance",
      "key": "addresses.location"
    }
  },
  {
    "$group": {
      "_id": "$name",
      "name": {
        "$first": "$name"
      },
      "age": {
        "$first": "$age"
      },
      "addresses": {
        "$push": {
          "$mergeObjects": [
            "$addresses",
            {
              "distance": "$distance"
            }
          ]
        }
      }
    }
  }
])

推荐阅读