做搜索这行八年了,见过太多人栽在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查询