做搜索这行七年了,天天跟 Elasticsearch 死磕,今天必须得吐个槽。最近有个哥们找我救火,说他们的 es geo polygon query 查出来的数据全乱了,客户投诉说明明在小区里,结果推荐列表里全是隔壁市的东西。我一看代码,好家伙,直接用 bounding box 也就是矩形框去硬套不规则的园区,这能准才怪了。
咱们做 LBS(基于位置的服务)的都知道,现实世界哪有那么多方方正正的矩形?园区、商圈、甚至你住的老旧小区,那都是弯弯曲曲的多边形。这时候 es geo polygon query 就派上用场了。但很多新人或者急着上线的产品经理,根本不懂里面的门道,以为传个经纬度数组进去就完事了。
我举个真实的例子。上个月帮一家连锁餐饮客户优化选址分析。他们的店铺分布在几个大型商业综合体里,这些综合体不是正方形,是那种L型或者U型的。如果用简单的经纬度范围查询,也就是 geo_bounding_box,那误差简直没法看。比如一个综合体,南北跨度200米,东西跨度500米,但中间是空的。你要是用矩形框查,那中间的空地也被算进去了,导致很多原本不在覆盖范围内的用户,或者不在覆盖范围内的店铺,都被错误地关联起来。
正确的做法是使用 geo_polygon。你需要把多边形的顶点坐标按顺序传进去,形成一个闭合的环。这里有个大坑,坐标的顺序很重要,必须是顺时针或者逆时针,不能乱跳。而且,这个多边形不能太复杂,顶点太多不仅查询慢,还容易因为浮点数精度问题导致判断错误。
我见过最离谱的一个案例,客户直接把高德地图导出的原始数据扔进 ES,结果坐标轴搞反了,经度和纬度互换。查出来的结果全跑到海里去了。这种低级错误,真的让人想砸键盘。所以,在入库前,一定要做数据清洗和校验。
还有一个容易被忽视的点,就是性能。geo_polygon 的查询效率肯定不如 geo_bounding_box 或者 geo_distance。如果你的多边形特别复杂,比如顶点超过几十个,查询速度会明显下降。这时候,你可以考虑把复杂的多边形拆分成几个简单的矩形或者小多边形,或者使用 geo_shape 类型,但要注意索引时的配置。
我那个朋友的问题,最后发现是多边形坐标没有闭合。ES 要求多边形必须是闭合的,也就是说最后一个点要和第一个点重合。他没加最后那个点,导致 ES 自动补全的时候出了偏差。加上闭合点后,数据立马就准了。
所以,兄弟们,用 es geo polygon query 的时候,千万别偷懒。坐标顺序、闭合性、顶点数量,这三个点必须检查到位。别等数据错了,客户骂娘了,才想起来来找我。这行就是这样,细节决定成败,稍微不注意,就是满盘皆输。
另外,提醒一下,ES 的版本升级也可能影响 geo 查询的行为,特别是从 6.x 升到 7.x 或者 8.x 的时候,有些默认参数变了。升级前一定要看好文档,别盲目升级,不然排查问题能把你头发愁白。
总之,es geo polygon query 是个好工具,但用不好就是灾难。希望大家都能避开这些坑,少加加班,早点下班。毕竟,代码是写给人看的,只是顺便给机器执行。要是人看着都费劲,那这代码迟早得炸。
本文关键词:es geo polygon query