GIS-LAB

Географические информационные системы и дистанционное зондирование

Руководство по PostGIS

4.7. Использование Mapserver

<<< предыдущая глава | оглавление | следующая глава >>>

Mapserver - картографический веб-сервер, который поддерживает спецификацию OpenGIS Web Mapping Server.

4.7.1. Основы использования

Для использования PostGIS с Mapserver, вы должны знать, как конфигурировать Mapserver, это выходит за рамки данной документации. В этом разделе описывается специфика использования PostGIS и детали конфигурирования.

Для использования PostGIS с Mapserver вам понадобятся:

  • PostGIS версии 0.6 или выше.
  • Mapserver версии 3.5 или выше.

Mapserver получает доступ к данным PostGIS/PostgreSQL, как и любой другой клиент PostgreSQL, с помощью libpq. Это означает, что Mapserver может быть установлен на любую машину с сетевым доступом к серверу PostGIS, если только в системе есть клиентские библиотеки PostgreSQL libpq.

  1. Скомпилируйте и установите Mapserver с любыми нужными вам опциями включив опцию конфигурации "--with-postgis".
  2. В map-файл вашего Mapserver-а добавьте слой PostGIS. Например:
    LAYER
      CONNECTIONTYPE postgis
      NAME "widehighways"
      # Соединение с удаленной пространственной базой данных
      CONNECTION "user=dbuser dbname=gisdatabase host=bigserver"
      # Получение линий из столбца 'geom' таблицы 'roads'
      DATA "geom from roads"
      STATUS ON
      TYPE LINE
      # Из имеющихся линий выбрать только широкие дороги
      FILTER "type = 'highway' and numlanes >= 4"
      CLASS
          # Супермагистрали сделать более яркими и установить их ширину в 2 пикселя
          EXPRESSION ([numlanes] >= 6)
          COLOR 255 22 22
          SYMBOL "solid"
          SIZE 2
      END
      CLASS
          # Все остальные - более темные и широной в 1 пиксель
          EXPRESSION ([numlanes] < 6)
          COLOR 205 92 82
       END
    END

    Приведенный пример содержит следующие специфические директивы относящиеся к PostGIS:

    CONNECTIONTYPE
    Для слоев PostGIS всегда должен быть равен "postgis".

    CONNECTION
    Соединение с базой данных управляется "строкой соединения ", которая содержит стандартный набор указанных ниже ключей и значений (значения по умолчанию заключены в скобки <>):

    user=<имя пользователя> password=<пароль> dbname=<имя базы> hostname=<имя сервера> port=<5432>

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

    DATA
    Этот параметр указывается в форме "<столбец> from <имя_таблицы>", где столбец подразумевает пространственный столбец, представленный на карте.

    FILTER
    Фильтр должен быть правильной строкой SQL, соответствующей логике, обычно следующей после ключевого слова "WHERE" в SQL-запросе. Так, например, для выбора только 6-рядных (или более) улиц, используется фильтр "num_lanes >= 6".
  3. Постройте пространственные (GiST) индексы на тех данных, с помощью которых будете рисовать какие-либо слои.
    CREATE INDEX [имя_индекса] ON [имя_таблицы] USING GIST ( [столбец_геометрии] );
  4. Если вы собираетесь запрашивать свои слои с помощью Mapserver, вам понадобится "индекс oid".

    При запросах Mapserver требует уникальные идентификаторы для каждого пространственного объекта и модуль Mapserver PostGIS использует значения oid PostgreSQL в качестве таких идентификаторов. Побочным эффектом этого является то, что для быстрого доступа к произвольной записи в запросе требуется индекс по oid.

    Для создания "индекса oid" используйте следующий запрос SQL:

    CREATE INDEX [имя_индекса] ON [имя_таблицы] ( oid );

4.7.2. Часто задаваемые вопросы

