【问题标题】:Save postgis geometry type from geojson从 geojson 保存 postgis 几何类型
【发布时间】:2019-11-04 10:54:40
【问题描述】:

我在 Laravel Blade 视图中有一个 Lealfet 地图,用户可以在其中绘制形状和标记。这些功能在GeoJson 对象中注册,我将其字符串化并插入到名为“geojson”的隐藏textarea 中,以在表单中将其提交给服务器。

问题是我想使用 PostGis ST_GeomFromGeoJSON() 函数将此数据保存为 geometry 类型在我的 PostgreSQL 数据库中,但我无法让它工作。

这是我现在尝试的:

$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 类的对象无法转换为字符串


编辑

这是 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":{},"几何":{"type":"Point","coordinates":[-0.229114,44.564488]}}]}) WHERE num_site = 248 AND city_id = 5)

但我在在线 geojson 验证器中测试了我的 geojson,结果似乎是正确的。

【问题讨论】:

  • posha_sites 表的迁移是什么样的?
  • 我编辑了我的帖子
  • 您的迁移出错。数据类型为驼峰式。您需要“geometryCollection”而不是“geometrycollection”。 (这可能是错误的,不过最好先检查一下)。
  • 这有帮助吗? dba.stackexchange.com/a/227581

标签: php laravel laravel-5 leaflet postgis


【解决方案1】:

现代 PostgreSQL + PostGIS 接受 JSONB and its functions这项工作的最佳数据类型,因为 ST_GeomFromGeoJSON 函数(也接受 JSONB)只接受纯几何,而不接受最流行的 GeoJSON 对象, Feature or FeatureCollection

小例子:

WITH json_load AS (
 SELECT $${
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  },
  "properties": {
    "name": "Dinagat Islands"
  }
 }$$::JSONB j
)

SELECT 
   j->'type' AS type,
   ST_GeomFromGeoJSON(j->'geometry') geom,
   j->'properties' AS props
FROM json_load;

注意。在服务器端,在 json_load 部分,您可以使用pg_read_file('/tmp/myFile.geojson')::jsonb 来读取文件。之前使用chmod 666 /tmp/myFile.geojson 之类的东西。 jsonb_array_elements 函数可以分解 GeoJSON 几何集合。

(Source)

【讨论】:

    【解决方案2】:

    假设您至少有 PostgreSQL 版本 9.3,您可以使用一些 JSON 函数和运算符来提取 ST_GeomFromGeoJSON 所需的 GeoJSON 规范的相关部分以创建几何。

    尝试以下操作,您可以在其中替换顶部的 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)
    

    您应该使用 ST_SetSRID 为几何体分配一个 SRID。

    或者,如果您只需要一个异构的 GEOMETRYCOLLECTION,您可以像这样使其紧凑:

    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)))
    

    另见Creating GeoJSON Feature Collections with JSON and PostGIS functions from the Postgres OnLine Journal,它的作用正好相反。

    【讨论】:

      猜你喜欢
      • 2011-10-14
      • 2014-10-06
      • 2015-05-18
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 2023-01-20
      • 2021-06-28
      • 1970-01-01
      相关资源
      最近更新 更多