🐇
SurrealDBに住宅データセットを入れる

nash1111

nash1111

2023年5月16日
DBSurrealDBRustPython

# SurrealDBが便利そう

SELECTの結果からテーブル作成が可能で、かつ元のテーブルの変更があると再度計算してくれるらしい。
詳細

# この記事について

この記事では

カリフォルニアの住宅データセットであるCalifornia HousingをCSVに読み込む。
CSVをRustのライブラリを使ってSurrealDBに書き込む。
元テーブルから平均築年数を示すテーブル(average_house_age_tbl)を作る。
元テーブルから築30年未満の住宅を削除して、average_house_age_tblが更新されるかを確認する。
を実施します。

# CSVの準備

from sklearn.datasets import fetch_california_housing
import pandas as pd

def download_data():
    # データをロード
    california_housing = fetch_california_housing()

    # データフレームに変換
    california_df = pd.DataFrame(california_housing.data, columns=california_housing.feature_names)

    # 目的変数(住宅価格)を追加
    california_df['MEDV'] = california_housing.target

    california_df.columns = ['med_inc', 'house_age', 'ave_rooms', 'ave_bedrms', 'population', 'ave_occup', 'latitude', 'longitude', 'medv']

    # CSVファイルとして保存
    california_df.to_csv('california_housing.csv', index=False)

if __name__ == "__main__":
    download_data()

これでcalifornia_housing.csvに住宅データとmedvを書き込めました。
20640件ありそうです。

# SurrealDBのインストール

インストール方法

# DBの起動

ファイル形式で取っておきたいのでディスクベースで起動しました、インメモリでも起動できます。
詳細

surreal start --log trace --user surreal_user --pass surreal_pass --bind 0.0.0.0:8080 file:test.db

# Rustのライブラリ設定

cargo add surrealdb
cargo add serde --features derive
cargo add tokio --features macros,rt-multi-thread
# CSVのパース用
cargo add csv serde serde_derive

# DBへの接続とCSV書き込み

構造体を決める

#[derive(Serialize, Debug, Deserialize)]
struct HousingRecord {
    med_inc: f64,
    house_age: f64,
    ave_rooms: f64,
    ave_bedrms: f64,
    population: f64,
    ave_occup: f64,
    latitude: f64,
    longitude: f64,
    medv: f64,
}

DBへの接続

    let db = Surreal::new::<Ws>("127.0.0.1:8080").await?;
    db.signin(Root {
        username: "surrealuser",
        password: "surrealpass",
    })
    .await?;
    db.use_ns("test_ns").use_db("test_db").await?;

CSVからDBへの書き込み

    let mut rdr = csv::Reader::from_reader(io::stdin());
    for result in rdr.deserialize() {
        let record: HousingRecord = result?;
        let housing_record: Record = db.create("housing").content(&record).await?;
    }

書き込みの実行

cargo run < california_housing.csv

DBへの接続

surreal sql --conn http://localhost:8980 --user surrealuser --pass surrealpass

書き込んだ件数の確認(事前にSurrealistでログインする)

SELECT count() FROM housing GROUP ALL;
[
    {
        "count": 20640
    }
]

# DEFINE TABLEを試す

元のテーブルから平均築年数だけを算出するテーブルを書く

DEFINE TABLE average_house_age_tbl AS
    SELECT count() AS total, math::mean(house_age) as average_house_age
    FROM housing
    GROUP ALL;
SELECT * FROM average_house_age_tbl

計算できていることを確認

[
    {
        "average_house_age": 28.639486434108505,
        "id": "average_house_age_tbl:[]",
        "total": 20640
    }
]

築年数30年未満のデータを元テーブル(housing)から消して、減っていることを確認

DELETE housing WHERE house_age < 30;
SELECT count() FROM housing GROUP ALL;
[
    {
        "count": 9971
    }
]

平均築年数テーブル(average_house_age_tbl)を見て、更新されていることを確認

SELECT * FROM average_house_age_tbl;
[
    {
        "average_house_age": 39.54367666232034,
        "id": "average_house_age_tbl:[]",
        "total": 9971
    }
]

# おわり

SurrealDBへのCSV書き込みと、テーブルの情報からテーブルを生やすところまで行いました。
次回はDEFINE FUNCTIONscripting functionを使って複雑なクエリをJavaScriptで書くかもしれません。

# 便利な開発ツール群

VSCode拡張(.surqlにハイライトがつく)

Surrealist(クライアントアプリ)