地理空間情報Webアプリの開発(3)

この記事は1年以上前に書かれました。
内容が古くなっている可能性がありますのでご注意下さい。


地理空間情報を活用したモバイルWebアプリケーションのサーバー環境として、Node.jsとPostGISのインストールができましたので、今回はサーバー側のプログラムを開発します。

前回、PostGISに投入した応急給水拠点のデータをJSONで返す、簡単なNode.jsプログラムを作成します。

はじめに、Node.jsでPostGIS(PostgreSQL)にアクセスするために使用するnode-postgresをインストールします。

# yum install postgresql93-devel

でPostgreSQLのヘッダファイルやpg_configをインストールしてから、

# npm install pg

でnode-postgresをインストールします。

サーバープログラム(water.js)の完全なリストは以下の通りです。

var http = require('http');
var url = require('url');
var pg = require('pg');

var connStr = 'tcp://username:password@localhost:5432/postgis';
pg.connect(connStr, function(error, client) {
  if(error) {
    console.log('Database Connection Error');
  } else {
    var server = http.createServer(function(req, res){
      var urlParam = url.parse(req.url, true).query;
      var queryStr = 'SELECT name, type, longitude, latitude ' +
        'FROM watersupplysites ' +
        'WHERE ST_DWithin(geog, ST_Point(' + urlParam.lon + ',' + 
        urlParam.lat + '), ' +
        urlParam.dist + ')';
      client.query(queryStr, function(error, result) {
        if(error) {
          res.writeHead(503, {'Content-Type': 'text/plain'});
          res.write('Service Temporarily Unavailable\n');
          res.end();
        } else {
          var jsonObjs = [];
          res.writeHead(200, {'Content-Type': 'application/json'});
          for(i=0 ; i<result.rows.length ; i++) {
            var obj = { name : result.rows[i].name, 
                        type : result.rows[i].type,
                        longitude : result.rows[i].longitude,
                        latitude : result.rows[i].latitude };
            jsonObjs.push(obj);
          }
          res.write(JSON.stringify(jsonObjs));
          res.end();
        }
      });
    }).listen(8080);
  }
});

まず、3つのモジュールをロードします。

var http = require('http');
var url = require('url');
var pg = require('pg');

httpモジュールはHTTPサーバの機能を実現します。urlモジュールはリクエストパラメータの取得に、pgモジュールはPostGIS(PostgreSQL)へのアクセスに使用します。

pg.connect()でPostGISサーバに接続します。接続文字列は、

tcp://ユーザ名:パスワード@サーバ名:ポート番号/データベース名

という形式です。
PostGISとの接続に失敗したらログを出力して終了します。
PostGISと接続できたら、http.createServer()でHTTPサーバを作成します。HTTPリクエストを受けると、url.parse()でHTTPリクエストパラメータを分解してurlParamに格納し、urlParam.lon、urlParam.lat、urlParam.distを用いてSQL文を組み立てます。
SQL文では、前回使用したPostGISの空間関係関数ST_DWithin()を使用しています。
query()メソッドでクエリを発行し、失敗した場合はステータスコード503を返し、成功した場合は、クエリ結果からオブジェクトの配列を作成し、JSON.stringify()でJSON形式に変換してからwrite()メソッドでレスポンスを返します。

# pm2 start water.js

でサーバープログラムを起動し、D3.jsを用いた簡単なテストプログラム

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>test client</title>
  <script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
  <p></p>
  <script type="text/javascript">
    var server = 'http://■■■■■.cloudapp.net/api';
    var query = server +
      '?lon=139.5377387&lat=35.51274191&dist=1000';
    d3.json(query, function (error, json) {
      d3.select("p")
        .selectAll("ul")
        .data(json)
        .enter()
        .append("li")
        .text(function(d) {
          return d["name"] + '(' + d["type"] + ')';
      });
    });
  </script>
</body>
</html>

を使用して動作確認します。以下のように表示されればOKです。

地理空間情報Webアプリの開発 1234