MongoDB Geospacial Query Spheres重叠单点

时间:2014-09-03 02:22:22

标签: mongodb geospatial mongodb-query aggregation-framework

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

我的数据看起来像这样:

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

基本上,我正在努力完成本SO帖子中描述的内容,但使用MongoDB - Get all points(circles with radius), that overlap given point

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

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

谢谢!

2 个答案:

答案 0 :(得分:7)

如果您可以使用GeoJSON对象来表示位置,那么会更好。但是到目前为止supported types are actually limited所以&#34; Circle&#34;不支持理想的类型。

你最接近的是&#34; Polygon&#34;近似一个圆圈,但这可能只是为了这个查询目的而构建的太多工作。另一个问题是这样做,然后应用$geoIntersects,结果将不会被排序&#34;距离查询点的距离。这似乎与找到最近的比萨饼的目的相反。到原点。

幸运的是,从MongoDB 2.4及更高版本开始,聚合框架中添加了$geoNear操作。这里的好处是它允许&#34;投影&#34;结果中的距离场。然后,这允许您在服务器上对那些在半径范围内的点进行逻辑过滤&#34;限制距离原点的距离。它还允许在服务器上进行排序。

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

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

基本上这就是说,

  

*&#34;距离指定位置100公里,找到距离该点距离的地方。如果距离在他们的&#34;交付半径范围内&#34;然后返回它们,按最近的&#34;

排序

您可以将其他选项传递给$geoNear以优化结果,并在需要时返回超过默认的100个结果,并基本上将其他选项传递给查询,例如&#34;类型& #34;或&#34;名称&#34;或者您在该文件上提供的任何其他信息。

答案 1 :(得分:-1)

更正: MongoDB(自v3.2.0起),不支持Circle索引的2dsphere GeoJSON类型。

以下是原始答案和错误答案。阅读评论以获取详细信息。


我不认为使用定义的模式可以找出你想要的东西。

使用mongodb&gt; = 2.4,您可以使用GeoJSON存储和索引文档,然后使用$geoIntersects命令,如下所示:

db.places.insert({
    name: "Pizza Hut",
    location: { 
        "type": "Circle",
        "coordinates": [100,0],
        "radius": 20
    }
})


db.places.find({
    location: {
        $geoIntersects: {
            $geometry: {
                type: "Point",
                coordinates: [ 110, 10]
            }
        }
    }
})

否则,$geoWithin和手动处理应用程序端的组合可能会起作用,但如果可能的话,我宁愿重新定义我的模式。