4.7.2.1. Когда я использую EXPRESSION в своем map-файле, условие никогда не возвращает истину, даже когда я знаю, что в моей таблице существует нужное значение.
4.7.2.2. FILTER, который я использую для моих шейп-файлов, не работает для моей таблицы PostGIS с теми же самыми данными.
4.7.2.3. Мой слой PostGIS выдается медленнее, чем мой слой из шейп-файла, это нормально?
4.7.2.4. Мой слой PostGIS выдается хорошо, но запросы реально тормозят. Что неправильно?
4.7.2.1.

Когда я использую EXPRESSION в своем map-файле, условие никогда не возвращает истину, даже когда я знаю, что в моей таблице существует нужное значение.

В отличие от шейп-файлов, имена полей PostGIS, встречающиеся в EXPRESSIONS, должны быть написаны в нижнем регистре.

EXPRESSION ([numlanes] >= 6)
4.7.2.2.

FILTER, который я использую для моих шейп-файлов, не работает для моей таблицы PostGIS с теми же самыми данными.

В отличие от шейп-файлов, фильтры для слоев PostGIS используют синтаксис SQL (они присоединяются к предложению SQL, которое создает коннектор PostGIS для рисования слоев в Mapserver).

FILTER "type = 'highway' and numlanes >= 4"
4.7.2.3.

Мой слой PostGIS выдается медленнее, чем мой слой из шейп-файла, это нормально?

Как правило, ожидание слоев PostGIS на 10% дольше, чем эквивалентных слоев шейп-файлов, из-за дополнительных накладных расходов: соединение с базой данных, преобразование данных и передача данных между базой и Mapserver.

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

postgis# CREATE INDEX geotable_gix ON geotable USING GIST ( geocolumn );
postgis# SELECT update_geometry_stats(); -- For PGSQL < 8.0
postgis# VACUUM ANALYZE; -- For PGSQL >= 8.0
4.7.2.4.

Мой слой PostGIS выдается хорошо, но запросы реально тормозят. Что неправильно?

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

С помощью пункта USING UNIQUE в своей строке DATA вы можете указать mapserver-у какой уникальный ключ использовать:

DATA "the_geom FROM geotable USING UNIQUE gid"

Если ваша таблица не имеет определенного уникального столбца, PostgreSQL позволяет вам "подделать" уникальный столбец с помощью "oid" в качестве такого столбца. "oid" является уникальным столбцом по умолчанию на случай, если вы таковой не декларировали. Вы сможете увеличить скорость выполнения запросов, создав индекс на значении oid вашей пространственной таблицы.

postgis# CREATE INDEX geotable_oid_idx ON geotable (oid);

4.7.3. Продвинутое использование

Функция USING предложений псевдо-SQL используется для того, чтобы предоставить MapServer некоторую информацию, которая поможет ему понять результаты более сложных запросов. Более конкретно: если вид или вложенный SELECT используются в качестве исходной таблицы (справа от "FROM" в определении DATA), то mapserver затруднительно автоматически определить уникальный идентификатор для каждой строки и SRID для таблицы. Функция USING может предоставить эту информацию MapServer следующим образом:

DATA "the_geom FROM (
    SELECT
        table1.the_geom AS the_geom,
        table1.oid AS oid,
        table2.data AS data
    FROM table1
    LEFT JOIN table2
    ON table1.id = table2.id
	) AS new_table USING UNIQUE oid USING SRID=-1"
USING UNIQUE <уникальный_id>

Mapserver требует уникального идентификатора для каждой строки, чтобы определить строку при создании карты запроса. Он, как правило, использует oid в качастве уникального идентификатора, но вилы и вложенные SELECT не имеют автоматически создаваемого столбца oid. Если нужно использовать функциональность запросов Mapserver, вам следует добавлять уникальные столбцы в свои виды и вложенные SELECT, и объявлять их в USING UNIQUE. Для этого вы можете, например, выбрать oid одной из таблиц, или любой другой столбец, который будет гарантированно уникальным в результирующем множестве.

