搞地图开发的兄弟,是不是被“两条线到底交没交”这个问题折磨得想砸键盘?别慌,今天这篇直接给你答案,教你用 Elasticsearch 高效判断直线相交,告别超时和报错。
很多同行还在用旧思路,把线拆成点去比对,结果慢得像蜗牛,还容易漏判。其实,只要搞懂底层逻辑,配合正确的查询方式,几毫秒就能出结果。
先说个大坑:Elasticsearch 原生并没有直接的“直线相交”查询算子。如果你直接搜,大概率会扑街。所以,我们必须换个角度,利用 GeoShape 的拓扑关系来曲线救国。
核心思路很简单:把直线看作一个极细的矩形或者多边形,然后利用 Intersects(相交)或 Within(包含)的逻辑去反推。
第一步,建索引。这是地基,打不好后面全白搭。
在 Mapping 里,你的字段类型必须选 geo_shape。别选 geo_point,那是管点的,不管线。
比如这样写:
"line_field": {
"type": "geo_shape",
"strategy": "recursive",
"precision": "50m"
}
注意 strategy 选 recursive,这样查询性能更稳。precision 设个合理的值,太精细了内存爆炸,太粗糙了精度不够。
第二步,存数据。
存线的时候,别只存两个端点。ES 的 geo_shape 支持 LineString 类型。
POST /my_index/_doc/1
{
"line_field": {
"type": "LineString",
"coordinates": [
[116.40, 39.90],
[116.41, 39.91]
]
}
}
这里有个细节,坐标顺序是 [经度, 纬度],千万别搞反了,不然查出来的结果能让你怀疑人生。
第三步,查相交。
这是最关键的一步。怎么判断两条线相交?
你可以构造一个极小的“缓冲多边形”或者直接用 LineString 去查询。
但更实用的方法是,利用 Intersects 查询。
POST /my_index/_search
{
"query": {
"bool": {
"must": [
{
"geo_shape": {
"line_field": {
"shape": {
"type": "LineString",
"coordinates": [
[116.405, 39.905],
[116.415, 39.915]
]
},
"relation": "intersects"
}
}
}
]
}
}
}
这里 relation 必须用 intersects。这意味着只要你的查询线和存储线有任何重叠部分,都会返回。
但是,等等。
如果你发现查出来结果不对,或者根本查不到,大概率是因为精度问题。ES 的地理空间索引是基于网格的。如果两条线只是理论相交,但在网格精度下没对齐,可能就漏了。
这时候,你需要调整 precision 参数,或者在查询时稍微扩大一点范围,做一个微小的缓冲。
另外,还有一种情况,就是线非常长。
长直线在 ES 里会被自动简化。如果简化后丢失了细节,相交判断就会出错。
所以,对于长直线,建议分段存储,或者在存入前做一定的简化处理,平衡精度和性能。
最后,总结一下。
es geo直线相交 并不是一个现成的 API 调用,而是一套组合拳。
建对索引,存对格式,用对查询关系。
这三步走通了,90% 的问题都能解决。
别再去网上找那些复杂的自定义脚本了,原生功能足够强大,只要你用对了方法。
记住,地图开发不是玄学,是逻辑。
搞懂了网格和拓扑,你就赢了。
赶紧去试试吧,有问题评论区见。
本文关键词:es geo直线相交