Comparison фильтры

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

Фильтры применяются как в декларативном описании стиля (style specification), так и динамически через API метода setFilter. В обоих случаях используется единый синтаксис выражений, совместимый с Mapbox Style Specification.


Базовая структура фильтра слоя

Любой слой в стиле может содержать ключ filter, определяющий правила отбора геометрий:

{
  "id": "cities",
  "type": "circle",
  "source": "places",
  "filter": ["==", ["get", "type"], "city"]
}

Фильтр всегда является выражением в виде массива, где первый элемент — оператор, далее аргументы.


Оператор равенства ==

Оператор == проверяет полное совпадение значений.

Синтаксис

["==", value1, value2]

Пример: фильтрация по типу объекта

["==", ["get", "class"], "highway"]

Этот фильтр оставляет только объекты, у которых свойство class равно "highway".

Важные особенности

  • Сравнение строгое
  • Типы данных учитываются (строка ≠ число)
  • Поддерживает свойства через ["get", "property"]

Оператор неравенства !=

Используется для исключения значений.

Синтаксис

["!=", value1, value2]

Пример: исключение жилых зон

["!=", ["get", "landuse"], "residential"]

Этот фильтр исключает все объекты с типом землепользования residential.


Сравнение числовых значений: >, <, >=, <=

Comparison-фильтры поддерживают числовые операции, что делает возможным построение диапазонных условий.

Больше >

[">", ["get", "population"], 100000]

Оставляет только города с населением более 100000.


Меньше <

["<", ["get", "rank"], 10]

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


Больше или равно >=

[">=", ["get", "elevation"], 500]

Меньше или равно <=

["<=", ["get", "speed_limit"], 60]

Комбинирование условий через логические операторы

Comparison-фильтры часто используются внутри логических конструкций all, any, none.


all — логическое И

Все условия должны выполняться одновременно.

[
  "all",
  ["==", ["get", "type"], "road"],
  [">", ["get", "lanes"], 2]
]

Такой фильтр оставит только дороги с количеством полос больше 2.


any — логическое ИЛИ

Достаточно выполнения одного условия.

[
  "any",
  ["==", ["get", "class"], "primary"],
  ["==", ["get", "class"], "secondary"]
]

none — отрицание набора условий

[
  "none",
  ["==", ["get", "tunnel"], true],
  ["==", ["get", "bridge"], true]
]

Фильтр исключает мосты и туннели.


Проверка наличия свойств: has и !has

has

Проверяет наличие свойства у feature:

["has", "maxspeed"]

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

!has

Обратная проверка:

["!has", "name"]

Выбирает объекты без названия.


Работа с множественными значениями: in

Оператор in позволяет проверить принадлежность значения к набору.

Синтаксис

["in", value, v1, v2, v3]

Пример: категории дорог

["in", ["get", "class"], "motorway", "trunk", "primary"]

Фильтр выбирает объекты, принадлежащие одной из перечисленных категорий.


Обратный оператор: !in

["!in", ["get", "class"], "path", "footway"]

Исключает пешеходные дорожки.


Сравнение строк и чувствительность к регистру

Все comparison-операторы работают с учётом регистра:

["==", ["get", "name"], "Moscow"]

Строка "moscow" не будет совпадать.

Для нормализации часто используется выражение downcase:

["==", ["downcase", ["get", "name"]], "moscow"]

Использование comparison-фильтров в setFilter

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

map.setFilter("cities-layer", [
  ">=",
  ["get", "population"],
  500000
]);

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

Замена фильтра

map.setFilter("cities-layer", null);

Удаляет фильтр и показывает все объекты слоя.


Сложные выражения сравнения

Comparison-фильтры часто становятся частью вложенных выражений.

Пример: многокритериальная фильтрация

[
  "all",
  [">", ["get", "population"], 100000],
  ["<", ["get", "population"], 1000000],
  ["==", ["get", "capital"], true]
]

Такой фильтр оставляет только столицы среднего размера.


Использование арифметики внутри comparison-фильтров

Выражения можно комбинировать с арифметическими операторами:

[">", ["*", ["get", "traffic"], 2], 100]

Фильтр учитывает удвоенный показатель трафика.


Сравнение чисел и отсутствие значений

Особое внимание требуется при работе с отсутствующими данными:

[">", ["get", "score"], 0]

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

[
  "all",
  ["has", "score"],
  [">", ["get", "score"], 0]
]

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

1. Фильтрация объектов по диапазону значений

[
  "all",
  [">=", ["get", "depth"], 10],
  ["<=", ["get", "depth"], 50]
]

2. Исключение категорий

[
  "none",
  ["in", ["get", "type"], "parking", "service"]
]

3. Приоритет отображения важных объектов

[
  "any",
  ["==", ["get", "priority"], "high"],
  [">", ["get", "usage"], 80]
]

Поведение фильтров в рантайме

Comparison-фильтры пересчитываются при каждом изменении данных источника. Это означает, что при обновлении GeoJSON или vector tiles:

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

Ограничения и особенности оптимизации

  • Глубоко вложенные выражения увеличивают стоимость рендеринга
  • Чрезмерное использование any/all снижает производительность на больших наборах данных
  • Операции in с большим списком значений менее эффективны, чем повторные == в некоторых сценариях
  • Проверка has предпочтительнее, чем сравнение с null

Сравнение с альтернативными подходами фильтрации

Comparison-фильтры в MapLibre GL JS заменяют классическую фильтрацию на стороне Jav * aScript:

features.filter(f => f.properties.type === "city")

Однако использование встроенных фильтров:

  • выполняется на уровне рендеринга
  • не требует переработки данных
  • работает с vector tiles напрямую
  • обеспечивает более высокую производительность при больших объёмах данных

Типовые ошибки при использовании comparison-фильтров

  • смешивание типов (строка vs число)
  • отсутствие проверки has перед сравнением
  • неправильный порядок аргументов в in
  • попытка использовать JavaScript-логические операторы вместо выражений (&&, || вместо all, any)
  • использование сложных вычислений внутри фильтра без необходимости