按彼此接近度对坐标进行分组

Group coordinates by proximity to each other

我正在构建 REST API,因此答案不能包含 google 地图或 javascript 内容。 在我们的应用程序中,我们有一个 table 包含看起来像这样的帖子:

  ID |   latitude   | longitude   | other_sutff
   1 | 50.4371243   |  5.9681102  |    ...
   2 | 50.3305477   |  6.9420498  |    ...
   3 | -33.4510148  | 149.5519662 |    ...

我们有一个地图视图,其中显示了世界各地的所有帖子。 希望我们会有很多帖子,在地图上显示成千上万的标记会很荒谬。所以我们想按邻近程度对它们进行分组,这样我们就可以按大陆划分 2-3 个标记。

明确地说,我们需要这个: 图片来自https://github.com/googlemaps/js-marker-clusterer

我做了一些研究,发现 k-means 似乎是解决方案的一部分。 因为我的数学真的很差,所以我尝试了几个 php 库,比如这个:https://github.com/bdelespierre/php-kmeans 似乎做得不错。 但是,有一个缺点:每次加载地图时我都必须解析所有 table。就性能而言,这太糟糕了。

所以我想知道是否有人已经解决了这个问题或者是否有更好的解决方案。

我一直在搜索,我找到了 KMeans 的替代方法:GEOHASH

维基百科会比我更好地解释它是什么:Wiki geohash

但总而言之,世界地图分为 32 个单元格,每个单元格都有一个字母数字字符。 每个单元格也分为 32 个单元格等 12 个级别。 因此,如果我在散列的第一个字母上执行 GROUP BY,我将获得最低缩放级别的集群,如果我想要更高的精度,我只需要按散列的前 N ​​个字母进行分组。

所以,我所做的只是在我的 table 中添加了一个字段,并生成了与我的坐标相对应的哈希值:

ID |   latitude   | longitude   | geohash      | other_sutff
 1 | 50.4371243   |  5.9681102  | csyqm73ymkh2 |     ...
 2 | 50.3305477   |  6.9420498  | p24k1mmh98eu |     ...
 3 | -33.4510148  | 149.5519662 | 8x2s9674nd57 |     ...

现在,如果我想获得我的集群,我只需要做一个简单的查询:

SELECT count(*) as nb_markers FROM mtable GROUP BY SUBSTRING(geohash,1,2); 

子串中,2为精度级别,必须在1到12之间

PS : Lib I used to generate my hash