Блог API Яндекс.Карт

Множественное геокодирование

15 августа 2012, 12:38

Мы заметили, что достаточно часто пользователи клуба сталкиваются с задачей получения координат для списка адресов (или получения адресов для списка координат). При этом встроенный в API геокодер позволяет получать данные только для одного адреса за один запрос.

Для обработки массива адресов мы написали класс множественного геокодирования. Его интерфейс полностью соответствует интерфейсу стандартного класса геокодирования в API, т.е. принимает те же опции и также возвращает объект-обещание (Promise). С его помощью можно делать смешанное гекодирование в одном запросе: для адресов — прямое, для координат — обратное (["Москва", [55.7, 37.5]]).

Также мы написали пример с использованием этого класса.

Класс множественного геокодирования позволяет получить коллекцию геообъектов для списка адресов и координат на клиенте. Полученная коллекция геообъектов может быть использована для отображения на карте или в качестве источника данных. Например, для добавления в кластер.

Использование этого класса позволяет решить проблемы, возникающие из-за асинхронности работы геокодера. Когда для каждого адреса из списка отправляется отдельный http-запрос, при этом время ответа сервера может быть разное, и как следствие, результаты могут прийти в разном порядке, например пятый адрес может прийти вторым и т.д. Написанный нами класс решает сразу две задачи:
1. Расположить найденные результаты в правильном порядке, соответствующем порядку в массиве адресов во входных данных.
2. Дождавшись ответа по всем запросам, сигнализировать о успешном выполнении и отдать агрегированный результат или вернуть ошибку.

Выбирая решение для вашего проекта, рекомендуем учитывать, что иногда лучше прогеокодировать все адреса на сервере, записать их в базу и работать на клиенте уже с координатами. Таким образом вы сэкономите трафик пользователей. Алгоритм множественного геокодирования на сервере подробно рассмотрен в статье «Получение координат для списка адресов».

42 комментария
Подписаться на комментарии к посту

если множественное геокодирование вставить в кластеризатор, то вид будет:

                       clusterer = new ymaps.Clusterer() ;
                       clusterer.add(res.geoObjects);
                       map.geoObjects.add(clusterer);

или нет ???

 clusterer.add принимает массив геообъектов или один геообъект.

Он не работает с геоколлекциями.

Нужно перебрать геообъекты и добавить в кластеризатор

 

res.geoObjects.each(function (geoObject) {
    clusterer.add(geoObject);
});

подскажите как к меткам добавить балун? или в пример добавьте к меткам балун, что бы посмотреть реализацию. Спасибо.

у меток есть балун, - появляется при клике на метку

или я не понял о чем вы спрашиваете

вы правы я невнятно выразился, как редактировать эти балуны, добавить в них информацию?

например, так

 

res.geoObjects.each(function (geoObject) {

    geoObject.properties.set('balloonContentBody', '_мой_контент_');

});

каждая метка на карте имеет свой адрес и как следствие разное описание... как показать для каждой метки свой контент балуна?

используйте данные геообъекта для формирования своего контента балуна

res.geoObjects.each(function (geoObject) {

    var data = geoObject.properties.getAll();


    geoObject.properties.set('balloonContentBody', '

' + data.name + '

' + data.description + '

' );

});

Контент балунов геообъектов у меня представлен в виде массива ("контент1","контент2","контент3", и т.п.). Как я понял нужно поочедно перебирать data.name и data.description, но до самой реализации кода не дошел... Подскажите или ткните где почитать.

Если я правильно понимаю - у вас контент балунов хранится в отдельном объекте (массиве)

Вам нужно сопоставлять данные пришедшие из геокодера со своими и выбирать нужный элемент массива, помещая его содержимое в контент балуна геообъекта

когда передаем массив адресов:

 // Геокодирование массива адресов и координат.
 mGeocoder.geocode([массив адресов])

тут же возможно передавать и массив контента балунов? что-то я совсем уже запутался:-)

а зачем?

вы уже после геокодирования получаете упорядоченную коллекцию геообъектов

метки идут в ней в том же порядке что и на входе, и если порядок следования данных для балунов в вашем массиве упорядочен так же, вы можете просто перебирая результаты геокодирования брать из него контент балуна по тому же индексу

подключил массив в контентом балунов

 

