Документация
Справочник JavaScript API
2.1.64 (текущая версия)
collection
interactivityModel
Интерфейсы

Поиск по карте

Геокодирование

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

Оба вида геокодирования (прямое и обратное) производятся с помощью функции geocode, в которую можно передать название объекта в виде строки или координаты в виде массива.

var myGeocoder = ymaps.geocode("Петрозаводск");
var myReverseGeocoder = ymaps.geocode([61.79,34.36]);

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

Асинхронное взаимодействие реализовано с помощью обещаний (promises). Вызов функции geocode приводит к (немедленному) созданию объекта типа vow.Promise, который выполнит заданные функции в тот момент, когда от сервера вернутся результаты геокодирования или сообщение об ошибке.

Результат функции geocode передается в функцию-обработчик в виде коллекции GeoObjectCollection. Этот объект реализует интерфейс IGeoObject, то есть может быть размещен на карте.

var myGeocoder = ymaps.geocode("Петрозаводск");
myGeocoder.then(
    function (res) {
        alert('Координаты объекта :' + res.geoObjects.get(0).geometry.getCoordinates());
    },
    function (err) {
        alert('Ошибка');
    }
);

Результаты геокодирования передаются в функцию-обработчик либо в виде коллекции GeoObjectCollection (по умолчанию) либо в виде JSON. Формат возвращаемых данных задается опцией json (true/false). Подробнее о формате возвращаемых данных можно посмотреть Поиск по карте.

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

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

Найденные объекты ранжируются по степени удаленности от заданной точки.

var myCoords = [55.754952,37.615319];
myMap.geoObjects.add(
    new ymaps.Placemark(myCoords,
        {iconContent: 'Где метро?'},
        {preset: 'islands#greenStretchyIcon'}
    )
);
var myGeocoder = ymaps.geocode(myCoords, {kind: 'metro'});
myGeocoder.then(
    function (res) {
        var nearest = res.geoObjects.get(0);
        var name = nearest.properties.get('name');
        nearest.properties.set('iconContent', name);
        nearest.options.set('preset', 'islands#redStretchyIcon');
        myMap.geoObjects.add(res.geoObjects);
    },
    function (err) {
        alert('Ошибка');
    }
);

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

var myGeocoder = ymaps.geocode('Новый Арбат, 10');
myGeocoder.then(
    function (res) {
        var coords = res.geoObjects.get(0).geometry.getCoordinates();
        var myGeocoder = ymaps.geocode(coords, {kind: 'street'});
        myGeocoder.then(
            function (res) {
                var street = res.geoObjects.get(0);
                var name = street.properties.get('name');
                // Будет выведено «улица Большая Молчановка»,
                // несмотря на то, что обратно геокодируются
                // координаты дома 10 на ул. Новый Арбат.
                alert(name);
            }
        );
});

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

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

Чаще всего геокодирование производится на стороне клиента (то есть запросы геокодеру отправляет браузер). При множественном геокодировании такой подход не всегда является оптимальным. Дело в том, что геокодер за один запрос позволяет получать данные только для одного объекта. То есть чем больше адресов необходимо геокодировать, тем больше HTTP-запросов надо отправить.

Отправка большого числа HTTP-запросов приводит к увеличению трафика, а дальнейшая обработка ответов — к уменьшению скорости отображения данных на карте. К тому же высока вероятность превысить суточный лимит в 25000 запросов к геокодеру (см. Пользовательское соглашение). При поиске на карте, например, ста объектов бразуер отправляет серверу сто запросов. Соответственно, при посещении сайта уже 300 пользователей число запросов к серверу достигнет 30000.

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

Геокодирование на стороне сервера

Для реализации геокодирования на серверной стороне разработан Node.js-модуль (multi-geocode), который использует HTTP-сервис геокодирования. Данный модуль позволяет осуществлять поиск сразу множества объектов по их географическим названиям. Полученный результат может быть добавлен на карту с помощью встроенных функций API.

Примечание. Модуль multi-geocode позволяет производить только прямое геокодирование.

Установить модуль можно с помощью менеджера пакетов npm:

npm install multi-geocoder

После установки модуля Node.js-приложению будет доступен класс MultiGeocoder, инициализируемый объектом со следующими полями (все поля являются необязательными):

  • provider – провайдер геокодирования. Поддерживаются провайдеры Яндекса и Google (по умолчанию принимает значение 'yandex');
  • coordorder – предпочитаемый порядок координат в ответе геокодера. По умолчанию координаты возвращаются в последовательности: долгота, широта ('longlat');
  • встроенные параметры геокодирования, допустимые для указанного провайдера.
