做地理空间搜索,最让人头大的就是坐标数据。
很多兄弟刚上手 ES,看到 geo_point 就兴奋。
觉得有了它,方圆几公里内的店都能搜出来。
结果一跑查询,要么报错,要么搜不到。
甚至有的数据存进去,查出来位置偏了十万八千里。
这真不是 ES 的锅,是你没搞懂 es geo_point 格式 的规矩。
我见过太多人,直接把经纬度当字符串存进去。
比如 "116.40,39.90"。
看着没问题吧?
但在 ES 眼里,这就是个普通的文本字段。
你让它做空间计算?它只会觉得你在逗它。
真正的 es geo_point 格式 有两种主流写法。
第一种,数组形式。
这是最直观的。
[经度, 纬度]。
注意顺序,千万别反了。
很多新手喜欢写 [纬度, 经度],这是 GIS 里的习惯,但在 ES 里,默认是 lon, lat。
一旦反了,北京的数据可能跑到非洲去了。
第二种,对象形式。
{"lon": 116.40, "lat": 39.90}。
这种写法更清晰,不容易搞混。
特别是当你还要存其他属性,比如高度或者别名时,对象形式更好扩展。
但是,对象形式有个坑。
字段名必须是小写的 lon 和 lat。
你写成 Longitude 或者 Latitude,ES 直接无视。
我就吃过这个亏。
折腾了半天,日志里全是 warning,数据就是不动。
除了格式,还有一个致命的问题。
精度。
坐标点不是随便写写就行。
你写 116.40,精度太低。
在 ES 内部,它会被近似处理。
虽然肉眼看着差不多,但做距离过滤时,误差可能达到几百米。
如果你做的是外卖配送范围,或者共享单车停放点,这点误差就是灾难。
建议至少保留小数点后 5 到 6 位。
当然,也不是越多越好。
数据量大了,存储和计算压力都会上来。
还有个容易被忽视的点。
空值处理。
如果你的数据源里,有些店铺没有坐标。
千万别留空字符串。
ES 对 geo_point 的空值很敏感。
留空可能导致整个分片查询失败,或者返回 null。
最好的办法是,在入库前清洗数据。
没有坐标的,直接过滤掉,或者标记为特殊值。
不要指望 ES 能自动帮你补全。
它只是个搜索引擎,不是算命先生。
再说说性能。
用了 es geo_point 格式,查询速度确实快。
基于倒排索引的空间查询,比数据库里的 ST_Distance 快几个数量级。
但是,如果你的数据量达到亿级。
记得开启 doc_values。
这是 ES 的默认行为,但有时候索引模板没配好,可能会失效。
一旦失效,每次查询都要重新计算,那速度简直慢到让人想砸键盘。
我有个朋友,做物流轨迹分析。
一开始没注意这些细节,查询延迟高达 2 秒。
后来改了格式,优化了索引映射,延迟降到 50 毫秒以内。
这中间的差距,就是专业和不专业的区别。
别总觉得技术是黑盒,只要调接口就行。
底层的数据结构,决定了你系统的上限。
es geo_point 格式 看着简单,细节全是坑。
从数组到对象,从精度到空值,每一步都得小心。
你现在是不是正被某个坐标查询的问题困扰?
或者正在规划新的地理空间项目,想提前避坑?
别自己瞎琢磨了。
很多看似简单的配置,背后都有大量的测试数据支撑。
如果你需要具体的索引模板示例,或者想聊聊你的业务场景怎么设计更合理。
可以直接来找我聊聊。
咱们一起把这个问题彻底解决,别让它成为你项目上线后的定时炸弹。