MapServer: присоединение CSV-таблицы

Решенные задачи, первая запись - описание решения.
Ответить
Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

MapServer: присоединение CSV-таблицы

Сообщение Denis Rykov » 30 ноя 2011, 10:32

Хочу присоединить к слою, созданному на базе shape-файлов атрибутику из внешней csv-таблицы, с использованием JOIN:

Код: Выделить всё

JOIN
    CONNECTIONTYPE csv
    NAME "Lookup"
    TABLE "landmap2.csv"
    FROM "No1"
    TO "1"
    TYPE ONE-TO-ONE
END
Пример CSV-файла:

Код: Выделить всё

ID,NameNN
1,"1. Категория 1 ..."
2,"2. Категория 2..."
3,"3. Категория 3..."
Проверяю при помощи запроса GetFeatureInfo - присоединенные поля не приходят, пытался указать несуществующее имя csv-файла - никаких сообщений об ошибках, может я что-то не так делаю? Кто-нибудь решал подобную задачу?
Spatial is now, more than ever, just another column- The Geometry Column.

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: MapServer: присоединение CSV-таблицы

Сообщение Denis Rykov » 30 ноя 2011, 17:48

Разобрался, рассказываю.

Как удалось выяснить, данные из присоединенной таблицы нельзя передавать на клиента в формате application/vnd.ogc.gml, а можно только в text/html (в text/plain тоже нельзя), что это за форматы подробно рассмотрено тут. То есть map-файл обязательно должен содержать следующую инструкцию:

Код: Выделить всё

MAP   
   ...
   WEB
      ...
      METADATA     
         ...
         wms_feature_info_mime_type "text/html"
         ...
      END
      ...   
   END
   ...
END
В документации приведён пример подключения CSV к shp - он не работоспособный. Во-первых, в нём пропущена строка CONNECTIONTYPE csv, а во-вторых ссылка на поле csv-файла указывается не по имени, а по индексу, например, TO '1'.

Существует 2 принципиально различных режима JOIN: ONE-TO-ONE (по умолчанию) и ONE-TO-MANY. Первый используется когда ключевому полю в исходном файле соответствует одна запись в присоединённом, второй - когда ключевому полю в исходном файле соответствует несколько записей в присоединённом. Каждый из этих режимов предполагает различную конфигурацию map-файа.

ONE-TO-ONE

Пример JOIN-секции:

Код: Выделить всё

JOIN
    CONNECTIONTYPE csv
    NAME "lookup"
    TABLE 'landmap2.csv'
    FROM 'Code'
    TO '1'
    TYPE ONE-TO-ONE
END
Пример csv-файла:

Код: Выделить всё

ID,NameNN
1,1. Выпуклые водоразделы
2,2. Плоские и слабовыпуклые водоразделы
3,3. Плоские водоразделы
В JOIN-секции мы описываем поиск значения поля Code исходного shape-файла в первой колоне CSV-файла (CSV-драйвер не понимает имён полей, адресация выполняется по номеру).

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

Код: Выделить всё

<!-- MapServer Template -->
[lookup_2],[Cоde]
lookup_2 - это второе поле присоединённого csv-файла, описанного в JOIN-секции lookup (NAME "lookup"), то есть имя этого поля составляется из имени JOIN-секции, нижнего подчеркивания и номера поля присоединенного csv-файла.

Code - имя одного из полей исходного shape-файла.

Имя шаблона указывается внутри объекта LAYER:

Код: Выделить всё

MAP
   ...
       LAYER
          ...
          TEMPLATE layertemplate.html
          ...
       END
   ...   
END
ONE-TO-MANY
Пример JOIN-секции:

Код: Выделить всё

JOIN
    CONNECTIONTYPE csv
    TEMPLATE jointemplate.html
    NAME "lookup"
    TABLE 'landmap2.csv'
    FROM 'Code'
    TO '1'
    TYPE ONE-TO-MANY
END
Всё то же самое, только возникает необходимости обязательного указания TEMPLATE еще и внутри самой секции JOIN. TEMPLATE внутри LAYER видоизменяется на:

Код: Выделить всё

<!-- MapServer Template -->
[join_lookup]
То есть этой конструкцией как-бы говорится, что данный шаблон не надо использовать, а нужно использовать тот, что находится внутри секции JOIN с именем NAME "lookup".

Пример содержимого TEMPLATE в JOIN (в нашем примере - jointemplate.html):

Код: Выделить всё

<!-- MapServer Template -->
[lookup_2],[Code]
То есть фактически шаблон, указываемый при ONE-TO-ONE на уровне LAYER теперь переехал в JOIN.

Вот и всё. Если кто захочет воспользоваться данным подходом - предупреждаю, как экранировать запятые внутри csv пока не ясно, в документации ничего подобного я не нашёл, можно конечно исходники глянуть, но это уже вопрос к тем, кто разбирается в C.

Без этого поста было бы сложно разобраться.
Spatial is now, more than ever, just another column- The Geometry Column.

ericsson
Гуру
Сообщения: 3321
Зарегистрирован: 27 июл 2009, 19:26
Репутация: 748
Ваше звание: Вредитель полей

Re: MapServer: присоединение CSV-таблицы

Сообщение ericsson » 30 ноя 2011, 18:52

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

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: MapServer: присоединение CSV-таблицы

Сообщение Denis Rykov » 30 ноя 2011, 19:23

Пробовал, не помогает, более того - кавычка попадает в значение поля.
Spatial is now, more than ever, just another column- The Geometry Column.

Tokha
Интересующийся
Сообщения: 38
Зарегистрирован: 08 апр 2011, 09:53
Репутация: 2

MS JOIN, MSSQL, EXPRESSION

Сообщение Tokha » 31 янв 2012, 14:12

Увидел JOIN в настройках mapserver, обрадовался, но рано :)

Мне нужно к слою MapInfo присоеденить вьюшку MSSQL и на основании этого подкрашивать определенным цветом полигон. Наткнулся на две проблемы:

1. JOIN и MSSQL не работают вместе. Ошибка: "getSymbol(): Symbol definition error. Parsing error near (PLUGIN)". Это, в общем-то ожидаемо, но обидно как-то.

2. Полученные поля из JOIN не получилось использовать в EXPRESSION. Ошибка: "msOGRLayerInitItemInfo(): OGR error. Invalid Fiels name: lookup_2"

Если у кого есть мысли, как решить такую задачу (хочется, чтобы она решалась на стороне сервера), прошу помочь, а я пока пойду каким-нибудь другим способом сделаю.
Вкратце, смысл такой: есть слой MapInfo с домами, который содержит информацию id дома и координаты полигона этого дома. Есть таблица в MSSQL, в которой лежат id нужных нам домов. Вот эти дома и нужно подсветить.

PS Данный рецепт с "CSV" и "text/html" попробовал, работает идеально, только это мне не нужно :)

Ответить

Вернуться в «Рецепты»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей