Поиск близости

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

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

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

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

См. Также штраф movable-type.co.uk/scripts/latlong.html#cosine-law

Arjan 29.05.2010 21:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
21
1
9 678
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Если записей достаточно, чтобы скорость имела значение, вот способ их заблаговременно проиндексировать.

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

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

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

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

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

Мы используем это для определения многих тысяч точек. Если вы выполняете это в 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

Другие вопросы по теме