Сохранить тип геометрии postgis из geojson - PullRequest
1 голос
/ 21 июня 2019

У меня есть карта Lealfet в представлении Laravel Blade, где пользователь может рисовать фигуры и маркеры. Эти функции зарегистрированы в GeoJson объекте, который я преобразую в строку и вставляю в скрытый textarea с именем "geojson", чтобы отправить его на сервер в форме.

Проблема в том, что я хочу сохранить эти данные как geometry тип в моей базе данных PostgreSQL, используя функцию PostGis ST_GeomFromGeoJSON(), но я не могу заставить ее работать.

Вот что я попробовал сейчас:

$site = new Site;
$data = $request->all();
unset($data['geojson']);

foreach($data as $key=>$d)
{
   $site->$key = $d;
}

$geojson = json_decode($request->geojson);
$site->save();

DB::update('update posha_sites set geom = ST_GeomFromGeoJSON(?)
      WHERE num_site = ?
      AND city_id = ?',
   [$geojson, $request->num_site, $city_id->id]
);

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

Когда я делаю это, я получаю эту ошибку:

Объект класса stdClass не может быть преобразован в строку


EDIT

Вот полная миграция для таблицы posha_sites:

public function up()
{
    Schema::create('posha_sites', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->bigInteger('num_site');
        $table->string('type', 50)->nullable();
        $table->mediumText('adresse')->nullable();
        $table->string('cartes_anciennes')->nullable();
        $table->string('carte_topo')->nullable();
        $table->mediumText('cadastre_remembre')->nullable();
        $table->mediumText('cadastre_moderne')->nullable();
        $table->mediumText('cadastre_ancien')->nullable();
        $table->string('lieu_dit')->nullable();
        $table->mediumText('nature_parcelles')->nullable();
        $table->mediumText('conditions_acces')->nullable();
        $table->string('situation_administrative')->nullable();
        $table->string('altitude')->nullable();
        $table->string('relief')->nullable();
        $table->mediumText('hydrographie')->nullable();
        $table->string('geologie')->nullable();
        $table->string('vestiges_periode')->nullable();
        $table->mediumText('vestiges_nature')->nullable();
        $table->mediumText('vestiges_conservation')->nullable();
        $table->longText('plans_documents_figures')->nullable();
        $table->longText('sources_manuscrites')->nullable();
        $table->longText('sources_imprimees')->nullable();
        $table->longText('renseignement_oral')->nullable();
        $table->longText('bibliographie')->nullable();
        $table->longText('histoire')->nullable();
        $table->longText('historiographie')->nullable();
        $table->longText('description_histoire_monumentale')->nullable();
        $table->geometrycollection('geom')->nullable();
        $table->string('last_author')->nullable();
        $table->integer('tree_id')->unsigned()->nullable();
        $table->integer('parent_id')->unsigned()->nullable();
        $table->integer('city_id')->unsigned();
        $table->timestamps();
    });
}

Функция ST_GeomFromGeoJSON() фактически ожидает строку, поэтому я не декодировал свою $geojson переменную:

$geojson = $request->geojson;

вместо:

$geojson = json_decode($request->geojson);

Но я все еще получаю ошибку:

SQLSTATE [XX000]: внутренняя ошибка:

7 ОШИБКА: недопустимое представление GeoJson (SQL: обновить posha_sites set geom = ST_GeomFromGeoJSON ({"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {}, " геометрия ": {" тип ":" точка "," координаты ": [- 0.229114,44.564488]}}]}) ГДЕ num_site = 248 И city_id = 5)

Все же я проверил свой геойсон в онлайн-валидаторе геоджонса, и он кажется правильным.

1 Ответ

1 голос
/ 22 июня 2019

Предполагая, что у вас есть по крайней мере PostgreSQL версии 9.3, вы можете использовать несколько функций и операторов JSON для извлечения соответствующих частей спецификации GeoJSON, требуемой ST_GeomFromGeoJSON для создания геометрий.

Попробуйте следующее, где вы можете заменить JSON в верхней части:

WITH data AS (SELECT '{ "type": "FeatureCollection",
    "features": [
      { "type": "Feature",
        "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
        "properties": {"prop0": "value0"}
        },
      { "type": "Feature",
        "geometry": {
          "type": "LineString",
          "coordinates": [
            [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
            ]
          },
        "properties": {
          "prop0": "value0",
          "prop1": 0.0
          }
        },
      { "type": "Feature",
         "geometry": {
           "type": "Polygon",
           "coordinates": [
             [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
               [100.0, 1.0], [100.0, 0.0] ]
             ]
         },
         "properties": {
           "prop0": "value0",
           "prop1": {"this": "that"}
           }
         }
       ]
     }'::json AS fc)

SELECT
  row_number() OVER () AS gid,
  ST_AsText(ST_GeomFromGeoJSON(feat->>'geometry')) AS geom,
  feat->'properties' AS properties
FROM (
  SELECT json_array_elements(fc->'features') AS feat
  FROM data
) AS f;

Находит три геометрии. Столбец geom содержит объект геометрии, а gid - номер объекта. Функция ST_AsText показывает WKT-эквивалент каждой геометрии. Я также включил свойства или атрибуты, которые можно определить для каждой геометрии, как показано в спецификации.

 gid |                   geom                   |              properties
-----+------------------------------------------+--------------------------------------
   1 | POINT(102 0.5)                           | {"prop0": "value0"}
   2 | LINESTRING(102 0,103 1,104 0,105 1)      | {                                   +
     |                                          |           "prop0": "value0",        +
     |                                          |           "prop1": 0.0              +
     |                                          |           }
   3 | POLYGON((100 0,101 0,101 1,100 1,100 0)) | {                                   +
     |                                          |            "prop0": "value0",       +
     |                                          |            "prop1": {"this": "that"}+
     |                                          |            }
(3 rows)

Вы должны назначить SRID для геометрии, используя ST_SetSRID.

Или, если вам просто нужна одна гетерогенная ГЕОМЕТРИЧЕСКАЯ КОЛЛЕКЦИЯ, вы можете сделать ее такой компактной:

SELECT ST_AsText(ST_Collect(ST_GeomFromGeoJSON(feat->>'geometry')))
FROM (
  SELECT json_array_elements('{ ... put JSON here ... }'::json->'features') AS feat
) AS f;

GEOMETRYCOLLECTION(POINT(2565453.18267219 -3835048.65976031),LINESTRING(2727584.72197102 -3713449.19424187,2732476.69178127 -3992291.47342619),POLYGON((2442627.90254053 -3705499.95430853,2425506.00820465 -3886502.83728783,2555143.20817631 -3910962.68633909,2442627.90254053 -3705499.95430853)))

См. Также Создание коллекций объектов GeoJSON с помощью функций JSON и PostGIS из журнала Postgres OnLine , который делает обратное.

...