日本語
PostgreSQL / PostGIS で使う
エンティティのモデルのページには、ダウンロードの行に PostgreSQL / PostGIS のテーブルがあります。モデルの決まりを制約にした CREATE TABLE です。空間インデックスと、各属性の IRI を書いたコメントも付いています。このページでは、指定緊急避難場所(EvacuationSite)のテーブルを PostGIS に作り、避難場所を 1 か所入れて、駅の近くの避難場所を検索します。
Docker が必要です。PostGIS を入れた自分の PostgreSQL でも、同じ手順で使えます。
1. PostGIS を起動する
bash
docker run -d --name datamodels-postgis -e POSTGRES_HOST_AUTH_METHOD=trust \
postgis/postgis:16-3.4
# データベースの準備ができるまで待つ(初回は 10 秒ほど、長くても 2 分)。
for i in $(seq 120); do
docker logs datamodels-postgis 2>&1 | grep -q "init process complete" &&
docker exec datamodels-postgis pg_isready -U postgres -q && break
sleep 1
done
# 「accepting connections」なら準備完了。そうでなければ、ログに原因が出る。
docker exec datamodels-postgis pg_isready -U postgres || docker logs datamodels-postgisPOSTGRES_HOST_AUTH_METHOD=trust では、パスワードなしで誰でも接続できます。自分のコンピューターでの試験だけに使ってください。
2. テーブルを作る
bash
BASE=https://datamodels.jp/adapters
curl -sSfO "$BASE/postgis/disaster/EvacuationSite.sql"
docker exec -i datamodels-postgis psql -U postgres < EvacuationSite.sqltext
CREATE FUNCTION
CREATE TABLE
CREATE INDEX
COMMENT
COMMENT
…列の名前は、属性名をスネークケースにしたものです。たとえば hazardTypes は hazard_types になります。値の中の項目は、それぞれ 1 つの列になります(address.addressText は address_address_text)。複数の値は配列で、位置は geometry(Point, 4326) です。
3. 避難場所を入れる
docker exec -it datamodels-postgis psql -U postgres で SQL のプロンプトを開き、次を実行します。
sql
INSERT INTO evacuation_site (id, name, external_site_id,
local_government_code, address_address_text, location,
hazard_types, also_designated_shelter)
VALUES ('urn:ngsi-ld:EvacuationSite:0012', '都立一橋高校', '13101-0012',
'131016', '東京都千代田区東神田1-12-13',
ST_SetSRID(ST_MakePoint(139.7810002, 35.6945488), 4326),
ARRAY['stormSurge', 'earthquake', 'inlandFlood'], true);text
INSERT 0 1モデルの決まりに合わない値は、テーブルが受け付けません。使える値、6 桁の全国地方公共団体コードのようなパターン、最小値、複数の列にまたがる決まり(「externalSiteId か nationalShelterId」)を確かめます。たとえば、fire はこのモデルの災害の種別にありません。
sql
UPDATE evacuation_site SET hazard_types = ARRAY['fire']
WHERE id = 'urn:ngsi-ld:EvacuationSite:0012';text
ERROR: new row for relation "evacuation_site" violates check constraint "evacuation_site_hazard_types_check"
DETAIL: Failing row contains (urn:ngsi-ld:EvacuationSite:0012, 都立一橋高校, null, …).4. 距離で検索する
秋葉原駅から 1 km 以内の避難場所を、距離(メートル)と一緒に取り出します。
sql
WITH station AS (
SELECT ST_SetSRID(ST_MakePoint(139.7731, 35.6984), 4326)::geography AS p
)
SELECT name, round(ST_Distance(location::geography, p)) AS metres
FROM evacuation_site, station
WHERE ST_DWithin(location::geography, p, 1000);text
name | metres
--------------+--------
都立一橋高校 | 833
(1 row)この検索は、地球上の距離(geography)をメートルで測ります。ファイルの空間インデックスは geometry に付いています。大きなテーブルでは、この検索が使うインデックスを足してください。CREATE INDEX ON evacuation_site USING gist ((location::geography)); です。
コメントの IRI
各列のコメントには、日本語と英語の説明があります。最後の行には、属性の IRI を山かっこで囲んで書いています。データベースのツールで見られるほか、SQL でも読み出せます。
sql
SELECT attname AS "column",
substring(col_description(attrelid, attnum) from '<([^>]+)>$') AS iri
FROM pg_attribute
WHERE attrelid = 'evacuation_site'::regclass
AND attname IN ('name', 'address_postal_code', 'hazard_types');text
column | iri
---------------------+-----------------------------------------------
name | https://uri.etsi.org/ngsi-ld/name
address_postal_code | https://schema.org/postalCode
hazard_types | https://datamodels.jp/ns/disaster/hazardTypes
(3 rows)IRI はモデルの @context と同じです。そのため、テーブルの行と NGSI-LD のエンティティは、同じ意味のデータとして扱えます。終わったら、docker rm -f datamodels-postgis でコンテナーを削除します。
自分のモデル
自分のサイトのモデルでも、datamodels export で同じファイルを作れます(他のツールに書き出す)。