在 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 中
无法向 Mongoose 查询返回的对象添加新属性 [重复]