MongoDB Geospacial Query Spheres重叠单点

Jef*_*eff 6 geospatial mongodb mongodb-query aggregation-framework

我试图在MongoDB中创建一个geospacial查询,查找与单个点重叠的所有圆(具有不同的半径).

我的数据看起来像这样:

{
    name: "Pizza Hut", 
    lat: <latitude>
    lon: <longitude>
    radius: 20
    ...
}
Run Code Online (Sandbox Code Playgroud)

基本上,我试图完全按照SO帖子中的描述进行操作,但使用MongoDB - 获取所有点(半径为圆),重叠给定点

geoIntersects(http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/)看起来就像我需要的那样.但在我的例子中,lat,lon和radius与每个mongodb文档一起存储,并且不是作为查询一部分的固定半径.可以这样做吗?

一种不同的方法是找到距离我的查询点的距离小于其半径字段值的所有文档(即上例中的20km).如何构建MongoDB查询,其中计算的距离是查询过滤条件的一部分?

谢谢!

Nei*_*unn 7

好吧,如果你可以使用GeoJSON对象来表示位置会更好,但是目前支持的类型实际上是有限的,因此不支持理想的"Circle"类型.

你能做的最接近的是一个近似圆形的"多边形",但这可能只是为了这个查询目的而构建的工作量太多了.执行此操作然后应用的另一个问题$geoIntersects是结果将不会被距离查询点的距离"排序".这似乎与寻找原产地"最近的比萨饼"的目的相反.

幸运的是$geoNear,从MongoDB 2.4及更高版本开始,聚合框架中添加了一个操作.这里的好处是它允许在结果中"投影"距离场.然后,这允许您对服务器上的逻辑过滤进行"距半径"约束的点与距离原点的距离.它还允许在服务器上进行排序.

但是您仍然需要更改架构以支持索引

db.places.insert({
    "name": "Pizza Hut",
    "location": { 
        "type": "Point",
        "coordinates": [
            151.00211262702942,
            -33.81696995135973
        ]
    },
    "radius": 20
})

db.places.ensureIndex({ "location": "2dsphere" })
Run Code Online (Sandbox Code Playgroud)

对于聚合查询:

db.places.aggregate([

    // Query and project distance
    { "$geoNear": {
        "near": { 
            "type": "Point",
            "coordinates": [ 
                150.92094898223877,
                -33.77654333272719
            ]
        },
        "distanceField": "distance",
        "distanceMultiplier": 0.001,
        "maxDistance": 100000,
        "spherical": true
    }},

    // Calculate if distance is within delivery sphere
    { "$project": {
         "name": 1,
         "location": 1,
         "radius": 1,
         "distance": 1,
         "within": { "$gt": [ "$radius", "$distance" ] }
    }},

    // Filter any false results
    { "$match": { "within": true } },

    // Sort by shortest distance from origin
    { "$sort": { "distance": -1 } }
])
Run Code Online (Sandbox Code Playgroud)

基本上这说,

*"距离指定位置100公里,找到距离该点距离的地方.如果距离在"交付半径"范围内,则返回它们,按最近的顺序排序

您可以传递其他选项$geoNear以优化结果,并在需要时返回超过默认的100个结果,并基本上将其他选项传递给查询,例如"类型"或"名称"或您拥有的任何其他信息在文件上.