检索与用户给出的最近的地理点(纬度/经度)的最佳方法,我有存储在 MySQL 数据库中的所有地理点的列表

发布于 2024-10-21 08:49:35 字数 208 浏览 2 评论 0原文

我正在尝试创建一个移动应用程序,捕获用户当前的地理点(纬度/经度),将其发送到 Web 服务,然后 Web 服务从长列表中返回 5 个最近的地理点。我不清楚的是如何获得 5 个最近的地理点(我最初的方法是从数据库中获取所有点,然后计算每个地理点与用户地理点之间的距离,并提供离他最近的 5 个地理点)并不是那么昂贵的处理明智。关于我该怎么做有什么建议吗?如果需要更多信息,请告诉我,以便我可以重新发布。

I'm trying to create a mobile application, that capture the user current geopoint(lat/long) send it to a web service and the web service returns the 5 nearest geopoints from the a long list. What i don't have clear is how can i get the 5 nearest geopoints (my initial approach was, getting all the points from the datebase then calculate the distance between each geopoint and the user geopoint and provide with the 5 nearest to him) that is not so costly proccesing wise. Any suggestion on how could i do it? If need more info let me know so i can repost.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

初与友歌 2024-10-28 08:49:35

有多种方法可以做到这一点,您需要的最佳方式可能取决于您拥有的点数(因此它可以很好地扩展)。

对于空间查询,您应该使用支持空间索引的数据库,这样可以加快搜索速度。 PostGIS 就是一个例子,还有 MySQL 的 GIS 扩展 http:// /dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html

这是 PostGIS 中 k-近邻问题的示例解决方案 http://www.bostongis.com /?content_name=postgis_nearest_neighbor_generic

编辑:您还可以使用使用 geohashing 的技术 (http ://en.wikipedia.org/wiki/Geohash),但请务必仔细阅读本文中的限制。

There are a number of ways to do this, and how optimal you need this to be will likely depend on the number of points you have (so it scales well).

For spatial queries, you should use a database that supports spatial indexing, which allows for much faster searches. PostGIS is one example, and there are GIS extensions for MySQL http://dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html.

Here is a sample solution to the k-nearest-neighbor problem in PostGIS http://www.bostongis.com/?content_name=postgis_nearest_neighbor_generic

EDIT: You can also use techniques that use geohashing (http://en.wikipedia.org/wiki/Geohash), but be sure to read the limitations carefully in this article.

离不开的别离 2024-10-28 08:49:35

在我们的esperanto.de 上的联系人地址搜索中,我们使用此 SQL 语句的变体(用 PHP 语法包装):

$demando =
  "SELECT DISTINCT id, [...]" .
  "   AVG(tie.longitudo) AS longitudo, AVG(tie.latitudo) AS latitudo, ".
  "   ROUND(111.3 *  SQRT( POW(({$chi[latitudo]} - AVG(tie.latitudo)),2) + " .
  "                        POW((({$chi[longitudo]} - AVG(tie.longitudo)) * COS(({$chi[latitudo]} + AVG(tie.latitudo)) / 114.6 )),2) )) " .
  "       AS efektiva_distanco " .
  " FROM MA_Adresoj, gxustaj_plzkoord AS tie " .
  " WHERE ( " . $pliaj_restriktoj . ") " .
  "  and (tie.plz = urba_kodo) " .
  " GROUP BY id, urba_kodo, nomo_pers, nomo_fam, adresaldono, strato, loko," .
  "          telefono, retadreso " .
  " HAVING efektiva_distanco < '" . $distanco . "' " .
  " ORDER BY " . $ordo;

过滤给定距离 ($distanco) 内的所有条目。这有点复杂,因为我们需要对单个邮政编码的多个坐标进行平均(这应该在坐标数据库上完成,但没有。)

核心是根据经度和纬度计算距离(以度为单位)这里:(

111.3 *  SQRT( POW(here.latitude - there.latitude),2) +
               POW((here.longitude - there.longitude) * COS( (here.latitude + there.latitude) / 114.6 ),2) ))

结果是以公里为单位的距离。)

我不确定这个公式是否普遍适用或者在某种程度上近似于德国(或者只是较小的距离 - 我认为当一个点是时它会计算出太大的距离赤道的北部和南部具有相似的绝对纬度......并且当东西向差异很大时)。

当然,如果你有很多点,这会变得相当慢 - 那么你要么必须像 iluxas 答案中那样进行一些预过滤,要么更好地使用具有空间索引的数据库。

In our contact adress search on esperanto.de we use a variant of this SQL statement (wrapped in PHP syntax):

$demando =
  "SELECT DISTINCT id, [...]" .
  "   AVG(tie.longitudo) AS longitudo, AVG(tie.latitudo) AS latitudo, ".
  "   ROUND(111.3 *  SQRT( POW(({$chi[latitudo]} - AVG(tie.latitudo)),2) + " .
  "                        POW((({$chi[longitudo]} - AVG(tie.longitudo)) * COS(({$chi[latitudo]} + AVG(tie.latitudo)) / 114.6 )),2) )) " .
  "       AS efektiva_distanco " .
  " FROM MA_Adresoj, gxustaj_plzkoord AS tie " .
  " WHERE ( " . $pliaj_restriktoj . ") " .
  "  and (tie.plz = urba_kodo) " .
  " GROUP BY id, urba_kodo, nomo_pers, nomo_fam, adresaldono, strato, loko," .
  "          telefono, retadreso " .
  " HAVING efektiva_distanco < '" . $distanco . "' " .
  " ORDER BY " . $ordo;

to filter all entries within a given distance ($distanco). It is a bit complicated by the fact that we need to average out several coordinates for a single post code (which should have been done on the coordinate database, but isn't.)

The core is the distance calculation depending on longitude and latitude (in degrees) here:

111.3 *  SQRT( POW(here.latitude - there.latitude),2) +
               POW((here.longitude - there.longitude) * COS( (here.latitude + there.latitude) / 114.6 ),2) ))

(The result is the distance in kilometers.)

I'm not sure if this formula works universally or is somehow approximate for Germany (or only smaller distances - I think it will calculate a too big distance when one point is north and the other south of the equator with similar absolute latitudes ... and also when there is a big east-west difference).

Of course, this will get quite slow if you have many points - then you'll either have to do some pre-filtering like in iluxas answer, or better use a database with spatial indexing.

一个人的夜不怕黑 2024-10-28 08:49:35
select x, y, sqrt((x-userX)^2, (y-userY)^2) as distance from points
where x > userX - 10 and x < userX + 10
and y > userY - 10 and y < userY + 10
order by distance asc
limit 5

当然,语法非常近似

select x, y, sqrt((x-userX)^2, (y-userY)^2) as distance from points
where x > userX - 10 and x < userX + 10
and y > userY - 10 and y < userY + 10
order by distance asc
limit 5

syntax very approximate, of course

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文