😀

Node.jsでPostGISから出たGeoJSONを受ける

2020/10/27に公開

はじめに

ふとNode.jsでPostGISを扱えるのかなと思いました。

方針

  • PostGISはあくまでPostgreSQLのエクステンション。まずはPostgreSQLとNode.jsがつながらなければいけない。
  • ジオメトリは放っておけばWKBHEXで出てくるけどJavaScriptで扱うならJSONにした方が良いだろう。
  • ていうかPostGISからGeoJSONを出してみよう。
  • js側ではGeoJSONをJSONとして受けよう。

Node.jsとpgのインストール

Node.jsとNPMを入れ、npm install pgでpgを入れました。

GeoJSONを吐くSQL

https://qiita.com/kshigeru/items/8940ecf7f261a6b01ed0 を参照。というか引き写しです。

SELECT row_to_json(featurecollection) FROM (
  SELECT
    'FeatureCollection' AS type,
    array_to_json(array_agg(feature)) AS features
  FROM (
    SELECT
      'Feature' AS type,
      ST_AsGeoJSON(geom)::json AS geometry,
      row_to_json((
        SELECT p FROM (
          SELECT [プロパティ1],[プロパティ2],...
        ) AS p
      )) AS properties
    FROM [テーブル]
    [(必要なら) LIMIT 5とか]
  ) AS feature
) AS featurecollection;
  • [プロパティ1],... は、プロパティで出したいカラム
  • [テーブル] は、テーブル名(geomとプロパティ1,...を持っている)
  • [(必要なら) LIMIT 5とか] の部分は、タプルに応じて非常に長い配列になるので、テストで地物数を限定する場合に追加します。
    SELECT
      'Feature' AS type,
      ST_AsGeoJSON(geom)::json AS geometry,
      row_to_json((
        SELECT p FROM (
          SELECT [プロパティ1],[プロパティ2],...
        ) AS p
      )) AS properties

では

type      | geometry | properties        |
---------+------------|------------------|
Feature | ジオメトリ | {プロパティ,...}|

というタプルができます。ジオメトリはJSON型で、GeoJSON形式の文字列型からキャストしたものです。

そして、

  SELECT
    'FeatureCollection' AS type,
    array_to_json(array_agg(feature)) AS features
  FROM (
  ...
  ) AS feature

では、服問い合わせで出てきたタプル(複数行になりうる)をarray_agg(feature) で配列にまとめて(1行になる)、array_to_json()でJSON型にしています。

JSONを受けるjs

https://symfoware.blog.fc2.com/blog-entry-2114.html を参照。これも引き写しです。

const {Client} = require('pg');

const client = new Client({
  "user": (ユーザ名),
  "host": (ホスト名),
  "port": 5432,
  "database": (データベース名),
});

client.connect();

const query = `
SELECT row_to_json(featurecollection) AS json FROM (
  SELECT
    'FeatureCollection' AS type,
    array_to_json(array_agg(feature)) AS features
  FROM (
    SELECT
      'Feature' AS type,
      ST_AsGeoJSON(geom)::json AS geometry,
      row_to_json((
        SELECT p FROM (
          SELECT [プロパティ1],[プロパティ2],...
        ) AS p
      )) AS properties
    FROM [テーブル]
    LIMIT 5
  ) AS feature
) AS featurecollection
`;

client.query(query, (err, res) => {
  if( err == null ) {
    // succeeded
    let json = res.rows[0].json;
    console.log(typeof json);
    console.log(JSON.stringify(json));
  }
  else {
    // error
    console.log(err, res);
  }
  client.end();
});

なお、console.log(res)resを見ると、次のようになりました。

Result {
  command: 'SELECT',
  rowCount: 1,
  oid: null,
  rows: [ { json: [Object] } ],
  fields: 
   [ Field {
       name: 'json',
       tableID: 0,
       columnID: 0,
       dataTypeID: 114,
       dataTypeSize: -1,
       dataTypeModifier: -1,
       format: 'text' } ],
  _parsers: [ [Function: bound parse] ],
  RowCtor: null,
  rowAsArray: false,
  _getTypeParser: [Function: bound ] }

データとしてはrowsプロパティを取り出せば、GeoJSONのデータをそのままJavaScriptで使えると思います。

本記事のライセンス

クリエイティブ・コモンズ・ライセンス
この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンス の下に提供されています。

Discussion