在Mongo中,$ near和$ nearSphere有什么区别?

mas*_*ker 13 mongodb

我阅读了文档,并且不太清楚两者之间的区别.

我发现的唯一区别是在nearSphere中明确表示Mongo使用球面几何计算$ nearSphere的距离.但这可以使用$ near来实现,不是吗?

Wan*_*iar 15

关键字sphere用于区分$ near$ nearSphere.

如您所知,$nearSphere声称使用球面几何计算距离.这与地球地图投影(失真)有关.凡MongoDB的2D指标是基于笛卡尔MongoDB的2dsphere指标是基于短程线.

足够的理论,让我们用一些例子.假设我们有两个文件如下:

db.map.insert({ "_id": "Westfield London", "location": [ -0.22157, 51.507176 ] });
db.map.insert({ "_id": "Green Lanes Shopping Centre", "location": [ -0.098092, 51.576198 ] });
Run Code Online (Sandbox Code Playgroud)

两个运营商的手册都指明我们可以使用:

索引:2dsphere,查询:GeoJSON

db.map.createIndex({"location": "2dsphere"});

db.map.find({"location":{"$nearSphere":{"$geometry":{"type":"Point", "coordinates":[ -0.127748, 51.507333 ] }}}});

db.map.find({"location":{"$near":{"$geometry":{"type":"Point", "coordinates":[ -0.127748, 51.507333 ]}}}});
Run Code Online (Sandbox Code Playgroud)

在这种情况下,两个查询都将返回相同的结果,因为索引存储在中2dsphere.

结果:

[ /* $nearSphere */
    {"_id" : "Westfield London"},
    {"_id" : "Green Lanes Shopping Centre"}
]
[ /* $near */
    {"_id" : "Westfield London"},
    {"_id" : "Green Lanes Shopping Centre"}
]
Run Code Online (Sandbox Code Playgroud)

索引:2d,查询:旧版坐标

db.map.createIndex({"location": "2d"});

db.map.find({"location":{"$nearSphere":[ -0.127748, 51.507333 ]}});

db.map.find({"location":{"$near":[ -0.127748, 51.507333 ]}});
Run Code Online (Sandbox Code Playgroud)

这是区别发生的地方,$nearSphere尽管有索引,但是$near以平面投影计算结果.

结果:

[ /* $nearSphere */
    {"_id" : "Westfield London"},
    {"_id" : "Green Lanes Shopping Centre"}
]
[ /* $near */
    {"_id" : "Green Lanes Shopping Centre"},
    {"_id" : "Westfield London"}
]
Run Code Online (Sandbox Code Playgroud)

请参阅上面示例的gist:JS测试脚本.这是使用MongoDB v3.4.4测试的.

另请参阅地理空间索引和查询.