наиболее эффективный способ расчета ближайшего города (из белого списка) - PullRequest
1 голос
/ 20 сентября 2011

У меня есть белый список городов.Допустим, Сиэтл, Портленд, Салем.Используя GeoIP, я бы определил город пользователя.Давайте назовем это $ user_city .Основываясь на $ user_city, я хочу отобразить списки объявлений из ближайшего города из моего белого списка (Сиэтл || Портленд || Салем) с пробегом в 140 миль.Если город не указан в 140 милях, я бы просто показал раскрывающийся список и попросил бы пользователя вручную выбрать город.

Есть несколько способов сделать это:

  1. вычислить это на лету (я нашел алгоритм в одном из ответов SO)
  2. с помощью БД (позвольте мне объяснить):

создать таблицу под названием регионов

регионов будут иметь

город 1 |город 2 |расстояние (до 140 миль)город 1 = города из белого спискагород 2 = любой город в пределах 140 миль от города 1

Это создаст таблицу разумного размера.Если мой белый список содержит 200 городов, и в пределах 140 миль от каждого города есть 40 городов (или городов).Это создаст 8000 строк.

Now, when a user comes to my site:
1) I check if user is from whitelist city already (city 1 column). If so, display that city
2). If not, check if $user_city is in "city 2" column
 2a) if it is, get whitelist city with lowest distance
 2b) if it is not, display drop-down for manual input

Окончательное ограничение : какой бы метод мы ни выбрали, он должен работать изнутри iFrame.Я имею в виду, могу ли я создать эту страницу на моем mysite1.com и встроить эту страницу в someothersite2.com внутри iframe?Удастся ли ему получить user_city и найти ближайший город из белого списка?Я знаю, что существуют некоторые правила междоменных сценариев, поэтому я не уверен, сможет ли iFrame получить IP-адрес пользователя, передать его в GeoIP и разрешить его в $ user_city

Итак, мой вопрос:

Как лучше всего это сделать?Если много людей встраивают мою страницу в свою страницу (используя iframe), то мой сервер будет отбрасываться 10000 раз в секунду (желаемое за действительное, но давайте предположим, что это так).Я не знаю, сможет ли БД справиться с таким количеством ударов.Я не хочу платить за дополнительные серверы БД или веб-серверы.Я хочу минимизировать потребность в ресурсах с моей стороны.Итак, я не возражаю перенести часть работы в браузер пользователя с помощью JavaScript.

РЕДАКТИРОВАТЬ:

  1. В некоторых ответах рекомендуется хранить lat, long и затем выполнятьматематикаПричина, по которой я предложил создать таблицу «регионов», заключается в том, что таким образом вся математика вычисляется заранее.Если у меня есть «белый список» городов, и если я предварительно вычислю все возможные города поблизости для каждого из белого города.Тогда мне не нужно каждый раз вычислять расстояние (например, используя алгоритм Haversine).

  2. Возможно ли выгрузить все это в браузер пользователя с помощью хитроумного использования Java Script?Я не хочу перегружать свой сервер для бесплатного обслуживания.Это может заработать деньги, но я очень близок к банкротству и боюсь, что мой сервер выйдет из строя, прежде чем я заработаю достаточно денег, чтобы заплатить за обновления.

Итак, три ограничения этой проблемы: 1) должен работать изнутри iframe (я надеюсь, что это станет вирусным, и каждый блоггер захочет встроить мой сайт в iframe своей страницы. 2) должен быть очень быстрым 3) должен минимизировать нагрузку на мойсервер

Ответы [ 4 ]

1 голос
/ 20 сентября 2011

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

