Получение деталей места

В экосистеме Google Maps JavaScript API получение подробной информации о месте строится вокруг уникального идентификатора place_id. Этот идентификатор является стабильным ключом, который однозначно связывает объект карты (ресторан, улицу, организацию, достопримечательность) с записью в базе Google Places.

Каждое место в системе описывается набором полей, среди которых:

  • название (name)
  • координаты (geometry.location)
  • типы (types)
  • адрес (formatted_address)
  • рейтинг (rating)
  • контактные данные (formatted_phone_number, international_phone_number)
  • сайт (website)
  • часы работы (opening_hours)
  • фотографии (photos)

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


Архитектура получения подробностей места

Получение информации о месте в Google Maps JavaScript API реализуется через сервис Places Library, который исторически включает объект PlacesService и методы вроде getDetails.

Общая схема взаимодействия:

  1. Пользователь выбирает объект (например, через автодополнение или клик по маркеру)
  2. Из объекта извлекается place_id
  3. Выполняется запрос getDetails
  4. Возвращается расширенный объект PlaceResult

В современных версиях API также используется новая модель Place с асинхронными методами, но концептуальная модель остаётся одинаковой: сначала идентификатор, затем запрос подробностей.


Использование PlacesService.getDetails

Классический способ получения информации основан на google.maps.places.PlacesService.

Создание сервиса

const service = new google.maps.places.PlacesService(map);

Здесь map — экземпляр карты, необходимый для инициализации контекста выполнения запросов.


Формирование запроса

Метод getDetails принимает объект запроса:

const request = {
  placeId: "ChIJN1t_tDeuEmsRUsoyG83frY4",
  fields: [
    "name",
    "formatted_address",
    "geometry",
    "rating",
    "opening_hours",
    "photos",
    "website"
  ]
};

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


Выполнение запроса

service.getDetails(request, (place, status) => {
  if (status === google.maps.places.PlacesServiceStatus.OK) {
    console.log(place.name);
    console.log(place.formatted_address);
  }
});

Объект place содержит все запрошенные поля. Статус запроса позволяет определить успешность операции.

Основные статусы:

  • OK — успешный ответ
  • NOT_FOUND — место не найдено
  • INVALID_REQUEST — ошибка параметров
  • OVER_QUERY_LIMIT — превышение лимита
  • REQUEST_DENIED — отказ в доступе

Выбор полей и оптимизация запроса

Одним из ключевых аспектов работы с деталями места является ограничение набора возвращаемых данных. Google Maps JavaScript API требует явного указания fields, что влияет на:

  • стоимость запроса
  • скорость ответа
  • объём передаваемых данных

Пример оптимального запроса

const request = {
  placeId: id,
  fields: ["name", "geometry.location", "rating"]
};

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


Работа с фотографиями места

Фотографии возвращаются как массив объектов PlacePhoto. Каждый объект содержит метод getUrl, позволяющий получить изображение нужного размера.

const photoUrl = place.photos[0].getUrl({
  maxWidth: 400,
  maxHeight: 300
});

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


Часы работы и структурированные данные

Поле opening_hours представляет собой сложный объект, содержащий:

  • open_now — текущее состояние
  • weekday_text — расписание по дням недели

Пример обработки:

if (place.opening_hours) {
  console.log(place.opening_hours.open_now);

  place.opening_hours.weekday_text.forEach(line => {
    console.log(line);
  });
}

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


Современный подход: Place class и асинхронные вызовы

В новых версиях Google Maps JavaScript API вводится объектная модель Place, ориентированная на Promise-based взаимодействие.

Пример:

const place = new google.maps.places.Place({
  id: "ChIJN1t_tDeuEmsRUsoyG83frY4"
});

await place.fetchFields({
  fields: ["displayName", "location", "rating"]
});

Ключевые отличия:

  • асинхронный стиль (await)
  • более строгая типизация полей
  • разделение идентификатора и данных
  • лучшая интеграция с современными фреймворками

Интеграция с автодополнением

Частый сценарий получения деталей места начинается с автодополнения. Пользователь вводит запрос, выбирает вариант, после чего используется place_id.

const autocomplete = new google.maps.places.Autocomplete(input);

autocomplete.addListener("place_changed", () => {
  const place = autocomplete.getPlace();
  const placeId = place.place_id;
});

Важно, что объект, возвращаемый автодополнением, содержит неполные данные. Для полноценной информации обязательно выполняется getDetails или fetchFields.


Ограничения и особенности квотирования

Система запросов в Google Maps JavaScript API работает на основе квот:

  • ограничение количества запросов в секунду
  • лимиты на число деталей места
  • тарификация по полям данных

Ошибка OVER_QUERY_LIMIT часто возникает при массовой загрузке карточек мест без кеширования.


Кеширование результатов

Для повышения производительности используется локальное кеширование по place_id.

Типичная стратегия:

  • хранить результаты getDetails в памяти приложения
  • использовать IndexedDB для долговременного хранения
  • избегать повторных запросов для одного и того же места

Пример структуры кеша:

const cache = new Map();

function getCachedPlace(placeId) {
  return cache.get(placeId);
}

function setCachedPlace(placeId, data) {
  cache.set(placeId, data);
}

Обработка ошибок и деградация функциональности

При работе с деталями места необходимо учитывать нестабильность сетевых запросов.

Основные сценарии обработки:

  • повтор запроса при временной ошибке
  • отображение базовой информации при отсутствии деталей
  • использование fallback-данных из автодополнения
service.getDetails(request, (place, status) => {
  if (status !== google.maps.places.PlacesServiceStatus.OK) {
    console.warn("Fallback mode");
    return;
  }

  renderPlace(place);
});

Структура объекта PlaceResult

Результат getDetails представляет собой комплексный объект, включающий:

  • геометрию (geometry)
  • идентификатор (place_id)
  • метаданные (types)
  • пользовательские данные (reviews)
  • медиа (photos)

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


Использование отзывов и пользовательского контента

Поле reviews содержит массив пользовательских отзывов:

place.reviews.forEach(review => {
  console.log(review.author_name);
  console.log(review.rating);
  console.log(review.text);
});

Каждый отзыв включает:

  • автора
  • рейтинг
  • текст
  • дату

Данные могут быть ограничены по количеству и доступны не для всех мест.


Геометрия и привязка к карте

Поле geometry.location используется для позиционирования маркеров:

const marker = new google.maps.Marker({
  position: place.geometry.location,
  map: map
});

Таким образом, детали места напрямую связываются с визуальным представлением на карте, формируя единый UI-поток: поиск → выбор → отображение.


Стратегия построения интерфейса на основе Place Details

В архитектуре приложений на базе Google Maps JavaScript API данные Place Details часто используются как основа карточек объектов.

Типичный поток данных:

  1. Минимальная карточка из автодополнения
  2. Расширение через getDetails
  3. Рендер полной карточки
  4. Обновление карты и связанных компонентов

Такой подход позволяет отделить быстрый отклик интерфейса от тяжёлых сетевых операций и обеспечить постепенную загрузку данных без блокировки пользовательского взаимодействия.