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.
- Скомпилируйте и установите Mapserver с любыми нужными вам опциями включив
опцию конфигурации "--with-postgis".
- В 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".
- Постройте пространственные (GiST) индексы на тех данных, с помощью которых
будете рисовать какие-либо слои.
CREATE INDEX [имя_индекса] ON [имя_таблицы] USING GIST ( [столбец_геометрии] ); |
- Если вы собираетесь запрашивать свои слои с помощью 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
ENDl
END
END |
Этот слой примечаний добавляет зеленые подписи на все улицы в масштабе 1:20000
или меньше. Также здесь демонстрируется использование SQL вместе с определением
DATA.
Последнее обновление: August 14 2008 (Наверх)
|