Да, это возможно ... используя API Карт Google и библиотеку геометрии . Функция, которую вы ищете: google.maps.geometry.spherical.computeDistanceBetween. Вот пример , который я сделал недавно, который может помочь вам начать. Я использую JQuery здесь. Посмотрите на источник, чтобы увидеть, что происходит, и измените по мере необходимости. Кратко:

  1. supplierZips - это массив почтовых индексов, сравнимый с белым списком вашего города.
  2. Первое, что я делаю при загрузке страницы, - это геокодирование местоположений в белом списке. Вы можете сделать это заранее и сохранить результаты в кеше, если ваш белый список постоянен. Это ускорит ваше приложение.
  3. Когда пользователь вводит почтовый индекс, я сначала проверяю, является ли он действительным почтовым индексом из набора данных json всех допустимых почтовых индексов в США (http://ampersand.no.de/maps/validUSpostalCodes.json, 352 кб, данные, сгенерированные из данных почтового индекса в http://www.geonames.org).
  4. Если почтовый индекс действителен, я вычисляю местоположение между этим почтовым индексом и каждым местоположением в белом списке, используя вышеупомянутый computeDistanceBetween в API Карт Google.

Надеюсь, это поможет вам начать.

1 голос
/ 20 сентября 2011
  • Используйте одну таблицу City и выполняйте математические вычисления mysql для каждого запроса с добавлением слоя кэша, например memcache. Честная производительность и очень гибкий!
  • Используйте две таблицы City (id,lat,lng,name) и Distance (city_id1,city_id2,dist), получите свой результат традиционным JOIN. (Может также использовать слой кэша.) Не очень гибкий.
  • Пользовательская структура данных: CityObj (id,lat,lng,data[blob]) просто сериализовать и сжать php-массив городов и сохранить его. Это может удивить вас, но, как мы знаем, узкое место - это не процессор или память, а дисковый ввод-вывод. Это одно чтение из индекса INT в применении к JOIN, который использует таблицу tmp. Это не очень гибко, но будет быстро и масштабируемо. Легко осколок и кластер.
0 голосов
/ 20 сентября 2011

Ваш алгоритм кажется в целом правильным. Я хотел бы использовать PostGIS (плагин postgresql, который проще в настройке, чем кажется :-D). Я считаю, что дополнительная кривая обучения того стоит, это стандарт геоданных.

Если вы поместите города из белого списка в ТОЧКИ, с широтой и долготой, вы можете попросить PostGIS отсортировать по расстоянию до заданного широты / долготы. Это должно быть намного эффективнее, чем делать это самостоятельно (PostGIS очень оптимизирован).

Вы можете получить латы и длины ваших пользовательских городов (и городов белого списка) с помощью API геокодирования, такого как Yahoo Placefinder или Google Maps. Я хотел бы иметь таблицу (либо совпадающую с городами белого списка, либо нет), в которой хранятся названия городов, лат и лон, и выполнять поиск по ней. Если название города не найдено, нажмите API, который вы используете, и сохраните результат в таблице. Таким образом, вам быстро не понадобится использовать API, кроме непонятных мест. API тоже быстрый.

Если вы действительно собираетесь видеть такую ​​нагрузку на сервер, вы, возможно, захотите использовать что-то помимо PHP (например, node.js). Кстати, у вас не должно возникнуть проблем с геокодированием с помощью iframe с точки зрения сервера, точно так же, как браузер переходит на эту страницу «нормально».

0 голосов
/ 20 сентября 2011

Вам просто нужно получить lat и long каждого города и добавить его в базу данных.

Таким образом, в каждом городе есть только 1 запись.На земном шаре не сохраняются расстояния.

Если у вас есть это, вы можете легко выполнить запрос с помощью формулы haversine (http://en.wikipedia.org/wiki/Haversine_formula), чтобы получить ближайшие города в пределах диапазона.

знаю, что существуют некоторые правила междоменных сценариев, поэтому я не уверен, сможет ли iFrame получить IP-адрес пользователя

Можно будет получить IP пользователяили что-то еще, если вы просто получите информацию со встроенной страницы.

Я не знаю, сможет ли БД справиться с таким большим колотанием

Если у вас естьчто многие запросы, которые вы должны были найти, нашли способ заработать на этом :-), который вы можете использовать для обновлений: D

...