// Подключаем класс множественного геокодирования после загрузки АПИ.
 $.getScript('https://raw.github.com/dimik/ymaps/master/multi-geocoder.js', function () {
 var mGeocoder = new MultiGeocoder({ boundedBy : map.getBounds() });

// Геокодирование массива адресов и координат.
 var par;
 par=0;

 var dataname = [$MYINF_52$];
 //for(par=0;par mGeocoder.geocode([
 $MYINF_49$
 ])
 .then(

 function (res) {
 // Асинхронно получаем коллекцию найденных геообъектов.
 res.geoObjects.each(function (geoObject) {
 var data = geoObject.properties.getAll();
 geoObject.properties.set('balloonContentBody', '

' + dataname[par] + '

' );
 par++;
});
 


clusterer = new ymaps.Clusterer();
 res.geoObjects.each(function (geoObject) {
 clusterer.add(geoObject);
});
 map.geoObjects.add(clusterer);
 },

но описание метки не совпадает с ее расположением. Дело в том, что адреса меток берутся напрямую с сайта и они не всегда "удовлетворительного качества" (вида - "пр.Кирова, офис 258"), соответственно Яндекс не находит метку с таким адресом, а содержимое балуна этой же метки переходит на следующую точку. Как с этим бороться?

может вам лучше прогеокодировать ваши адреса один раз на серверной стороне и сохранить координаты в базу?

и уже на клиенте работать с координатами.

Это избавит ваших пользователей от сотен лишних http-запросов (съекономит их траффик и время)

 

с серверным кодированием понятно

подскажите, можно ли все таки вместе с адресом передавать геокодеру параметры объекта (название, описание, хотя бы ID), чтобы геокодер возвращал их в каком то виде

такая же проблема, если метку не находит, все описания съезжают

id нет,

а исходный запрос геокодер возвращает

Здравствуйте. А существует ли сейчас адекватный способ множественного геокодирования на клиенте, гарантирующий, что полученная коллекция будет упорядочена так же, как исходный массив строк? Указанный в коде вызов конструктора ListCollection() у меня не выполняется, я вообще не нашел ни единого его упоминания в документации, единственный найденный в API 2.x класс, позволяющий добавлять элементы с указанием индекса, который я нашел — GeoObjectArray — работает через push или splice, а надо бы, чтобы вставлял точно по индексу, не трогая соседей, ну а в 2.1β Promises не работают пока.

Мне пришло в голову только переписать предложенный класс таким образом, чтобы он сначала собирал элементы в динамически расширяемый массив, а потом уже отдавал его элементы в виде ymaps-коллекции.

Адекватный способ описан в этом примере.

ListCollection в документации нет, так как это расширенная мной реализация геоколлекции, и в примере она подключается отдельным файлом

Все файлы есть на гитхаб

 

Вообще делать множественное геокодирование на клиенте - плохое решение.

Лучше всегда по возможности его избегать

Ох, спасибо за разъяснение, не пришло в голову посмотреть остальные файлы в репозитории.

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

Здравствуйте

Начал разбиратсья с API, возникла задача своей подписи к каждой метке, пока только начал,но  сразу же наткнулся на непонятную проблему

// Геокодирование массива адресов.
mGeocoder.geocode([
"г. Кемерово, пр. Советский 27, оф. 515",
"г. Кемерово, пр. Октябрьский 31, оф. 515",
"г. Кемерово, пр. Ленинградский 38, оф. 515",
"г. Кемерово, пр. Ленина 35, оф. 515",
"г. Кемерово, 50 лет Октября 26"

])
.then(function (res) {
// Асинхронно получаем коллекцию найденных геообъектов.
res.geoObjects.each(function (geoObject) {
geoObject.properties.set('balloonContentBody', '_мой_контент_');
myMap.geoObjects.add(geoObject);
});
});

Почему то метки на карту добавляются через одну, т.е. первая, третья, пятая, а промежуточные как будто игнорируются, не могу понятьв  чем проблема...

 

 

 

 

 

Когда вы перекладываете метки в другую коллекцию, она удаляется из текущей. Поэтому происходит такой эффект

Тогда логику понял) т.е. получается на следующем шаге перескакивает через одну. А вот как этого избежать не могу сообразить...

Лучше так не делать.

Но если надо, то можно например так:

var geoObject;

while(geoObject = res.geoObjects.get(0)) {

    myMap.geoObjects.add(geoObject);

}

Спасибо)
Множественное геокидрование практически использовать не планирую, только для новых объектов разово

