QuerySourceFeatures

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

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


Сигнатура метода

map.querySourceFeatures(sourceId, options);

Параметры

sourceId (string) Идентификатор источника, заданного в стиле карты:

map.addSource('cities', {
  type: 'vector',
  url: 'mapbox://examples.8fgz4egr'
});

options (Object, необязательный) Позволяет уточнить выборку данных:

  • sourceLayer — имя слоя внутри векторного тайл-сета
  • filter — фильтр в формате выражений Mapbox GL
  • validate — включение проверки валидности геометрий (редко используется)

Принцип работы

Векторные данные в Mapbox GL JS загружаются по тайлам. Каждый тайл содержит набор фич (features), относящихся к определённым sourceLayer.

querySourceFeatures:

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

Это делает метод быстрым, но ограниченным текущим состоянием кэша тайлов.


Отличие от queryRenderedFeatures

Ключевое различие заключается в уровне абстракции.

queryRenderedFeatures

  • работает с уже отрисованными объектами
  • учитывает стиль, фильтры, visibility
  • возвращает то, что видно пользователю

querySourceFeatures

  • работает с исходными данными тайла
  • игнорирует стиль
  • может возвращать скрытые или отфильтрованные в визуализации объекты

Пример базового использования

map.on('load', () => {
  const features = map.querySourceFeatures('cities');

  console.log(features);
});

Результатом будет массив GeoJSON-подобных объектов:

{
  type: "Feature",
  geometry: {
    type: "Point",
    coordinates: [69.2401, 41.2995]
  },
  properties: {
    name: "Tashkent",
    population: 2500000
  },
  source: "cities",
  sourceLayer: "city_points"
}

Использование sourceLayer

Векторные тайл-сеты почти всегда содержат несколько логических слоёв. Без указания sourceLayer результат может быть пустым или избыточным.

map.querySourceFeatures('cities', {
  sourceLayer: 'city_points'
});

sourceLayer выполняет роль фильтра внутри тайла и существенно влияет на производительность и точность выборки.


Фильтрация данных

Фильтр используется для выборки объектов по атрибутам. Синтаксис совпадает с фильтрами слоёв Mapbox.

map.querySourceFeatures('cities', {
  sourceLayer: 'city_points',
  filter: ['>', ['get', 'population'], 1000000]
});

Часто используемые операторы

  • ['==', ['get', 'field'], value]
  • ['!=', ['get', 'field'], value]
  • ['>', ['get', 'field'], value]
  • ['<', ['get', 'field'], value]
  • ['in', ['get', 'field'], a, b, c]

Ограничения метода

1. Зависимость от загруженных тайлов

Если объект не попал в загруженные тайлы текущего экрана, он не будет возвращён.

2. Отсутствие глобального поиска

Метод не выполняет поиск по всему датасету, только по кэшу.

3. Отсутствие учёта стилей

Слои, opacity, visibility и filter слоя не влияют на результат.


Практические сценарии использования

Поиск объектов по атрибутам

const largeCities = map.querySourceFeatures('cities', {
  sourceLayer: 'city_points',
  filter: ['>', ['get', 'population'], 500000]
});

Агрегация данных на лету

const features = map.querySourceFeatures('roads', {
  sourceLayer: 'road_segments'
});

const totalLength = features.reduce((sum, f) => {
  return sum + (f.properties.length || 0);
}, 0);

Подготовка данных для аналитики

Метод часто используется для построения пользовательских аналитических слоёв поверх карты:

  • кластеризация вне встроенного clustering API
  • построение heatmap-данных вручную
  • расчёт плотности объектов

Поведение при зуме и перемещении карты

Так как данные зависят от тайлов:

  • при изменении zoom набор features может изменяться
  • при pan появляются новые тайлы
  • часть объектов может временно исчезать из результата

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


Взаимодействие с векторными тайл-сетами

Векторные источники разбиваются на тайлы по zoom levels. Каждый тайл содержит подмножество данных.

querySourceFeatures фактически работает с:

  • текущими тайлами
  • локальным кэшем браузера
  • уже загруженными source tiles

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


Фильтрация по геометрии

Хотя метод не предназначен для геопространственных запросов, возможна дополнительная фильтрация после получения данных:

const features = map.querySourceFeatures('cities', {
  sourceLayer: 'city_points'
});

const filtered = features.filter(f => {
  const [lng, lat] = f.geometry.coordinates;
  return lng > 60 && lat > 40;
});

Особенности работы с дубликатами

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

  • в нескольких тайлах
  • на разных уровнях zoom

Это приводит к дублированию features в результате запроса. Устранение дублей обычно выполняется через:

  • id объекта (если присутствует)
  • хэширование геометрии
  • комбинацию source + sourceLayer + id

Производительность

Метод считается относительно быстрым, но его стоимость растёт при:

  • большом количестве загруженных тайлов
  • отсутствии sourceLayer фильтра
  • частых вызовах в move или render событиях

Рекомендуется:

  • кэшировать результаты
  • ограничивать частоту вызовов
  • использовать debounce при событиях карты

Типичные ошибки использования

Отсутствие sourceLayer

map.querySourceFeatures('cities');

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


Ожидание глобальных данных

Запрос не охватывает весь датасет, только загруженные тайлы.


Использование вместо queryRenderedFeatures

Ошибка возникает, когда ожидается визуальный результат, но возвращаются «сырые» данные без учёта стилей.


Интеграция в сложные системы

В продвинутых приложениях метод используется как часть pipeline:

  • загрузка тайлов → querySourceFeatures → агрегация → визуализация
  • анализ данных в реальном времени
  • синхронизация с внешними API аналитики

Работа с динамическими источниками

При обновлении source через:

map.getSource('cities').setData(newGeoJSON);

querySourceFeatures начинает возвращать данные из обновлённого набора только после пересборки тайлов и перерисовки кэша источника.