1

我想用一个 $maxDistance 参数编写一个 $near 查询,它的值不是常数。例如,我有一组具有位置和覆盖半径的消防站,我想查找其覆盖半径包括某个特定点的所有消防站。覆盖半径可能因站点而异。

我有一个完整的文档集合,如下所示:

{
    'loc' : [-72,40],
    'radius' : 10
}

一个看起来像这样的查询:

{'loc': { $near : coordinates, $maxDistance : 'radius'}};

但这是不正确的。

如果我正在编写 SQL 查询,我会使用类似的东西:

SELECT * FROM table AS foo WHERE foo.radius ... (whatever your distance method looks like)

但我不知道如何在 mongo 查询中访问该半径变量。这甚至可能吗?

4

1 回答 1

0

您不能完全这样做——通常,您的 MongoDB 查询中的任何内容都不能基于集合中的值。

但是,从 MongoDB 2.4 开始,我们支持一个名为的新索引2dsphere,它不仅允许您在数据库中存储点,还可以存储多边形。您可以将该信息存储在一个文档中,例如:

db.so.ensureIndex( { loc: '2dsphere' } );
db.so.insert( {
    name: "Firestation 1",
    loc: {
        type: "Polygon",
        coordinates: [ [ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 0 ] ] ]
    }
} );

然后您可以使用“相交”查询来确定一个点是否被每个多边形覆盖:

db.so.find( {
    'loc' : {  
        $geoIntersects: { 
            $geometry: { type: 'Point', coordinates: [ 0, 0 ] } 
        } 
    }
} );

然后返回:

{ 
    "_id" : ObjectId("51f24d566775068ab0b786f0"), 
    "name" : "Firestation 1", 
    "loc" : { 
        "type" : "Polygon", 
        "coordinates" : [  [  [  0,  0 ],  [  0,  1 ],  [  1,  1 ],  [  1,  0 ],  [  0,  0 ] ] ] 
    } 
}

在这里它找到了消防站,因为 0, 0 在多边形的中间。现在,诀窍当然是计算构成距离中心点“半径”(例如 10 公里)的圆的多边形点。您将无法获得真正的圆形,但六边形或八边形应该足够好。数学并不是非常简单,但http://www.movable-type.co.uk/scripts/latlong.html#destPoint有一个 JavaScript 示例。只需从 0 到 2PI 分 8 步循环您的方位,即可计算圆周上的点,并将它们放入坐标中。确保将它们嵌入到双重嵌套数组中,并使第一个和最后一个相同:

{
    name: "Firestation 1",
    loc: {
        type: "Polygon",
        coordinates: [ [
            [ point1-lon, point1-lat ], 
            [ point2-lon, point2-lat ], 
            [ point3-lon, point3-lat ], 
            ...
            [ point1-lon, point1-lat ], 
        ] ]
    }
}
于 2013-07-25T21:22:01.183 回答