geoadd成功但geosearch查不到点,主因是经纬度顺序颠倒(应经度在前、纬度在后)、输入非十进制度(如误用度分秒)、精度丢失或单位混淆;georadius半径单位需显式指定(默认为米),geosearch的radius字段单位固定为米。

Go 里用 redis-go 调 GEO 命令本身不难,难点在坐标精度、单位换算和边界行为——比如 GEOSEARCH 返回空结果,大概率不是代码写错了,而是传了度分秒或用了错误的半径单位。
为什么 GEOADD 成功但 GEOSEARCH 查不到点
常见原因是经纬度顺序反了或精度丢失:redis-go 的 GEOADD 要求参数顺序是 经度 纬度(注意不是“纬度 经度”),且必须是 float64 类型。如果从 GPS 设备或前端拿到的是字符串或整数秒格式,直接传会导致插入值为 0 或溢出。
- 检查原始数据:确认输入是十进制度(如
116.481529,不是116°28'53.5") - 强制类型转换:
lon, _ := strconv.ParseFloat(lonStr, 64),别用int截断 - 用
redis-cli手动验证:GEORADIUS myset 116.48 39.99 10 km看是否返回预期结果
GEOSEARCH 和 GEORADIUS 选哪个
GEORADIUS 是旧命令,GEOSEARCH 是 Redis 6.2+ 推荐方式,支持更灵活的形状(BYRADIUS/BYBOX)和排序。但 Go 客户端(如 github.com/redis/go-redis/v9)对两者的封装差异明显:
-
GEORADIUS对应client.GeoRadius(ctx, key, lon, lat, &redis.GeoRadiusQuery{...}),半径单位必须显式指定(km/m/mi/ft) -
GEOSEARCH对应client.GeoSearch(ctx, key, &redis.GeoSearchQuery{...}),Radius字段单位固定为米,Unit参数已废弃 - 若用
GEORADIUS传了10却没写单位,默认是m,查不到 10 米外的点——这是最常被忽略的隐式约定
如何避免地理距离计算偏差
Redis GEO 使用的是 Haversine 公式,但只适用于球面模型。当业务需要高精度(比如打车定位误差
- Redis 不支持 WGS84 椭球修正,跨大洲查询时误差可达百米级
- 所有坐标必须用 WGS84 基准系,如果原始数据来自 GCJ-02(国内火星坐标),必须先纠偏,否则
GEOPOS返回的位置会偏移 200–500 米 - 批量查询时慎用
GEOSEARCH的Count参数:它只限制返回数量,不保证按距离排序——得手动加Sort: "ASC"
Go 客户端实际调用示例
以下是在 github.com/redis/go-redis/v9 中安全调用 GEOSEARCH 的最小可行片段:
query := &redis.GeoSearchQuery{
Longitude: 116.481529,
Latitude: 39.992677,
Radius: 5000, // 单位:米
Sort: "ASC",
Count: 10,
}
locations, err := client.GeoSearch(ctx, "poi:store", query).Result()
if err != nil {
// 注意:err 可能是 redis.Nil(无结果),不是真正的错误
}
// locations 是 []string,需再调用 GeoPos 获取经纬度
positions, _ := client.GeoPos(ctx, "poi:store", locations...).Result()
关键点:不要依赖 GEOSEARCH 直接返回坐标,它只返回成员名;距离排序必须显式设 Sort,否则顺序不确定;Radius 数值单位是硬编码的米,别试图传 "5km" 字符串。
真正麻烦的从来不是调哪个函数,而是你手里的坐标数据到底是什么基准、有没有被前端悄悄转过格式、Redis 实例跑的是不是老版本——这些细节不核对清楚,写再漂亮的 Go 封装也没用。