// Подключаем модуль multi-geocoder
var MultiGeocoder = require('multi-geocoder'),
    // Получаем доступ к сервису геокодирования.
    geocoder = new MultiGeocoder({
        coordorder: 'latlong',
        lang: 'ru-RU'
    });

Для формирования и отправки запроса геокодеру используется функция geocode. Она принимает на вход следующие параметры:

  • массив строк с адресами, которые требуется геокодировать ('Москва, ул Крылатские холмы, 28'), либо массив объектов, содержащих адрес и любые другие свойства ({'address': 'Москва, ул. Крылатские холмы, 28', 'organization': 'школа'});

    Примечание. Перед формированием запроса модуль извлекает адреса из переданного массива с помощью встроенного метода getText. По умолчанию предполагается, что адреса заданы в виде строк, поэтому getText возвращает содержимое элементов массива целиком. Если же адреса заданы в виде объектов с полями, то необходимо переопределить метод getText так, чтобы он возвращал значение полей, содержащих нужные адреса. Подробнее см. ниже.

  • встроенные параметры геокодирования, которые будут применены только для текущего запроса.

Ниже приведен пример геокодирования адресов, заданных в виде строк:

var MultiGeocoder = require('multi-geocoder'),
    geocoder = new MultiGeocoder({ coordorder: 'latlong', lang: 'ru-RU' });

geocoder.geocode([
    'Москва, 1905 года ул., д.19',
    'Москва, 1-ая Квесисская ул., д 18',
    'Москва, 1-й Тверской-Ямской пер, д.16'
    ], {
    // Описание объектов в ответе будет на алглийском языке,
    // несмотря на то что параметр lang задан также в конструкторе MultiGeocoder.
    lang: 'en-US'
})
    .then(function (res) {
        console.log(res);
    });
Примечание. Параметры геокодирования, заданные через функцию geocode, имеют более высокий приоритет по сравнению с параметрами, заданными в конструкторе MultiGeocoder.

В следующем примере в функцию geocode передается массив объектов с полями address, name и phone. Чтобы извлечь из заданных объектов адреса для геокодирования, необходимо переопределить метод getText:

var MultiGeocoder = require('multi-geocoder'),
    geocoder = new MultiGeocoder({ provider: 'yandex', coordorder: 'latlong' }),
    // Получаем экземпляр провайдера.
    provider = geocoder.getProvider();

// Переопределяем метод getText(), извлекающий из переданного массива адреса,
// которые требуется геокодировать.
provider.getText = function (point) {
    var text = 'Москва, ' + point.address;
    console.log(text);
    return text;
};
geocoder.geocode([
    {
        "address": "1905 года ул., д.19",
        "name": "Старый лекарь",
        "phone": "8-499-253-52-61"
    }, {
        "address": "1-ая Квесисская ул., д 18",
        "name": "А5 №2",
        "phone": "8-495-614-04-67"
    }, {
        "address": "1-й Тверской-Ямской пер, д.16",
        "name": "Самсон Фарма №9",
        "phone": "8-495-251-22-27"
    }
])
    .then(function (res) {
        console.log(res);
    }); 

Посмотреть более развернутый пример можно в следующих файлах: index.js, source.json (исходные данные), gecoded.json (результат геокодирования).

Функция geocode возвращает объект-обещание (vow.Promise), который выполнит заданную функцию-обработчик в тот момент, когда сервер вернет результаты геокодирования.

Результат геокодирования передается функции-обработчику в формате GeoJSON. Данный формат предназначен для описания различных структур географических данных. Объекты, представленные в GeoJSON-формате, могут быть добавлены на карту.

Далее представлен результат множественного геокодирования с использованием модуля multi-geocode:


