如何在附近 100w 的商户中,快速找到离你最近的 5 家商户?
如何在附近 100w 的商户中,快速找到离你最近的 5 家商户?
回答重点
可以使用 MySQL 或 MongoDB 的空间索引,或者使用 Redis 提供的 Geo 数据结构来存储商户位置的位置信息来实现根据距离的快速查找。
使用空间索引
例如 R-tree,它适用于二维空间的树形数据结构,能够高效地进行范围查询和最近邻查询。将商户位置(经纬度)数据按照地理区域组织成树结构,可以快速找到位于用户当前位置附近。
像 MySQL 就支持 R-tree,或者使用 MongoDB 也支持空间索引。
拿 MongoDB 距离,实现步骤就是:
1)创建一个地理集合
2)将商家的经纬度导入到集合中
1 | [{name:"商家A", location:{ type:"Point", coordinates:[111,22]}}, |
3)创建地理索引
给 location 创建 2dsphere 索引
4)根据自己的坐标,利用 $near 查询附近距离
1 | { |
这里已经自动按最近的排序了,再结合 .limit(20) 即可得到最近的 20家饭店。
使用 Redis 的 Geospatial
Redis 内部使用 Geohash 算法将地理坐标编码为字符串的技术,通过将地球表面划分成网格,来减少坐标的存储空间,并且能够根据前缀进行范围搜索实现快速的区域范围搜索。
1)数据存储:
使用 Redis 的 GEOADD 命令,将饭店的地理位置信息存储在 Redis 中。每个饭店的经纬度信息作为空间坐标进行存储,并关联到饭店的唯一标识符。
1 | GEOADD restaurants:locations longitude1 latitude1 restaurant_id1 |
2)查询附近的饭店:
使用 GEORADIUS命令,根据用户当前位置(经纬度)查询指定半径内的饭店,并按距离排序,返回最接近的 20 家饭店。
1 | GEORADIUS restaurants:locations user_longitude user_latitude radius km WITHDISTANCE COUNT 20 ASC |
- user_longitude 和 user_latitude 是用户的经纬度。
- radius 是查询的半径,单位可以是 m(米)、km(千米)等。
- WITHDISTANCE 返回与用户的距离。
- COUNT 20 ASC 返回距离最近的前 20 个结果,并按距离升序排列。
扩展知识
Comments