osm2pgsqlで特定のタグキーを指定してデータを効率的に取り込む(PBF)

# はじめに
今回の記事は、[QGISでPostGISでのPBFデータの読み込み方法](https://qiita.com/AshMap/items/b6f7177ea75584619f0f)[OSMデータをPostgreSQLに取り込む：hstore拡張の有無による違い](https://qiita.com/AshMap/items/602e90d429905a5689d6)の続編の位置付けです。

PBFフォーマットの概要は[PBFフォーマットの概要と他のデータ形式との比較](https://qiita.com/AshMap/items/455d2a19e09db9e46ec5)の記事をご参照ください。

これらの記事では、OpenStreetMap（OSM）のPBFデータをPostGISに取り込む方法を解説しました。しかし、大規模なデータセットでは、全てのタグを取り込むと以下のような課題が生じることがあります：
	•	処理時間が長くなる。
	•	取り込まれたデータが冗長で、QGIS等で扱いにくい。
	•	SQLクエリが重くなる。

特定のキーだけを取り込むことで、処理時間を短縮し、データの管理を効率化するのに私が活用した方法を本記事で紹介します。

# 利用するツール
- osm2pgsql（OSMデータをPostGISにインポートするツール）
- PostgreSQL + PostGIS（データベース）
- QGIS（地理データの可視化ツール）

# 課題の整理

hstoreを使った全てのキーの取り込み

osm2pgsqlの--hstoreオプションを使用すると、すべてのタグがtagsカラムに格納されます。この方法は汎用性が高い一方で、そのままでは筆者には以下の課題がありました：
- 処理時間が長い：事例:Northwest USA データで全タグを取り込む場合、処理時間は約1時間。(別記事参照)
- QGISなどのツールで扱いにくい：タグがJSON形式で格納されるため、可視化や操作が難しい。
- SQLクエリが重い

## 解決策
特定のタグキーのみを取り込むカスタムスタイルファイルを作成することで、次のような利点が得られます：
- 処理時間を大幅に短縮：例えば、Pointで1つのキーだけを取り込むと30秒程度で完了。（手元集計）
- 直接カラムとして作成され、扱いやすい：QGISでの可視化が容易。

## 手順
#### データベース準備

今回も、Geofabrikでダウンロード可能なNorth AmericaのUS Midwestのデータを活用してみます。(約2GB)

以下に、PostGIS拡張を有効にしたデータベースを作成します。(SQL)
```sql
CREATE DATABASE sample;
\c sample
CREATE EXTENSION postgis;
```

#### キーのリストアップ
>通常、取得したいキーが決まっている場合はそのキーに基づいて「カスタムファイルの作成」の項目に移ってください。

ここでは、例としての処理結果を紹介するため、サンプルデータでhstoreで全てのキーを取り込んだ状態で、どのようなタグキーが存在するかを確認してそこでピックアップしたキーを記事内で利用します。

存在するタグキーの一部(4つ)を取得
```sql
SELECT DISTINCT key
FROM (
    SELECT skeys(tags) AS key
    FROM planet_osm_point
) AS subquery
LIMIT 4;
```

結果（今回記事で使うキー）
| **Key**         |
|------------------|
| flow_control     |
| name:pcd         |
| hardware         |
| panoramax:2      |

#### カスタムファイルの作成
必要なキーのみを記述したスタイルファイル（例: custom.style）を作成します。
利用する際Tagを任意の（利用したい）タグにして作成し、custom.styleとして保存します。

本記事では、上記で取得した4つのキーのみを取り込む設定を例として示します。

```text
custom.style

# OsmType  Tag                DataType     Flags
node,way   flow_control       text
node,way   name:pcd           text
node,way   hardware           text
node,way   panoramax:2        text
```

#### カスタムスタイルファイルの構成要素
- *OsmType*:
  - `node,way` は、ノードデータとウェイデータの両方を対象にすることを指定しています。

- *Tag*:
  - 各行で特定のタグキー（例: `flow_control`）を指定します。

- *DataType*:
  - `text` を指定しています。これはタグの値が文字列型として取り込まれることを意味します。

- *Flags*:
  - ここでは特に追加の設定を行わないため、空白にしています。

#### データを取り込む(bash)

```bash
osm2pgsql -c -d sample -U $(whoami) --slim -r pbf -S custom.style us-midwest-lataset.osm.pbf
```
### 結果
取り込まれたflow_controlのデータをSQLで確認してみます。

```sql
SELECT osm_id, flow_control
FROM planet_osm_point
WHERE flow_control IS NOT NULL;
```

結果
```text
   osm_id   | flow_control 
------------+--------------
 7469061608 | moench
(1 row)
```

#### QGISで表示
下記のように指定したタグキーがAttributionとして取り込まれ表示されます。

![Screenshot 2024-12-03 at 17.00.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789281/ed23dfc4-3af0-83d2-8ce1-5dbb33a2803a.png)

## 補足
今回利用した.styleですが、通常はosm2pgsqlをインストールしたときにdefault.styleが同時に取得されています。osm2pgsqlの[リポジトリ](https://github.com/osm2pgsql-dev/osm2pgsql/tree/master)にも置かれています。カスタムスタイルを利用しなかった場合はこのdefault.styleが利用されるため、一部の標準タグが取り込まれるという仕組みになっていました。

# まとめ
カスタムスタイルファイルを使用することで、osm2pgsqlで特定のキーのみを効率的に取り込むことが可能です。この方法は次のようなユースケースで利用できるかと思います：
- 処理時間を短縮したい場合。
- 特定のデータだけを扱いたい場合。
- クエリはそれほど使わずにビジュアルツールで直接データを確認したい場合。