如何对嵌入式文档进行 $geoNear 聚合?
Posted
技术标签:
【中文标题】如何对嵌入式文档进行 $geoNear 聚合?【英文标题】:How can I do a $geoNear aggregation on embedded documents? 【发布时间】:2020-10-02 10:44:24 【问题描述】:我有一个名为 services 的 MongoDB 集合,每个集合都有多个嵌入位置。
看起来像这样:
name: "example",
locations: [
coordinates: [0, 0]
,
coordinates: [0, 0]
,
]
我想对 $unwind
数据结构使用聚合,因此每个位置都被视为单独的文档,然后使用 $geoNear
根据与用户提供的点的距离对每个位置进行排序,如下所示:
db.collection("services").aggregate([
$unwind : "$locations"
$geoNear:
near: [0, 0],
distanceField: "distance"
,
不过,很自然,$geoNear 想成为first thing in an aggregation,我很难理解如果没有 $unwind 先出现它是如何工作的。
创建索引 似乎 成功,但是当我尝试运行它时,我收到“无法找到 $geoNear 查询的索引”错误。
我能否以某种方式运行一个聚合,然后对结果运行另一个聚合?
或者,有没有办法在没有聚合的情况下做到这一点?
重要的是,简单地更改数据架构并不容易,因为 mongo 被用作搜索索引之类的东西,而数据本身来自其他地方的关系数据库。
我或许可以考虑创建第二个预展开数据的集合? MongoDB 是否有某种回调可以减轻这种痛苦?
【问题讨论】:
【参考方案1】:geoNear 查询需要特殊的 2d 或 2dsphere 索引。索引会将每个位置与文档相关联。如果单个文档包含多个位置,则所有位置都将引用同一个文档。
geoNear 查询然后通过搜索索引选择文档,并按从最近到最远的顺序返回文档。
单个文档即使有多个位置也不会被多次返回。
虽然展开确实允许您处理单独文档中的每个位置,但在 $unwind 之后管道中的文档没有索引,因此 geoNear 无法运行。
使用 geoNear 检查数组中所有元素的唯一方法是在展开后将它们输出到临时集合,在临时集合上创建 2dsphere 索引,然后将 geoNear 与该集合一起使用。
您可以使用Haversine 公式计算两点之间距离的合理近似值。
【讨论】:
以上是关于如何对嵌入式文档进行 $geoNear 聚合?的主要内容,如果未能解决你的问题,请参考以下文章