Membership фильтры

Фильтр in реализует проверку принадлежности значения набору допустимых вариантов. В терминах MapLibre GL JS это выражение используется для сопоставления значения свойства объекта с одним из перечисленных элементов.

Базовый синтаксис:

['in', expression, value1, value2, ...]

Где:

  • expression — выражение, возвращающее значение свойства (например, ['get', 'type']);
  • value1...valueN — список допустимых значений.

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

['in', ['get', 'type'], 'park', 'forest', 'lake']

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


Особенности поведения in

Оператор выполняет строгое сравнение без приведения типов. Это означает, что значение "1" и число 1 рассматриваются как разные сущности.

При работе с массивом значений в стиле:

['in', ['get', 'category'], 'road', 'highway']

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

Важный момент: порядок значений не влияет на результат, так как проверка является множественной принадлежностью, а не последовательным сравнением.


Использование in с динамическими выражениями

В качестве первого аргумента может использоваться любое выражение MapLibre:

['in', ['get', 'class'], ['literal', ['primary', 'secondary', 'tertiary']]]

или вычисляемое значение:

['in', ['downcase', ['get', 'name']], 'moscow', 'london', 'paris']

Это позволяет нормализовать данные перед сравнением и уменьшить зависимость от формата исходных данных.


Отрицательная форма !in

Оператор !in инвертирует логику принадлежности. Результат истинный тогда, когда значение отсутствует в списке.

Синтаксис:

['!in', expression, value1, value2, ...]

Пример исключения определённых типов:

['!in', ['get', 'type'], 'building', 'tunnel']

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


Применение !in для очистки слоёв

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

['!in', ['get', 'class'], 'label', 'minor_road', 'annotation']

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


Проверка наличия ключа has и отрицание !has

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

['has', 'name']

Фильтр пропускает только объекты, содержащие свойство name.

Отрицательная форма:

['!has', 'name']

Пропускает объекты, у которых отсутствует свойство name.


Комбинация in с логическими выражениями

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

Пример комбинирования:

[
  'all',
  ['in', ['get', 'type'], 'road', 'path'],
  ['!has', 'bridge']
]

Здесь одновременно проверяется принадлежность типа и отсутствие дополнительного признака.


Вложенные выражения и нормализация данных

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

[
  'in',
  ['to-string', ['get', 'id']],
  '1001',
  '1002',
  '1003'
]

Преобразование типов снижает вероятность несрабатывания фильтра из-за несоответствия форматов.


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

Фильтры in и !in относятся к линейным операциям по списку значений. При увеличении количества элементов в списке возрастает стоимость проверки для каждого объекта слоя.

Практическое поведение:

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

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

Часто встречаются следующие проблемы:

  1. Несовпадение типов:
['in', ['get', 'id'], 1, 2, 3] // при строковых id не сработает
  1. Отсутствие нормализации регистра:
['in', ['get', 'name'], 'moscow'] // не совпадёт с "Moscow"
  1. Избыточные списки значений, усложняющие поддержку стиля

Использование membership-фильтров в стилях слоёв

Фильтры in применяются для управления отображением тематических групп объектов:

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

Пример слоя дорог:

filter: ['in', ['get', 'highway'], 'motorway', 'trunk', 'primary']

Семантика множественной принадлежности

Оператор in реализует проверку принадлежности элемента множеству, что концептуально соответствует операции:

[ x ]

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


Сочетание с другими типами фильтров

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

[
  'all',
  ['in', ['get', 'type'], 'water', 'wetland'],
  ['>=', ['get', 'area'], 1000]
]

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


Особенности обработки в рантайме MapLibre GL JS

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

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


Использование in в динамических стилях

При изменении стиля на лету membership-фильтры сохраняют поведение без пересборки слоя:

map.setFilter('layer-id', [
  'in',
  ['get', 'category'],
  'A',
  'B',
  'C'
]);

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