Wikipedia データをデータベースに格納する


リレーショナルデータベース管理システム（RDBMS）であるほとんどの有名なプロジェクトが JSON 型をサポートするようになりました．
各種データモデルの専門とする NoSQL の普及により，RDBMS も様々な要求に合わせて，表の一つのセルには一つの値ではなく，一つのオブジェクトを格納可能なように対応しつつあります．

本記事では，Wikipedia の記事をデータベースに JSON 形式で格納する方法についてご紹介します．本記事では，Wikipedia データを JSON に変換し，格納するまでを詳細に説明しますが，簡単に試してみたいという方は [こちらの記事](https://qiita.com/ryotayamanaka/items/02a2efdcb74cac280b3e) をご参照ください！

## 準備

日本語 Wikipedia のダンプデータを利用して JSON データをデータベースｎ格納する方法について説明します．

### 実行環境

以下のツールを利用します．Docker Compose で構成しているので再現はしやすいと思います．

- Docker環境
- Git
- Oracle Database 21c 以上（自前で準備）

RDBMS の準備は自前でインスタンスを立てるように構成しており，本記事では Oracle Database 23ai のインスタンスを用意しました．
Docker を利用して無償で Oracle Database 23ai を立ち上げる方法は [こちらの記事](https://qiita.com/ryotayamanaka/items/156932a48e65d3ddc5ac) にまとめてありますのでご利用ください．
無償ライセンスの場合，リソース制限があるのでダンプデータの全ての記事を格納することは不可能ですので，以下の対処が必要です．

- Oracle Database 23ai の有償ライセンスに変更する
- Wikipedia ダンプデータからロードする記事数を制限する（後述します）

### プログラム・データの準備

Wikipedia のダンプデータは XML 形式データですので，文書 ID やテキスト部分の抽出をして JSON 形式の変換を行う必要があります．後述する GitHub リポジトリ [json-db-importer](#json-db-importer) で任意のダンプデータを JSON 形式への変換や Oracle Database への格納などの処理を行います．

#### Wikipedia Dump (jawiki)

Wikipedia のダンプデータは各言語でダンプデータのリンクページが用意されています．日本語 Wikipedia ダンプのデータは下記のリンクから取得できます．

https://dumps.wikimedia.org/jawiki/

本記事では [2024年5月1日時点のダンプデータ](https://dumps.wikimedia.org/jawiki/20240501/jawiki-20240501-pages-articles-multistream.xml.bz2) を利用しましたが，新しい版があればそちらをダウンロードしても構いません．

#### json-db-importer

Wikipedia のダンプデータを JSON 形式へ変換・JSON データを Oracle Database へ格納の処理を実行するプログラムを準備しました．

https://github.com/meer-consulting/json-db-importer/tree/task-single-insert

次のコマンドでクローンできます．

```bash:shell
git clone --branch task-single-insert --single-branch git@github.com:meer-consulting/json-db-importer.git
```

ダウンロードしておいた Wikipedia ダンプデータは `json-db-importer/data/` 直下に配置します．

細かい説明は後のセクションに回して，実行方法について説明します．

## 実行方法

データおよびプログラムの準備が完了すれば，docker コマンドで `json-db-importer` で用意している機能を実行していきます．

### 1. Wikipedia ダンプデータから JSON データを作成

Wikipedia ダンプデータを WikiExtractor を利用して JSON データに変換する作業を行います．

`docker-compose.yml` が置いてある `json-db-importer/docker/development` に移動します．

```bash:shell
cd docker/development/
```

移動した場所で，以下の内容を記述した `.env` ファイルを作成します．
※同じディレクトリに .env.example があるので利用してください．

```conf:json-db-importer/docker/development/.env
DUMP_FILENAME=jawiki-20240501-pages-articles-multistream.xml.bz2
```

WikiExtractor のコマンドで環境変数 `DUMP_FILENAME` を参照しますので，別版のダンプデータを利用時は `DUMP_FILENAME` に設定するファイル名を適宜変更してください．

次のコマンドで `wikiextractor` サービスを起動します．

```bash:shell at json-db-importer/docker/development/
docker compose --profile generate-json up
```

`json-db-importer/wikiextractor` ディレクトリが作成され，複数のディレクトリに仕分けされて JSON データが大量に書き出されます．

```json:JSON出力構造
[
  {
    "id":    string,
    "revid": string,
    "url":   string,
    "title": string,
    "text":  string
  }
]
```

2024年5月1日のダンプデータには 2,289,281 記事のアーカイブがありました．

### 2. データベース接続情報の設定

Oracle Database 23ai インスタンスへプログラムから接続するためデータベース接続情報を `.env` に追記します．

```conf:json-db-importer/docker/development/.env
DUMP_FILENAME=jawiki-20240501-pages-articles-multistream.xml.bz2

# 以下追記

ORACLE_USER=<User name>
ORACLE_PASSWORD=<Password>
ORACLE_DSN=<IP addr of Oracle DB instance>:<port>/<SID>
ORACLE_MODE=THICK

MAX_JSON_LOAD=3000000 # 読み込み上限
TABLE_NAME=wiki
TASK_RATIO_1_WIKI_IMPORT=1
```

データベース接続情報以外の各種変数の意味については次の通りです．

- `MAX_JSON_LOAD`：データ件数を制限できます．簡単に試したい場合は小さい値を設定します．
- `TABLE_NAME`：Oracle Database に作成されるテーブル名です．
- `TASK_RATIO_1_WIKI_IMPORT`：Locust のタスク設定用です．

### 3. Wikipedia データのロード

JSON データの準備とデータベース接続情報の設定が完了すればデータをロードする準備ができましたので，作成した JSON データを Oracle Database に格納します．

ベンチマークツールの Locust を利用して Python で Oracle Database に Wikipedia データを格納するプログラムを作成しました．次のコマンドで Locust 用のコンテナを立ち上げます．

```bash:shell at json-db-importer/docker/development/
docker compose --profile locust up
```

データベース接続情報が適切に設定できていると Locust サーバが立ち上がりますのでお好みの Web ブラウザで [http://127.0.0.1:8089/]() にアクセスしてみます．Locust のトップ画面の設定はユーザ数を 1，同時アクセスの最大数を 1 と設定して，Startボタンを押して実行開始します．

## `json-db-importer` に関する説明

`json-db-importer` の中で記述した `docker-compose.yml` の構成や，JSON データを格納するにあたり便利なライブラリの記述について説明する．

### Wikipedia ダンプデータを JSON 形式に変換

Wikipedia ダンプデータを JSON 形式に変換する処理は `wikiextractor` サービスで実行します． この処理は [WikiExtractor](https://github.com/attardi/wikiextractor) を利用しており，このツールのオプションで `--json` を指定することで JSON 形式でファイル出力されます．

サービス起動時に `wikiextractor --json --processes 60 --output /wikiextractor/ /data/${DUMP_FILENAME:?Set .env}` が実行され，適切に処理が終了すると `json-db-importer/wikiextractor/` に変換後のデータが格納されます．

私の環境では下記のログの通り，2,289,281 件の記事を 892.8 秒（15分弱）で出力できましたが，`--processes` オプションを実行環境の計算機 CPU に合わせて大きく設定することでより速く処理することもできます．

```log:wikiextractorの実行完了メッセージ
development-wikiextractor-1     | INFO: Finished 60-process extraction of 2289281 articles in 892.8s (2564.3 art/s)
```

### JSON データをデータベースに格納

データベースに JSON データを格納する処理は `locust-master` / `locust-worker` サービスで実行します．

ベンチマークツールの Locust を利用しており，このサービスの中で python-oracledb ライブラリでデータベース操作を行っています．

https://github.com/locustio/locust

Locust については機会があれば別記事にまとめようと思いますが，負荷テストの内容を確認するには `json-db-importer/locust/locustfile.py` を参照します．

## まとめ

Wikipedia のダンプデータを利用して，JSON データを Oracle Database に格納する環境を作成しました．Locust を利用していますので，タスクをいくつか定義して性能を評価する環境としても利用できます．Wikipedia データをデータベースに格納して JSON 形式の問合せや全文検索など試したい方はぜひ利用してみてください！

JSON の格納方法や問合せ方法，性能評価の方法などについては別の記事でまとめられたらと考えております．