2008-11-03 4 views
21

Как приложение выполняет поиск по близости? Например, пользователь вводит почтовый код, затем приложение перечисляет все предприятия в пределах 20 миль, заказанных по близости.Поиск близости

Я хочу построить что-то подобное в PHP и MySQL. Правильно ли этот подход?

  1. Получит адрес для местоположений Я заинтересован в и магазине в моей базе данных
  2. Геокодирование всего адрес службы
  3. геокодирования Google, Напишите запрос к базе данных, которая включает в себя формулу Haversine, чтобы сделать поиск близости и упорядочивание

В порядке ли? На шаге 3 я собираюсь рассчитать близость для каждого запроса. Лучше ли иметь таблицу PROXIMITY, в которой указано расстояние между каждым бизнесом и несколькими ссылочными позициями?

+1

См. Также мелкий http://www.movable-type.co.uk/scripts/latlong.html#cosine-law – Arjan 2010-05-29 17:11:32

ответ

9

Если данных о скорости достаточно, достаточно указать их заранее.

Определите сетку бункеров около 20 миль на стороне. Сохраните номер ячейки с записью каждого магазина. Во время поиска вычислите числа всех бинов, которые пересекают 20-мильный радиус от точки поиска. Затем загрузите все магазины в любом из этих ящиков и действуйте по-прежнему.

2

Мы делаем это примерно для 1200 мест. Я бы просто использовал формулу Хаверсина «на лету», хотя в зависимости от вашего приложения лучше было бы хранить его в PHP вместо SQL. (Наша реализация в .net, поэтому ваше перемещение может меняться).

Действительно, наш самый большой недостаток в том, как мы его реализовали, заключается в том, что каждый расчет (до недавнего времени) должен был быть рассчитан на уровне данных, который был болезненно медленным (когда я говорю медленно, я действительно имею в виду немедленное принятие второй или около того), но это было связано с тем, что ему приходилось вычислять расстояние для всех 1200 мест на основе поставленного почтового индекса.

В зависимости от выбранного маршрута существуют способы ускорить расчет расстояний между номерами, взглянуть на долготу и широту и удалить их за пределами предопределенного диапазона (например, если вы просматриваете весь адрес в течение 20 миль есть диапазон долготы, вы можете рассчитать, что все адреса должны упасть, чтобы быть в 20 милях.) Это может ускорить ваш запрос, если это необходимо.

Мы действительно посмотрели на хранение всех возможных комбинаций в нашей базе данных. На самом деле это звучит так, будто это может быть большой магазин данных, но это действительно не в большом объеме вещей. С индексами это может быть довольно быстро, и вам не нужно беспокоиться об оптимизации алгоритмов и т. Д. Мы решили против этого, потому что у нас было уравнение в C#, и это позволило нам кэшировать информацию, необходимую для выполнения всех вычислений в бизнес-уровня. Либо все будет работать отлично, это всего лишь вопрос ваших предпочтений.

11

Мы используем это, чтобы сделать много тысяч точек. Важно, если вы выполняете это в SQL, чтобы иметь индекс в столбце Широта и долгота. Мы попытались сделать это в SQL 2008 с пространственными индексами, но мы действительно не видели увеличения производительности, которого мы ожидали. Хотя, если вы хотите рассчитать на определенном расстоянии от ZIP, вам нужно подумать о том, собираетесь ли вы использовать ZIP-центр или многоугольное представление почтового индекса.

Haversine forumla - хорошее место для начала.

У нас не было проблем с производительностью, вычисляющих расстояние «на лету», мы вычисляем это заранее для некоторых приложений, где мы знаем моменты раньше времени, и там будут миллионы записей.

SELECT 
     [DistanceRadius]= 
     69.09 * 
     DEGREES(
      ACOS(
      SIN(RADIANS(latitude))*SIN(RADIANS(@ziplat)) 
      + 
      COS(RADIANS(latitude))*COS(RADIANS(@ziplat)) 
      * 
      COS(RADIANS(longitude - (@ziplon))) 
     ) 
     ) 
     ,* 
     FROM 
      table 

    ) sub 
WHERE 
    sub.DistanceRadius < @radius 
Смежные вопросы