做地图搜索、附近的人、物流轨迹,你肯定被ES的geo搞崩溃过。
别去啃官方文档那些天书了。
今天我就掏心窝子,把es geo原理掰碎了讲给你听。
保证你看完就能上手,少走半年弯路。
先说个大实话,很多新人上来就建索引。
字段直接写geo_point,然后就开始查。
结果查出来的数据,要么不准,要么慢得像蜗牛。
为啥?因为你根本不懂es geo原理里的底层逻辑。
ES里的经纬度,不是简单的数字。
它被压缩成了经纬度网格。
这就好比把地球切成了无数个小方块。
每个方块有个唯一的ID,叫geohash。
这个geohash就是定位的核心。
你存数据的时候,ES会自动算出这个hash值。
查数据的时候,也是基于这个hash去匹配。
这里有个大坑,很多人不知道。
geohash的精度,直接决定查询速度和准确度。
默认精度是5位,大概5公里范围。
你要是做外卖配送,这精度够吗?
肯定不够啊,5公里都能跨半个城了。
这时候你得手动指定精度。
比如指定到7位,大概50米。
或者8位,大概10米。
精度越高,hash值越长,匹配越慢。
这就是es geo原理里最纠结的地方。
你要在速度和精度之间找平衡。
一般建议,城市内用7位,郊区用6位。
别一上来就搞10位,那查询能卡死你。
除了geohash,还有另一种方式。
叫lat/lon直接存。
这种方式适合做精确的矩形范围查询。
比如查一个小区的四至范围。
这时候用geo_bounding_box最合适。
但要注意,这种方式不支持圆形搜索。
想查“半径5公里内的人”,必须用geo_distance。
这里有个细节,很多人会搞错。
geo_distance是基于球面计算的。
它不是简单的平面几何。
所以算出来的距离,比勾股定理准得多。
但是,如果你数据量特别大。
比如几千万条轨迹数据。
每次算球面距离,CPU能给你干冒烟。
这时候就得用缓存或者预计算。
把热门区域的查询结果缓存起来。
或者在写入数据时,就把距离算好存起来。
虽然占空间,但查起来飞快。
这也是es geo原理里的高级技巧。
再说说多边形查询。
比如查某个行政区域的数据。
用geo_polygon。
这个功能很强大,但也很吃资源。
因为要判断点是否在多边形内。
算法复杂度比较高。
如果你的多边形很复杂,有很多凹凸角。
查询速度会明显下降。
这时候建议简化多边形。
或者把多边形拆分成几个矩形。
用geo_bounding_box组合查询。
虽然代码麻烦点,但性能提升巨大。
最后说说索引优化。
别把所有geo字段都设成keyword。
一定要用geo_point或geo_shape。
而且,最好加上doc_values。
不然你每次排序,都得重新算。
那速度,你懂的。
还有,别在geo字段上搞分词。
经纬度是精确值,不需要分词。
分了词反而查不到。
我见过有人把经纬度当字符串存。
然后搞什么like查询。
那是自欺欺人,数据量一大就崩。
记住,专业的事交给专业的字段。
总结一下,搞懂es geo原理,关键就三点。
一是选对精度,别盲目追求高。
二是选对查询类型,矩形用box,圆形用distance。
三是注意性能优化,缓存和预计算不能少。
别怕踩坑,我当年也交了不少学费。
现在把这些经验分享给你,希望你能少掉点头发。
做技术就是这样,踩坑多了,自然就懂了。
希望这篇能帮你解决实际问题。
要是还有不懂的,评论区见。