Фильтрация на стороне сервера

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

Серверная фильтрация означает, что клиент (OpenLayers) не загружает весь датасет, а формирует запросы с условиями: по пространству, атрибутам, временным диапазонам и пользовательским параметрам.


Архитектурная модель передачи фильтров

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

  • пользователь взаимодействует с картой (панорамирование, масштабирование, выбор фильтра)
  • OpenLayers формирует запрос к серверу
  • сервер применяет фильтры к геоданным
  • возвращается ограниченный набор объектов
  • OpenLayers отображает результат

Фильтрация происходит в слоях данных:

  • WMS (растровая выдача)
  • WFS (векторные объекты)
  • Vector Tile Services
  • кастомные REST API

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

Наиболее распространённый механизм — фильтрация по bounding box (BBOX). OpenLayers автоматически подставляет текущий видимый экстент карты.

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

import TileLayer fr om 'ol/layer/Tile';
import TileWMS from 'ol/source/TileWMS';

const layer = new TileLayer({
  source: new TileWMS({
    url: 'https://server/geoserver/wms',
    params: {
      LAYERS: 'workspace:roads',
      TILED: true
    },
    serverType: 'geoserver'
  })
});

Здесь ключевой момент: сервер сам ограничивает выдачу объектов по текущему экстенту карты.

В случае GeoServer BBOX применяется автоматически при каждом запросе тайла.


Атрибутивная фильтрация через WMS параметры

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

В GeoServer поддерживаются:

  • CQL_FILTER
  • FILTER
  • VIEWPARAMS

Пример:

const layer = new TileLayer({
  source: new TileWMS({
    url: 'https://server/geoserver/wms',
    params: {
      LAYERS: 'workspace:buildings',
      CQL_FILTER: "height > 50 AND type = 'residential'"
    }
  })
});

В этом случае сервер возвращает только объекты, соответствующие условию.

Важно: OpenLayers не интерпретирует фильтр, он лишь передаёт строку на сервер.


WFS как основной механизм векторной фильтрации

Для полноценной работы с векторными объектами используется Web Feature Service. OpenLayers позволяет формировать запросы GetFeature с фильтрами.

Пример запроса через ol/format/WFS:

import WFS from 'ol/format/WFS';
import {bbox as bboxFilter} from 'ol/format/filter';

const wfsFormat = new WFS();

const filter = bboxFilter('geom', [30, 50, 40, 60], 'EPSG:4326');

const request = wfsFormat.writeGetFeature({
  srsName: 'EPSG:4326',
  featureNS: 'workspace',
  featurePrefix: 'workspace',
  featureTypes: ['parcels'],
  filter: filter
});

Отправка запроса:

fetch('https://server/geoserver/wfs', {
  method: 'POST',
  body: new XMLSerializer().serializeToString(request)
});

Здесь сервер выполняет:

  • пространственную фильтрацию
  • выборку атрибутов
  • ограничение количества объектов (если настроено)

Атрибутивные фильтры OGC Filter Encoding

WFS поддерживает сложные выражения фильтрации:

  • PropertyIsEqualTo
  • PropertyIsLike
  • PropertyIsGreaterThan
  • логические операции AND/OR/NOT

Пример:

import {equalTo, like, and} from 'ol/format/filter';

const filter = and(
  equalTo('type', 'road'),
  like('name', 'Main*')
);

Такой фильтр передаётся на сервер и выполняется на стороне СУБД (часто PostGIS).


Серверная фильтрация и PostGIS

В типичной архитектуре данные хранятся в PostGIS, а GeoServer транслирует запросы в SQL.

Пример логики на сервере:

SEL ECT *
FROM roads
WH ERE type = 'highway'
AND ST_Intersects(geom, ST_MakeEnvelope(:bbox))

OpenLayers не выполняет SQL, но формирует параметры, которые приводят к таким запросам.


Фильтрация в Vector Tiles

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

OpenLayers:

import VectorTileLayer fr om 'ol/layer/VectorTile';
import VectorTileSource from 'ol/source/VectorTile';

const layer = new VectorTileLayer({
  source: new VectorTileSource({
    url: 'https://server/tiles/{z}/{x}/{y}.pbf'
  })
});

Сервер (например, TileServer GL или кастомный сервис) применяет:

  • фильтрацию по zoom level
  • атрибутные ограничения
  • simplification geometry

Преимущество — минимальный объём данных.


Динамическая серверная фильтрация через параметры URL

Часто используется REST-подход:

const source = new ol.source.Vector({
  format: new ol.format.GeoJSON(),
  loader: function(extent) {
    const url = `/api/features?bbox=${extent.join(',')}&category=park`;

    fetch(url)
      .then(res => res.json())
      .then(data => {
        const features = source.getFormat().readFeatures(data);
        source.addFeatures(features);
      });
  },
  strategy: ol.loadingstrategy.bbox
});

Здесь сервер получает:

  • текущий экстент
  • пользовательские параметры (category, status, filters)

И возвращает уже отфильтрованный GeoJSON.


Стратегии загрузки и влияние на фильтрацию

В OpenLayers ключевую роль играет стратегия загрузки:

  • bbox — загрузка по области видимости
  • tile — загрузка по тайлам
  • all — загрузка всего набора (редко используется)

Пример:

import {bbox as bboxStrategy} from 'ol/loadingstrategy';

const source = new VectorSource({
  loader: loadFunction,
  strategy: bboxStrategy
});

Каждый сдвиг карты вызывает новый серверный фильтр.


Комбинирование пространственных и атрибутивных фильтров

На практике фильтрация почти всегда комбинированная:

  • bbox ограничивает географию
  • CQL/OGC фильтр ограничивает семантику
  • zoom level влияет на детализацию

Пример логики:

результат = объекты
  где объект ∩ bbox ≠ ∅
  и population > 10000
  и status = 'active'

Проблемы и ограничения серверной фильтрации

При неправильной настройке возникают типовые проблемы:

  • отсутствие spatial index на сервере
  • передача сложных фильтров в URL (лимиты GET)
  • избыточные атрибуты в ответе
  • отсутствие paging в WFS
  • блокировка по времени выполнения SQL

Особенно критично в PostGIS без индексов GiST/SP-GiST.


Оптимизация запросов

Серверная фильтрация эффективно работает при соблюдении условий:

  • использование пространственных индексов
  • ограничение набора полей (propertyName)
  • использование тайлов вместо полного WFS
  • кэширование WMS/WMTS
  • предагрегация данных

OpenLayers в этом случае лишь минимизирует нагрузку, не перегружая сервер лишними запросами.


Фильтрация на уровне стилей и серверных правил

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

  • SLD (Styled Layer Descriptor)
  • dynamic rendering rules
  • rule-based symbology

Фильтр может влиять не только на выбор объектов, но и на способ их отображения, что уменьшает объём клиентской обработки.


Поток данных при сложной фильтрации

При комбинированных сценариях поток выглядит так:

  • OpenLayers отправляет bbox + параметры пользователя
  • сервер применяет SQL фильтр
  • PostGIS выполняет пространственный запрос
  • GeoServer формирует GeoJSON/WMS
  • OpenLayers отрисовывает результат
  • при изменении карты процесс повторяется

Поведение при масштабировании данных

При увеличении объёма данных серверная фильтрация становится критически важной:

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

OpenLayers в таких условиях работает как тонкий клиент, делегируя вычисления серверу.