Доброе вермя суток! У меня задача геокодировать около 100 адресов (в 1С 8,1). Вставил ваш пример,а он выдает ошибку:  

Строка 48, символ 5. Объект не подерживает это свойство или метод код 0.

https://raw.github.com/dimik/ymaps/master/multi-geocoder.js?_=1349683952618 Подскажие что не так?

Все-таки хотелось бы понять как сделать собственный балун на основе этого примера http://api.yandex.ru/maps/jsbox/multigeocode

Задача вроде несложная, но как сделать ума не приложу.

Имеется массив информации, который надо отобразить на карте:

1. Адрес в текстовом виде.

2. Текстовый комментарий к адресу.

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

Помогите пожалуйста! Особенно со вторым пунктом.

Я Вам очень рекомендую поискать ответ в клубе и если не найдете, открыть там тему. http://clubs.ya.ru/mapsapi/

Все таки может кто обьяснить как к уже имеющейся информации балуна добавить дополнительную, а так же как сменить метку на свою картинку?

Плиз с примером куда вставить, а то примеры что здесь куда не пробовал вставить всё ошибка

Создайте новую тему с описанием что не получается и приложите ссылку на страницу

IE8 выдал ошибку:

Сообщение: Объект не поддерживает это свойство или метод

Строка: 50

Символ: 5

Код: 0

URI-код: /multi-geocoder.js


там строка:requests.forEach(function (request, index) {
видимо не поддерживается forEach. Как-то можно победить?

Я обычно подключаю es5-shim от Криса Коваля, чтобы не думать поддерживает броузер EcmaScript5 или нет.

спасибо. А то я уж через for переписал :)

кстати в примере он подключен. видимо вы просто не обратили внимание

каюсь, в песочницу смотрел, а в пример не глянул 

записал в переменную адреса в формате:

'Санкт-Петербург Лиговский проспект, 1',
'Санкт-Петербург Композиторов,10',
'Санкт-Петербург Юбилейный квартал 68а'

подставил ее в код:

.........

        myMultiGeocoder = new MultiGeocoder({ boundedBy: myMap.getBounds() });
    // Геокодирование массива адресов и координат.
    myMultiGeocoder.geocode([
    listItemInfo
    ])
.......

и не работает. создает всего одну метку. Если скопировать то, что содержит переменная и вставить вместе нее в код:

.........

        myMultiGeocoder = new MultiGeocoder({ boundedBy: myMap.getBounds() });
    // Геокодирование массива адресов и координат.
    myMultiGeocoder.geocode([
'Санкт-Петербург Лиговский проспект, 1',
'Санкт-Петербург Композиторов,10',
'Санкт-Петербург Юбилейный квартал 68а'
    ])
.......

то создаются 3 метки.

multi-geocoder.js выдаёт ошибку

TypeError: ymaps.util.Promise is not a constructor
promise = new ymaps.util.Promise(),

Я уже понял, что Promise переместился в ymaps.vow, но при простой замене ymaps.util.Promise на ymaps.vow.Promise скрипт перестаёт работать - не срабатывает .then()

http://api.yandex.ru/maps/doc/jsapi/2.0/ref/reference/util.Promise.xml

http://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/vow.Promise.xml

Как решить?

 

upd: пока единственное быстрое решение использую 2.0-stable версию.

Мы крайне не рекомендуем делать множественное геокодирование на клиенте.

Расскажите зачем вам это

Чтобы отметить маркеры на карте, при известном только текстовом адресе. А как тогда?

Ясно, в моём случае идеально подошел мой вариант. Уже всё сделано, спасибо.

Вот немного исправленная версия, работает с 2.1:

https://github.com/deflexor/ymaps/blob/patch-1/multi-geocoder.js

Добрый день! Скажите, работает ли класс множественного геокодирования http://dimik.github.io/ymaps/examples/multi-geocoder/multi-geocoder.js в версии карт 2.1 ??

 При попытке прицепить версию карт 2.1 на страницу с примером http://dimik.github.io/ymaps/examples/multi-geocoder/ ругается на 46 строку вышеуказанного скрипта.