{ type
[no-highlight[

Описание

Тип объекта GeoJSON.

  • FeatureCollection – описание коллекции объектов;
  • Feature – описание конечного объекта.

]no-highlight]
: 'FeatureCollection', features: [{ // Результаты поиска 'Москва, 1905 года ул., д.19' type
[no-highlight[

Описание

Тип объекта GeoJSON.

  • FeatureCollection – описание коллекции объектов;
  • Feature – описание конечного объекта.

]no-highlight]
: 'Feature', bbox
[no-highlight[

Описание

Координаты ограничивающей области.

]no-highlight]
: [ [ 37.556586, 55.765554 ], [ 37.560682, 55.767863 ] ], geometry: { type
[no-highlight[

Описание

Тип геометрии.

]no-highlight]
: 'Point', coordinates
[no-highlight[

Описание

Координаты найденного топонима.

]no-highlight]
: [ 37.558634, 55.766709 ] }, properties: { name
[no-highlight[

Описание

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

]no-highlight]
: 'улица 1905 года, 19', description
[no-highlight[

Описание

Подробный адрес объекта.

]no-highlight]
: 'Москва, Россия', metaDataProperty: { GeocoderMetaData: { kind
[no-highlight[

Описание

Вид найденного топонима. Список доступных значений.

]no-highlight]
: 'house', text
[no-highlight[

Описание

Полный адрес топонима одной строкой текста.

]no-highlight]
: 'Россия, Москва, улица 1905 года, 19', precision
[no-highlight[

Описание

Точность соответствия между номером найденного дома и номером дома из запроса.

]no-highlight]
: 'exact', AddressDetails: { Country: { AddressLine
[no-highlight[

Описание

Запрашиваемая строка в поиске.

]no-highlight]
: 'Москва, улица 1905 года, 19', CountryNameCode
[no-highlight[

Описание

Код страны в соответствии со стандартом ISO 3166-1.

]no-highlight]
: 'RU', CountryName
[no-highlight[

Описание

Название страны.

]no-highlight]
: 'Россия', AdministrativeArea: { AdministrativeAreaName
[no-highlight[

Описание

Область, провинция, край, республика, города — субъекты федерации.

]no-highlight]
: 'Московская область', SubAdministrativeArea: { SubAdministrativeAreaName
[no-highlight[

Описание

Район области, муниципальный район, городское поселение, сельское поселение.

]no-highlight]
: 'Москва', Locality: { LocalityName
[no-highlight[

Описание

Населенный пункт: город, поселок, станица и т. д.

]no-highlight]
: 'Москва', Thoroughfare: { ThoroughfareName
[no-highlight[

Описание

Общепризнанная именованная территория согласно спецификации формата xAL.

]no-highlight]
: 'улица 1905 года', Premise: { PremiseNumber
[no-highlight[

Описание

Конечная единица в иерархии административно-территориального деления. Номер дома, парк, название моста и пр. Подробнее см. в описании спецификации формата xAL

]no-highlight]
: '19' } } } } } } } } } } } // Результаты поиска 'Москва, 1-ая Квесисская ул., д 18' { type
[no-highlight[

Описание

Тип объекта GeoJSON.

  • FeatureCollection – описание коллекции объектов;
  • Feature – описание конечного объекта.

]no-highlight]
: 'Feature', ... } // Результаты поиска '1-й Тверской-Ямской пер, д.16' { type
[no-highlight[

Описание

Тип объекта GeoJSON.

  • FeatureCollection – описание коллекции объектов;
  • Feature – описание конечного объекта.

]no-highlight]
: 'Feature', ... } ] }

Ниже приведен фрагмент кода, демонстрирующий загрузку сохраненных GeoJSON-данных и их добавление на карту:

// Загружаем данные с сервера с помощью jQuery.
jQuery.ajax({
    url: 'http://api.yandex.ru/maps/doc/jsapi/2.1/examples/geocoded.json',
    dataType: 'json'
}).then(function(res) {
      // Формируем выборку на основе загруженных данных.
      var objects = ymaps.geoQuery(res);
      objects.addToMap(myMap);
  });

На данный момент API позволяет манипулировать GeoJSON-данными только через класс GeoQueryResult. Это означает, что на основе загруженных данных необходимо сформировать выборку, после чего уже производить над ней различные действия (добавлять на карту, кластеризовать и т. д.).

Элемент управления «Поиск по карте»

Элемент управления «Поиск по карте» предоставляет пользователям возможность искать на карте интересующие их объекты. Когда пользователь вводит запрос в поисковую строку, API автоматически выполняет поиск и затем отображает на карте найденный результат. При этом объекты можно искать как по адресу, так и по их географическим координатам. Кроме того, через данный элемент управления доступен поиск по организациям.

Элемент управления «Поиск по карте» реализуется классом control.SearchControl. Ниже приведен пример добавления этого элемента управления на карту:

