查询实现思路
- 使用地理空间查询操作符:在MongoDB中,使用
$geoNear
或$nearSphere
操作符来计算两个点之间的距离。$geoNear
操作符适用于平面几何(在小范围区域较精确),$nearSphere
适用于球面几何(更适合全球范围)。由于我们处理的可能是全球范围内用户地址,使用$nearSphere
更合适。
- 构建查询条件:假设集合名为
users
,家庭地址字段为homeLocation
,工作地址字段为workLocation
,查询语句类似如下:
db.users.aggregate([
{
$project: {
distance: {
$geoNearSphere: {
near: "$workLocation",
spherical: true,
distanceField: "distance",
maxDistance: 50 * 1000 // 50公里转换为米
}
},
homeLocation: 1,
workLocation: 1
}
},
{
$match: {
distance: { $lte: 50 * 1000 }
}
}
]);
创建索引优化查询
- 为地理空间字段创建2dsphere索引:对于地理空间查询,创建2dsphere索引可以大大提升查询性能。分别对
homeLocation
和workLocation
字段创建2dsphere索引。
db.users.createIndex({ homeLocation: "2dsphere" });
db.users.createIndex({ workLocation: "2dsphere" });
数据量非常大时索引策略调整
- 复合索引:如果除了距离查询外,还有其他常用的过滤条件,例如按用户所在城市等进行过滤,可以考虑创建复合索引。例如,如果经常按城市过滤后再进行距离查询,可以创建类似如下的复合索引:
db.users.createIndex({ city: 1, homeLocation: "2dsphere", workLocation: "2dsphere" });
- 部分索引:如果数据量巨大,且存在部分数据是高频查询的,可以使用部分索引。例如,假设经常查询某个特定区域内的用户,可以对该区域内用户的数据创建部分索引。假设按城市过滤,对
New York
市的用户创建部分索引:
db.users.createIndex({ homeLocation: "2dsphere", workLocation: "2dsphere" }, { partialFilterExpression: { city: "New York" } });
- 索引维护:定期检查索引的使用情况和碎片情况。使用
db.collection.stats()
查看索引相关统计信息。如果索引碎片过多,可能需要重建索引来提高性能。
db.users.reIndex();