Когда вы создаете карту запросов, предложение USING может быть полезным также и для простых предложений DATA. Ранее было рекомендовано создавать в используемых таблицах индекс по столбцу oid для ускорения выполнения карты запросов. Но с помощью пункта USING можно указать Mapserver-у использовать первичный ключ вашей таблицы в качестве идентификатора для карты запросов, и тогда отпадает необходимость создавать дополнительный индекс.

Замечание

"Запрос карты" ("Querying a Map") - действие, возникающее при щелчке на карту для запроса информации о данном месте. Не следует путать его с "картой запроса" для SQL-запроса в определении DATA.

USING SRID=<srid>

Чтобы вернуть Mapserver правильные данные, PostGIS должен знать, какая пространственная ссылочная система исопльзуется в геометриях. Обычно, эту информацию можно найти в базе данных PostGIS в таблице "geometry_columns", однако, это невозможно для таблиц, создающихся "на лету" вложенными SELECT и видами. Поэтому лучше использовать опцию USING SRID=, которая позволяет указывать корректный SRID в определении DATA.

Предупреждение

Парсер Mapserver для слоев PostGIS довольно примитивен и в некоторых местах является чувствительным к регистру. Проследите, чтобы все ключевые слова SQL и все ваши пункты USING были в верхнем регистре, а также, чтобы пункт USING UNIQUE предшествовал пункту USING SRID.

4.7.4. Примеры

Давайте начнем с простого примера работы с описанными выше таблицами. Рассмотрим следующее определение слоя Mapserver:

LAYER
    CONNECTIONTYPE postgis
    NAME "roads"
    CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
    DATA "the_geom FROM roads"
    STATUS ON
    TYPE LINE
    CLASS
       COLOR 0 0 0
    END
END

Этот слой отобразит все геометрии улиц из таблицы улиц как черные линии.

Теперь, при приближении к масштабу 1:100000, будем показывать только шоссе. Следующие два слоя позволят добиться этого эффекта:

LAYER
    CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
    DATA "the_geom FROM roads"
    MINSCALE 100000
    STATUS ON
    TYPE LINE
    FILTER "road_type = 'highway'"
    CLASS
        COLOR 0 0 0
    END
END
LAYER
    CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
    DATA "the_geom FROM roads"
    MAXSCALE 100000
    STATUS ON
    TYPE LINE
    CLASSITEM road_type
    CLASS
        EXPRESSION "highway"
        SIZE 2
        COLOR 255 0 0
    END
    CLASS
        COLOR 0 0 0
    END
END

Первый слой используется, когда запрашиваемый масштаб больше, чем 1:100000, и отображает только дороги типа "шоссе", как черные линии. Опция FILTER отфильтровывает для показа только дороги типа "шоссе" ("highway").

Второй слой используется, когда масштаб меньше 1:100000, и отобразит шоссе как две красные линии, а другие дороги, - как сплошные черные линии.

Итак, мы получили интересный результат, используя только функции MapServer, с довольно простым предложением DATA. Теперь предположим, что названия улиц по какой-то причине хранятся в другой таблице, и нам нужно присоединить ее, чтобы пометить улицы.

LAYER
    CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
    DATA "the_geom FROM (SELECT roads.oid AS oid, roads.the_geom AS the_geom,
        road_names.name as name FROM roads LEFT JOIN road_names ON
        roads.road_name_id = road_names.road_name_id)
        AS named_roads USING UNIQUE oid USING SRID=-1"
    MAXSCALE 20000
    STATUS ON
    TYPE ANNOTATION
    LABELITEM name
    CLASS
        LABEL
          ANGLE auto
          SIZE 8
          COLOR 0 192 0
          TYPE truetype
          FONT arial
        END
    END
END

Этот слой примечаний добавляет зеленые подписи на все улицы в масштабе 1:20000 или меньше. Также здесь демонстрируется использование SQL вместе с определением DATA.

<<< предыдущая глава | оглавление | следующая глава >>>

Обсудить в форуме Комментариев — 21

Последнее обновление: December 01 2008