// Создание элемента управления «Поиск по карте».
var searchControl = new ymaps.control.SearchControl({
        options: {
            // Будет производиться поиск и по топонимам и по организациям.
            provider: 'yandex#search'
        }
    });

// Добавляем элемент управления на карту.
myMap.controls.add(searchControl);

Примечание. Чтобы на карте можно было искать не только топонимы, но также и организации, конструктору класса control.SearchControl следует передать опцию provider: 'yandex#search'.

Для того чтобы программно выполнить поиск какого-нибудь объекта, следует вызвать функцию search(). Поиск объектов будет выполнен в рамках текущей прямоугольной области.

searchControl.search('Шоколадница');

Для работы с результатами поиска класс control.SearchControl предоставляет следующие методы:

getResult

Метод, возвращающий найденный объект по заданному индексу. Метод работает в асинхронном режиме. Он возвращает Promise-объект, который разрешится найденным объектом либо отклонится с ошибкой.

var searchControl = new ymaps.control.SearchControl({
        options: {
            // Поиск будет производиться по топонимам и по организациям.
            provider: 'yandex#search'
        }
    });

var result = searchControl.getResult(0);
result.then(function (res) {
    console.log("Результат " + res );
}, function (err) {
    console.log("Ошибка");
});
getResultsArray

Возвращает массив, содержащий все текущие результаты.

var searchControl = new ymaps.control.SearchControl({
        options: {
            // Поиск будет производиться по топонимам и по организациям.
            provider: 'yandex#search'
        }
    });

// Подписываемся на событие выбора результата поиска.
searchControl.events.add('resultselect', function (e) {
    // Получаем массив результатов.
    var results = searchControl.getResultsArray(),
        // Индекс выбранного объекта.
        selected = e.get('index'),
        // Получаем координаты выбранного объекта.
        point = results[selected].geometry.getCoordinates();
})
getResponseMetaData

Возвращает метаданные геопоиска.

var searchControl = new ymaps.control.SearchControl({
        options: {
            // Поиск будет производиться по топонимам и по организациям.
            provider: 'yandex#search'
        }
    });

searchControl.search('Шоколадница');

searchControl.events.add('resultselect', function (e) {
    var index = e.get('index'),
        results = searchControl.getResponseMetaData();
    console.log(results.SearchRequest.request); // Шоколадница
    console.log(results.SearchRequest.results); // 20
})
getResultsCount

Возвращает количество найденных результатов.

var searchControl = new ymaps.control.SearchControl({
        options: {
            // Поиск будет производиться по топонимам и по организациям.
            provider: 'yandex#search'
        }
    });

// Подписываемся на событие получения результатов поиска с сервера.
searchControl.events.add('load', function (e) {
    var count = searchControl.getResultsCount();
    console.log("Количество найденных результатов поиска: " + count);
})
getSelectedIndex

Возвращает индекс выбранного элемента.

var searchControl = new ymaps.control.SearchControl({
        options: {
            // Поиск будет производиться по топонимам и по организациям.
            provider: 'yandex#search'
        }
    });

// Подписываемся на событие получения результатов поиска с сервера.
searchControl.events.add('resultselect', function (e) {
    var index = searchControl.getSelectedIndex(e);
    console.log("Индекс выбранного элемента: " + index);
})
showResult

Отображает результат на карте.

// Мы хотим показывать всегда первый результат
// вне зависимости от количества найденных
// объектов на карте (1 или более).
var searchControl = new ymaps.control.SearchControl({
   options: {
       noSelect: true
   }
});
searchControl.events.add('load', function (event) {
    // Проверяем, что это событие не "дозагрузки" результатов и
    // по запросу найден хотя бы один результат.
    if (!event.get('skip') && searchControl.getResultsCount()) {
        searchControl.showResult(0);
    }
});
hideResult

Скрывает результат, показанный на карте.

// Если мы показали какой-то результат на карте с помощью control.SearchControl.showResult
// или он был показан автоматически при поиске, мы можем скрыть его, например
// по клику на кнопку.
var myButton = new ymaps.control.Button("Скрыть результаты");
myButton.events.add('click', function () {
    searchControl.hideResult();
    }, this);

myMap.controls.add(myButton, {
    selectOnClick: false
});

Список всех доступных методов приведен в справочнике.

С примером использования control.SearchControl можно ознакомиться в песочнице.