elasticsearch geo查询避坑指南:8年老鸟教你搞定附近的人

elasticsearch geo查询避坑指南:8年老鸟教你搞定附近的人

做搜索这行八年了,见过太多人栽在elasticsearch geo查询这个坑里。

别信那些网上抄来的“完美配置”,那是写给新手看的童话。

今天我不讲原理,只讲怎么让你的查询快如闪电,还不崩服务器。

很多兄弟一上来就搞个巨大的bounding box,结果查询慢得想砸电脑。

我见过最蠢的做法,是用lat/lng直接存,还没加索引类型。

这种低级错误,我每次看到都想骂人,真的,太浪费资源了。

第一步,mapping必须写对。

location字段必须用geo_point类型,别整那些花里胡哨的。

如果你用经纬度数组,记得顺序是lng,lat,别搞反了。

搞反了不仅查不到,还会把你自己的数据全污染,到时候哭都来不及。

第二步,查询语句别乱写。

很多人喜欢用match_all然后过滤,这是找死。

一定要用geo_distance或者geo_bounding_box。

特别是做“附近的人”这种功能,geo_distance是标配。

参数里distance别写太大,10公里以内还行,超过50公里直接卡死。

这时候你得考虑分片策略,或者用geo_shape代替。

第三步,别忽略性能陷阱。

es的geo查询是基于geohash的,精度越高,树越深,查询越慢。

默认精度是7,差不多1.2公里误差。

如果你要精确到街道,精度调到9或10。

但记住,精度越高,内存占用越大,查询时间越长。

我在实际项目中,为了平衡速度和精度,通常把精度卡在8。

这个精度下,误差大概300米,对于大部分LBS应用足够了。

第四步,缓存是个好东西,但别滥用。

很多人喜欢把查询结果缓存到redis,这没问题。

但要注意,geo查询的结果是动态的,用户位置一变,结果就变。

如果你的缓存key只存了经纬度,没存时间戳,那数据就是旧的。

我见过有人缓存了一天的“附近的人”,结果用户走到隔壁城市,看到的还是昨天的邻居。

这种体验,用户会直接卸载你的app,没商量。

第五步,监控和报警不能少。

es的geo查询很吃CPU,特别是数据量大的时候。

一定要配置慢查询日志,设置阈值,比如超过500ms就报警。

我之前的项目,有一次因为一个同事写了个错误的geo查询,导致整个集群CPU飙升到90%。

差点就把生产环境搞挂了,吓得我半夜爬起来重启。

这种教训,希望你别经历。

最后,说说价格。

如果你用云服务,比如阿里云或者AWS,geo查询是单独计费的。

别以为买了包年包月就万事大吉,高频的geo查询照样扣钱。

我算过一笔账,每天100万次geo_distance查询,一个月下来,光这部分费用就得好几千。

对于小团队来说,这可不是小数目。

所以,能本地算的,就别去查es。

比如简单的圆形区域判断,用代码算一下,比发请求快多了。

只有复杂的范围查询,才交给es。

别把es当数据库用,它是搜索引擎,别让它干不该干的活。

总结一下,elasticsearch geo查询这东西,水很深。

别光看文档,要去实战里摸爬滚打。

多测,多压,多监控。

别指望一劳永逸,架构是不断迭代的。

希望这篇干货能帮你省下几个通宵,少掉几把头发。

毕竟,头发比代码值钱多了。

本文关键词:elasticsearch geo查询