Всем привет! Буквально недавно я закончил делать геокодер для своих целей Ариадна Под катом рассказ о том, почему я это сделал и на что он способен.
В этой статье не будет ни строчки кода Go. Зато будет полное описание работы геокодера и проблем, с которыми я столкнулся.
И вы можете посмотреть код на Github.
Фон
Я работаю в одной из служб такси Бишкек в Кыргызстане.Мы решили оптимизировать расположение координат по адресу для более оптимального распределения заказов.
Чего у нас нет:
- Полная карта Яндекса, Гугла или 2ГИС
- Доверяйте данным GPS
- Очень разнообразные входные данные
- Openstreetmap
- Собственная накопленная база адресов с координатами
Что могут ввести пользователи?
Пользователи могут вводить адреса в разных форматах:- Уличный дом
- Перекресток
- Название заведения
- Имя точки
- микрорайонный дом
- микрорайон улица дом
Постановка задачи
Создать геокодер, который сможет принимать любые входные данные и выдавать им координаты.Язык поиска только русский.
Как вы попали в эту жизнь?
Прежде чем сделать свой велосипед, я решил посмотреть на уже существующие решения.Были:
Что нам не понравилось в номинации, которую мы получили:- Сложно само по себе
- Сделано на PHP+C (Это не потому, что PHP плохой, а потому, что только для этого инструмента у нас есть Apache и PHP)
- Сложная логика в хранимых процедурах Postgresql
- Может работать со многими источниками геоданных
- Поиск организован на ElasticSearch.
- Я хочу отсортировать данные в OSM и импортировать только то, что нужно для поиска.
- Я могу обрабатывать геоданные перед их индексацией
- Яваскрипт и node.js не люблю, отсюда и отсутствие желания делать поиск по Пелиасу
Дизайн
Был заложен следующий алгоритм:- Сначала получаем геометрию для крупных населенных пунктов (городов, столиц, сел, жилых массивов)
- Выгружаем все возможные адреса и соотносим их с желаемым жилым районом, городом или другим населенным пунктом, задавая нужное значение
- Разгрузка всех дорог
- Ищем перекрёсток дорог
- Ставим все в индекс
- Ищем
Я также хотел улучшить свои навыки в этом.
Выполнение
Кажется, я разобрался, как получать и анализировать данные из OSM. Для жилых районов для фильтрации мы используем теги Place=city,place=village,place=suburb,place=town,place=neighborhood. Чтобы получить адреса, здания: адрес:улица+адрес:номер дома,удобства,магазин,адрес:номер дома Все дороги можно получить с помощью тега шоссе.Были трудности с поиском англоязычных имен на русском языке.
Как я пытался это решить:
- Простая автоматическая транслитерация на русский язык.
В результате получилось абсурдно и неправильно.
Пример преобразования данных: Городской Дом -> Городской Дом.
- Попробуем конвертировать вот так.
Получите транскрипцию слова и затем транслитерируйте его.
Получилось что-то вроде Adrenaline Rush -> Эrdenaline Rush. Сносно, но нужен русский акцент, например Adrenaline Rush.
- Такой механизм появился.
Мы автоматически транслитерируем все данные, используя словарь замены.
Тем не менее, простая и глупая транслитерация работает вполне сносно.
Словарь быстро заполнился после нескольких прогонов данных.
- Нормализовали и довели до русского языка
- адреса указываются в формате Страна, город, село или поселок, микрорайон или жилой район, улица, дом
Я сделал это быстро и получил очень медленную реализацию со сложностью O(n^2).
В качестве временного решения я использую Postgres+postgis для поиска пересечений, пока не найду хороший алгоритм поиска пересечений.
В результате получается хороший парсер данных с osm, который помещает данные в ElasticSearch. Получивший простое название импортер
Автоматизируйте это
Учитывая, что мне вскоре надоело постоянно выкачивать и создавать индексы в ElasticSerch, появился компонент обновления.Также есть автоматическая конфигурация в формате JSON. Автоматизирован процесс скачивания файла и импорта его в Elastic Search. Плюс появилась возможность обновлять данные в ElasticServch без простоев, благодаря псевдонимам.
Как это работает:
- Программа обновления загружает файл
- Узнает текущую версию индекса из конфига
- Увеличивает версию и создает новый индекс
- Заполняет его данными
- Изменяет псевдонимы
- Удаляет старый индекс
- Написание конфигурации
- Запустите обновление .
/ariadna
- пойдем попьем кофе
- Получаем готовый настроенный индекс.
Автоматическое пополнение данных
Помимо OSM у нас еще много водителей и операторов, которые оформляют заказы.Соответственно, у нас есть имя и координаты.
Была сделана следующая схема:
- Треки драйверов хранятся в индексе driver_data.
- Данные из OSM хранятся в индексе osm_data.
- Их объединяет адрес-псевдоним, который используется для поиска адресов.
Общий
В результате получается геокодер, который может:- Найдите координаты, используя синонимы.
например ШВК - ШампанскоеВинКомбинат
- Может искать адреса в определенном радиусе (например, для себя делал поиск адресов в 30 км от центра города)
- Поиск по названию заведения (кафе у Ашота например)
- Поиск пересечений
- Поиск адресов в микрорайонах и спальных районах
- Выполнить обратное геокодирование
- Будет автоматически обновляться новыми данными от водителей.
- Импортер данных
- Средство обновления данных
- веб интерфейс
Минусы
- Протестировано только для Кыргызстана.
- Нет демо
- Нет поддержки всех схем адресации.
Если кому-то проект покажется интересным, то я не против никакой критики, пула запросов, вопросов на Github и отзывов в целом.
Теги: #поиск #геокодирование #обратное геокодирование #osm #OpenStreetMap #OpenStreetMap #Go #Геоинформационные сервисы
-
Важность Использования Купонов На Хостинг
19 Oct, 24 -
Резерв Российского Фриланса
19 Oct, 24