这篇文专治那些在 ES 里查多边形、圆或者不规则地块时各种报错、查不准的疑难杂症,看完你就知道怎么把 geo_shape 玩明白,不再对着日志发愣。
说实话,刚接触 ES 的时候,谁没被地理位置查询坑过?
以前我觉得用 geo_point 加个半径查询就完事了,直到那天老板让我查某个行政辖区内的所有门店。
我心想这还不简单?随手写了个 geo_shape 查询,结果返回空集,查了半天日志,头发都快掉光了。
后来才反应过来,geo_shape 和 geo_point 完全是两个路数,一个是点,一个是面,混着用肯定出乱子。
今天就把我踩过的坑和正确的姿势整理出来,希望能帮兄弟们省点加班时间。
第一步,先搞懂数据结构,别急着写查询语句。
你要查的区域,比如一个商圈,在 ES 里得存成 geo_shape 类型。
我在测试环境里,直接往索引里灌数据,用的是 GeoJSON 格式。
记得一定要指定 "type" 为 "polygon" 或者 "envelope",别偷懒用默认的。
我当时就是没指定,ES 默认当成点处理了,结果怎么查都查不到范围里的数据,尴尬不?
第二步,建立索引映射,这一步至关重要。
在创建索引的时候,字段类型必须显式声明为 geo_shape。
别指望 ES 能自动识别,它有时候挺笨的。
比如我的 mapping 里,店铺位置字段是 geo_point,而商圈范围字段是 geo_shape。
这两个字段虽然都跟位置有关,但底层存储机制完全不同,别搞混了。
我有一次就是因为映射写错,导致后续查询性能极差,CPU 直接飙到 100%。
第三步,写入数据时的坐标顺序,这是最容易出错的地方。
GeoJSON 标准要求的是经度在前,纬度在后,也就是 [lon, lat]。
但我写代码的时候,习惯性地用了 [lat, lon],结果查出来的位置全跑到太平洋去了。
这种低级错误, debug 的时候真的会让人想砸键盘。
一定要在代码层面做好转换,或者在写入前检查一遍坐标顺序。
我当时为了查这个 bug,盯着屏幕看了两个小时,眼睛都花了。
第四步,编写 geo_shape 查询语句,这里有个小细节。
查询的时候,要用 "shape" 关键字,而不是 "geo_shape"。
我刚开始也是直接写 geo_shape,结果 ES 报错说找不到这个查询类型。
后来查了官方文档,才发现是 "shape"。
还有,记得指定 "relation" 参数,是 "within" 还是 "intersects"。
within 是包含关系,intersects 是相交关系,业务需求不同,选错了结果就不对。
我那次查商圈,本来想查完全在商圈内的店,用了 intersects,结果把边缘蹭到一点的店也查出来了,数据不准被老板骂了一顿。
第五步,优化查询性能,别让小数据量拖垮大集群。
geo_shape 查询比 geo_point 慢,这是肯定的,因为计算几何关系更复杂。
如果数据量大,记得加索引,比如设置 "strategy" 为 "recursive" 或 "indexed"。
我在生产环境里,把 strategy 改成了 indexed,查询速度提升了不止一倍。
虽然写入速度稍微慢了点,但查询是高频操作,这点牺牲值得。
最后,多测试,多验证。
别信网上那些复制粘贴的代码,自己建个测试索引,跑一遍流程。
我现在的习惯是,每次改完查询逻辑,先在 Kibana 里试一下,确认结果无误再上线。
这种粗糙但实用的方法,比看十篇理论文章都管用。
ES 地理位置 geo_shape 这东西,看着高大上,其实只要摸清脾气,也就那么回事。
别被那些复杂的术语吓住,动手试试,你就懂了。
希望这些经验能帮到你,少走点弯路,早点下班回家陪陪家人。
毕竟,代码是写不完的,但生活是自己的。
记住,es地理位置 geo_shape 的核心就是精准匹配,别马虎。
本文关键词:es地理位置 geo_shape