在 mongodb 地理位置查询中使用对象属性作为 $maxDistance 参数

Posted

技术标签:

【中文标题】在 mongodb 地理位置查询中使用对象属性作为 $maxDistance 参数【英文标题】:Using an object property as the $maxDistance argument in a mongodb geolocation query 【发布时间】:2013-07-25 20:49:12 【问题描述】:

我想编写一个带有 $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 查询中访问该半径变量。这甚至可能吗?

【问题讨论】:

您能解释一下您的最终目标,以便我可以为您提供替代方案吗? 以消防站为例,我想得到一个 foo.loc 在某个指定位置的 foo.radius 内的所有站 foo 的列表。至于替代方案,如果这不是我可以用单个查询做的事情,我想我会获取所有内容并自己进行距离比较。我最终要处理的文档数量实际上非常少,所以这应该是合理的。 请将该信息添加到问题中,而不仅仅是评论。但我已经更新了我的答案。 【参考方案1】:

您不能完全这样做——一般来说,您的 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 ], 
        ] ]
    

【讨论】:

以上是关于在 mongodb 地理位置查询中使用对象属性作为 $maxDistance 参数的主要内容,如果未能解决你的问题,请参考以下文章

在查找 localField 中使用 _id 对象的 mongodb 查询

使用 _id 字符串的 GraphQL 查询,对象 ID 存储在 MongoDB 中

MongoDB查询列表中的对象属性

无法向 Mongoose 查询返回的对象添加新属性 [重复]

无法向 Mongoose 查询返回的对象添加新属性 [重复]

遍历 MongoDB 对象属性