MongoDB $near 查询准确性问题
Posted
技术标签:
【中文标题】MongoDB $near 查询准确性问题【英文标题】:MongoDB $near query accuracy issue 【发布时间】:2018-10-07 16:10:44 【问题描述】:在我的应用程序中,我想查询坐标附近(例如 5 公里内)的项目,我尝试使用 $near 来实现这一点。快速浏览了一下,我认为它有效,但在我进一步测试后,查询似乎有些不准确。这是我的设置:
我选择了两个相距不到 5 公里的坐标:
61.4644750214197, 23.8426943813556 61.497133399999996, 23.778528100000003(至少根据this、this 或 this 等工具,这些坐标之间的距离应该约为 ~4.99 公里)
-
我将其中一个坐标添加到空的“项目”集合中:
db.items.insert(
"geo" :
"type" : "Point",
"coordinates" : [
61.4644750214197,
23.8426943813556
]
);
-
我在集合中添加了“2dsphere”索引,使地理空间查询成为可能:
db.items.createIndex( geo : "2dsphere" )
-
最后,我使用 $near 查询的另一个坐标:
db.items.find(geo:
$near:
$geometry:
type: "Point" ,
coordinates: [ 61.497133399999996, 23.778528100000003 ]
,
$maxDistance: 5000 // according to docs with '2dsphere' index and GeoJSON this is is meters
).count()
-
我预计结果为 1,但结果为 0。即使我将 $maxDistance 设置为 7000,结果仍为 0,但如果我将其设置为 8000,结果将为 1。
我做错了什么还是 MongoDB 地理空间查询(或只是 $near 查询?)不准确?如果是这样,有没有更好的方法来获得这种查询的准确结果?这是我第一次在 MongoDB 中处理地理空间查询,所以对于我的问题可能有一个简单的解释。
编辑: 基本上,我梦想有一种功能可以在距离用户当前位置 X 公里的地图中显示所有项目,并且 X 可以由用户确定。如果用户想要过滤 7 公里内的项目,5 公里内的项目将不可见,这将是很尴尬的。
我已经尝试了大多数用于执行此查询的选项,例如 $centerSphere、$nearSphere 和 geoNear,结果相似。他们似乎都声称我前面提到的坐标之间的距离在 7-8 公里之间。我开始考虑 1. 我缺少一些关于距离一般如何工作的关键信息,或者 2. 用mongodb 根本无法解决我的问题。以下是我对其他选项的查询:
$centerSphere(5、6 和 7 公里的结果为 0,但 8 公里的结果为 1):
db.items.find( geo:
$geoWithin: $centerSphere: [ [ 61.497133399999996, 23.778528100000003 ], 5/6378.1 ]
).count()
geoNear(maxDistance 5000、6000 和 7000 的 0 个结果,但 8000 的 1 个结果):
db.runCommand(
geoNear: "items",
near: type: "Point", coordinates: [ 61.497133399999996, 23.778528100000003 ] ,
spherical: true,
maxDistance: 5000
)
【问题讨论】:
$nearSphere
是实际考虑地球曲率的算子。我以为$near
运算符上有对它的引用,但似乎没有。
是的,地理空间查询的数学运算存在“内置错误”。地球不是“真的”一个球体,你必须期待错误。但应该在5米以内
@NeilLunn 在这种情况下,$nearSphere
我得到与$near
相同的结果。
在同一个坐标上,这并不奇怪。关键是如果你想要你使用的“真实”距离。但是“错误”仍然是任何地理空间计算所固有的。你有很多关于haversine和类似算法的阅读。
感谢@NeilLunn 的回复!我再次阅读了您的原始评论,现在我明白了您的意思。我仍然认为我在查询中得到 $maxDistance 值为 5000、6000 和 7000 的 0 结果的原因无法解释:在这种情况下,准确度“错误”远远超过 5m。
【参考方案1】:
我知道我迟到了,但对于所有面临类似问题的人
这里的问题是,当您将数据存储到“坐标”中时,它必须按 [longitude, latitude] 顺序,因为这就是 mongodb 的工作方式。 https://docs.mongodb.com/manual/geospatial-queries/#spherical 我刚刚以相反的坐标顺序运行了您的示例,它按预期工作。
db.items.insert(
"geo" :
"type" : "Point",
"coordinates" : [
23.8426943813556,
61.4644750214197
]
);
然后我跑了
db.items.find(geo:
$near:
$geometry:
type: "Point" ,
coordinates: [ 23.778528100000003 , 61.497133399999996]
,
$maxDistance: 5000
).count()
这里的计数是1:
希望对你有帮助
【讨论】:
感谢 Ishaan,帮了大忙。以上是关于MongoDB $near 查询准确性问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 mongoid dsl 中编写 mongodb $near 查询?
Mongodb $near 查询 120 万份文档耗时 6 秒
使用 java 的 MongoDb $near 查询没有给出正确的位置