如何统计经纬度距离登录用户15英里范围内的其他用户数量
.NET 实现统计指定坐标15英里范围内用户数量的解决方案
核心原理
地球为球面,两点之间的距离不能直接用平面欧氏距离计算,需使用哈弗辛公式(Haversine Formula)计算球面距离,或直接使用数据库/框架内置的空间计算能力实现,最终筛选出距离当前登录用户小于等于15英里的其他用户即可。
实现方案
方案1:应用层C#直接实现
适合用户量较小的场景,无需修改数据库结构,直接在代码中计算距离:
// 计算两个经纬度坐标之间的距离,返回值单位为英里 public double CalculateDistanceInMiles(double lat1, double lon1, double lat2, double lon2) { // 地球平均半径,单位为英里 const double EarthRadiusInMiles = 3958.8; // 经纬度转弧度 var radLat1 = lat1 * Math.PI / 180; var radLon1 = lon1 * Math.PI / 180; var radLat2 = lat2 * Math.PI / 180; var radLon2 = lon2 * Math.PI / 180; var deltaLat = radLat2 - radLat1; var deltaLon = radLon2 - radLon1; // 哈弗辛公式计算 var haversine = Math.Pow(Math.Sin(deltaLat / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(deltaLon / 2), 2); var centralAngle = 2 * Math.Atan2(Math.Sqrt(haversine), Math.Sqrt(1 - haversine)); return EarthRadiusInMiles * centralAngle; }
调用示例:拿到当前登录用户的经纬度后,遍历所有其他用户的经纬度,调用上述方法判断返回值是否小于等于15,累加符合条件的数量即可。
方案2:数据库层实现(推荐,性能更高)
适合用户量较大的场景,直接在数据库层面完成计算过滤,避免全量拉取用户数据。
SQL Server 原生SQL实现
使用SQL Server内置的GEOGRAPHY空间类型计算:
-- 定义当前登录用户的坐标,4326为WGS84 GPS坐标系统的SRID DECLARE @currentLocation GEOGRAPHY = GEOGRAPHY::STPointFromText('POINT(' + CAST(@currentLongitude AS VARCHAR(20)) + ' ' + CAST(@currentLatitude AS VARCHAR(20)) + ')', 4326); -- 统计15英里范围内的其他用户数量,STDistance返回单位为米,15英里=15*1609.34米 SELECT COUNT(*) AS NearbyUserCount FROM Users WHERE Id != @currentLoginUserId AND @currentLocation.STDistance(GEOGRAPHY::STPointFromText('POINT(' + CAST(Longitude AS VARCHAR(20)) + ' ' + CAST(Latitude AS VARCHAR(20)) + ')', 4326)) <= 15 * 1609.34
EF Core 集成实现
如果使用EF Core操作数据库,可引入空间数据支持包直接用LINQ实现:
- 先安装对应数据库的空间支持包,SQL Server环境下安装
Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite - 实体类新增
Point类型的位置字段,配置SRID为4326 - LINQ查询写法:
// 构造当前用户坐标,注意Point构造参数先传经度再传纬度 var currentLocation = new Point(currentUserLongitude, currentUserLatitude) { SRID = 4326 }; var nearbyUserCount = await _dbContext.Users .Where(u => u.Id != currentLoginUserId && u.Location.Distance(currentLocation) <= 15 * 1609.34) .CountAsync();
如果使用MySQL等其他数据库,对应也有ST_Distance_Sphere等内置空间函数,逻辑与上述实现一致。
常见踩坑提醒
- 绝大多数空间计算库的坐标参数都要求先传经度、后传纬度,和日常表述的纬度在前的习惯不同,传反会导致距离计算完全错误
- 注意单位转换,1英里=1609.34米,不要混淆单位导致阈值偏差
- 用户量超过10万时建议给空间字段添加空间索引,可大幅提升查询性能
内容的提问来源于stack exchange,提问作者Sami In
相关产品推荐
相关产品推荐

