Existential фильтры

Фильтры в стиле MapLibre GL JS основаны на выражениях, которые вычисляются для каждого объекта слоя и определяют, должен ли этот объект быть отображён или нет. В рамках спецификации стилей ключевое место занимают экзистенциальные (existential) фильтры, позволяющие проверять наличие или отсутствие конкретных свойств в данных источника.

MapLibre GL JS использует фильтрационную систему, совместимую со спецификацией Mapbox Style Specification, где фильтры описываются в виде массивов. Экзистенциальные операторы относятся к базовому набору логики отбора объектов и работают на уровне наличия атрибутов, а не их значений.


Экзистенциальный фильтр отвечает на единственный вопрос: существует ли у объекта заданное поле (property) в его данных.

Векторные тайлы содержат объекты (features), каждый из которых может иметь набор атрибутов. Эти атрибуты не всегда полные: часть данных может отсутствовать в зависимости от источника, типа слоя или этапа обработки.

Экзистенциальные фильтры позволяют:

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

Оператор has

Базовый оператор экзистенциального фильтра — has.

Синтаксис

["has", "property_name"]

Логика работы

Фильтр возвращает true, если у объекта присутствует указанное свойство.

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

{
  "id": "points-with-name",
  "type": "circle",
  "source": "places",
  "filter": ["has", "name"],
  "paint": {
    "circle-radius": 6,
    "circle-color": "#ff6600"
  }
}

В данном случае на карте отображаются только те объекты, у которых присутствует атрибут name.

Поведение при разных типах данных

  • строка: проверяется наличие ключа property_name
  • числовое значение: учитывается только факт существования поля, а не его значение
  • null: считается отсутствующим значением в большинстве источников

Оператор !has

Противоположность has — фильтр отсутствия свойства.

Синтаксис

["!has", "property_name"]

Логика работы

Фильтр возвращает true, если свойство отсутствует у объекта или не определено.

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

{
  "id": "unclassified-features",
  "type": "circle",
  "source": "places",
  "filter": ["!has", "category"],
  "paint": {
    "circle-radius": 4,
    "circle-color": "#999999"
  }
}

Этот слой визуализирует объекты без категории, позволяя выделять «неразмеченные» данные.


Роль экзистенциальных фильтров в структуре выражений

Фильтры в MapLibre GL JS поддерживают композицию через логические операторы:

  • all (логическое И)
  • any (логическое ИЛИ)
  • none (логическое НЕ)

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

Пример комбинированного фильтра

[
  "all",
  ["has", "name"],
  ["!has", "temporary"],
  [">=", ["get", "population"], 1000]
]

Здесь объект будет отображён только если:

  • присутствует имя
  • отсутствует признак временности
  • население не меньше 1000

Экзистенциальные проверки формируют первую ступень отбора, после которой применяются числовые и логические условия.


Отличие от проверки значений

Экзистенциальные фильтры принципиально отличаются от сравнительных операторов.

Тип проверки Пример Что проверяется
Экзистенциальная ["has", "name"] существует ли поле
Сравнительная [">", ["get","population"], 1000] значение поля

Ключевой момент: has не анализирует содержимое, только структуру объекта.


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

1. Фильтрация неполных данных

В реальных геоданных часто отсутствуют дополнительные атрибуты.

["has", "height"]

Используется для отображения только объектов с измеренной высотой (например, зданий).


2. Разделение данных по уровню детализации

["all",
  ["has", "name"],
  ["has", "type"]
]

Позволяет отделить «полноценные» объекты от базовых геометрий без описания.


3. Очистка визуализации

["!has", "debug"]

Исключает служебные или тестовые объекты.


4. Условная стилизация

Экзистенциальные фильтры часто используются в нескольких слоях для создания визуальной иерархии.

// слой с полными данными
["has", "name"]

// слой с неполными данными
["!has", "name"]

Поведение при обработке источников данных

Векторные источники MapLibre GL JS могут иметь разную структуру:

  • GeoJSON
  • Vector Tiles (MVT)
  • динамически сформированные источники

Экзистенциальные фильтры применяются на этапе рендеринга и зависят от наличия ключей в текущем feature.

Важно учитывать:

  • отсутствие свойства в тайле трактуется как его отсутствие
  • значение null часто эквивалентно отсутствию
  • вычисляемые выражения (["get", ...]) не создают свойства, а только читают их

Взаимодействие с выражением get

Экзистенциальные фильтры часто используются совместно с get, но между ними есть различие:

  • has проверяет наличие
  • get извлекает значение

Пример

[
  "all",
  ["has", "population"],
  [">", ["get", "population"], 5000]
]

Без has выражение может давать неожиданные результаты, если поле отсутствует, так как get вернёт undefined или null.


Особенности производительности

Экзистенциальные фильтры являются одними из самых дешёвых операций в системе фильтрации:

  • не требуют вычислений
  • не выполняют арифметику
  • работают как проверка наличия ключа

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


Ограничения и нюансы

Несмотря на простоту, поведение has и !has зависит от источника данных:

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

Также важно учитывать, что:

  • экзистенциальные фильтры не различают тип значения
  • наличие 0 или "" не равно отсутствию свойства

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

Ошибка: ожидание проверки значения

["has", "population", 1000]

Логическая ошибка: has не принимает значение для сравнения.


Ошибка: дублирование условий

["all",
  ["has", "name"],
  ["!has", "name"]
]

Такое выражение всегда возвращает false, так как условия взаимоисключающие.


Ошибка: подмена проверки значения

["has", "population"]

при фактической необходимости:

[">", ["get", "population"], 0]

Использование в архитектуре стилей

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

  1. проверка наличия атрибута
  2. разделение слоя
  3. применение числовых и категориальных условий
  4. стилизация

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


Композиция с категориальными фильтрами

[
  "all",
  ["has", "class"],
  ["in", ["get", "class"], "road", "path", "track"]
]

Здесь экзистенциальная проверка гарантирует, что поле существует до выполнения операции принадлежности к набору значений.


Значение в реальных картографических системах

Экзистенциальные фильтры становятся критичными при работе с:

  • OSM-данными с неполной атрибуцией
  • агрегированными датасетами
  • тайловыми сервисами с упрощением геометрии
  • динамическими источниками данных

Они позволяют строить устойчивые стили, не зависящие от идеальной структуры входных данных.