单点重叠的MongoDB地理空间查询领域 [英] MongoDB Geospacial Query Spheres Overlapping Single Point

查看:133
本文介绍了单点重叠的MongoDB地理空间查询领域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在MongoDB中创建地理空间查询,以查找与单个点重叠的所有圆(半径不同).

我的数据如下所示:

{
    name: "Pizza Hut", 
    lat: <latitude>
    lon: <longitude>
    radius: 20
    ...
}

基本上,我正在尝试完全按照SO帖子中的描述进行操作,但使用MongoDB- http://docs.mongodb.org/手册/参考/运算符/查询/geoIntersects/)看起来像我所需要的.但是在我的情况下,纬度,经度和半径与每个mongodb文档一起存储,而不是查询中包含的固定半径.能做到吗?

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

谢谢!

解决方案

如果您可以使用GeoJSON对象来表示位置,那会更好,但是到目前为止,受支持的类型实际上受到限制,因此不支持理想的圆形"类型.

您能做的最接近的是近似于圆的多边形",但是仅出于此查询目的而构建可能要花费太多的工作.这样做的另一个陷阱,然后应用 $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" })
 

对于聚合查询:

 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 } }
])
 

基本上是说

*"在距给定位置100公里的地方,找到距该点的距离.如果距离在其传递半径"之内,则将其返回,并按最接近的距离排序".

您还可以将其他选项传递给 $geoNear 为了优化结果,并在需要时返回多于默认的100个结果,并基本上传递其他选项来进行查询,例如类型"或名称"或您在文档中拥有的任何其他信息.

I am trying to create a geospacial query in MongoDB that finds all circles (with varying radius) that overlap a single point.

My data looks something like this:

{
    name: "Pizza Hut", 
    lat: <latitude>
    lon: <longitude>
    radius: 20
    ...
}

Basically, I am trying to do exactly what is described in this SO post but with MongoDB - Get all points(circles with radius), that overlap given point

geoIntersects (http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/) looks like what I need. But in my case, the lat, lon, and radius is stored with each mongodb document and is not a fixed radius that is part of the query. Can this be done?

A different approach would be to find all documents whose distance from my query point is less than the value of their radius field (ie - 20km in the example above). How do you structure a MongoDB query where the calculated distance is part of the query filter criteria?

Thanks!

解决方案

Well it would be nicer if you could use a GeoJSON object to represent the location but as of present the supported types are actually limited so a "Circle" type which would be ideal is not supported.

The closest you could do is a "Polygon" approximating a circle, but this is probably a little too much work to construct just for this query purpose. The other gotcha with doing this and then applying $geoIntersects is that the results will not be "sorted" by the distance from the query point. That seems to be the opposite of the purpose of finding the "nearest pizza" to the point of origin.

Fortunately there is a $geoNear operation added to the aggregation framework as of MongoDB 2.4 and greater. The good thing here is it allows the "projection" of a distance field in the results. This then allows you to do the logical filtering on the server to those points that are "within the radius" constraint to the distance from the point of origin. It also allows sorting on the server as well.

But you are still going to need to change your schema to support the index

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

db.places.ensureIndex({ "location": "2dsphere" })

And for the aggregation query:

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 } }
])

Basically this says,

*"out to 100 kilometers from a given location, find the places with their distance from that point. If the distance is within their "delivery radius" then return them, sorted by the closest"

There are other options you can pass to $geoNear in order to refine the result, as well as return more than the default 100 results if required and basically pass other options to query such as a "type" or "name" or whatever other information you have on the document.

这篇关于单点重叠的MongoDB地理空间查询领域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