#はじめに
前回では、GoのDataFrameの基本的な扱い方を紹介しました。
今回はDB接続して、DataFrameに入れてみようと思います。
(SQLでやったらとか言う野暮なツッコミは無しで(^人^)オ・ネ・ガ・イ)
LoadStructsでやってみる
一応ハンズラボのアドベントカレンダーなので、DBから東急ハンズの店舗情報を取得します。
LoadStructs
が個人的に一番DataFrame
を作りやすいのでやってみました。
main.go
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/kniren/gota/dataframe"
)
// DBから取得するカラムを定義
type Store struct {
ID int
Name string
Address string
}
func main() {
db, err := sql.Open("mysql", "<user>:<password>@tcp(<host>:3306)/<db>")
if err != nil {
panic(err.Error())
}
defer db.Close()
rows, err := db.Query("SELECT id, name, address FROM store")
if err != nil {
panic(err.Error())
}
defer rows.Close()
user := []Store{}
for rows.Next() {
var store Store
err := rows.Scan(&(store.ID), &(store.Name), &(store.Address))
if err != nil {
panic(err.Error())
}
user = append(user, store)
}
if err := rows.Err(); err != nil {
panic(err.Error())
}
df := dataframe.LoadStructs(user)
fmt.Println(df)
}
[84x3] DataFrame
ID Name Address
0: 1 渋谷店 渋谷区宇田川町12-18
1: 4 江坂店 吹田市豊津町9-40
2: 5 町田店 町田市原町田6-4-1東急ツインズ イースト 6F・7F
3: 6 池袋店 豊島区東池袋1-28-10
4: 7 三宮店 神戸市中央区下山手通2-10-1
5: 8 横浜店 横浜市西区南幸1-3-1横浜モアーズ 5F〜7F
6: 9 広島店 広島市中区八丁堀16-10
7: 10 新宿店 渋谷区千駄ヶ谷5-24-2タイムズスクエアビル 2F〜8F
8: 11 札幌店 札幌市中央区南一条西6-4-1
9: 12 心斎橋店 大阪市中央区南船場3-4-12
... ... ...
<int> <string> <string>
やっていることはこのような流れ
-
Struct
で取得してくるカラムを定義する - DB接続して、クエリを実行しデータを取得(
Struct
) - データを
for
で回してスライスにStruct
を詰める -
dataframe
のLoadStructs
にスライスを入れて読ませる
面倒な点
-
Struct
で取得してくるカラムを定義しないといけない -
Struct
を変更したらクエリも変更しないといけない
Structを定義せずにDataFrameを作成する
dataframe
のLoadStructs
を使用しましたが、今回はLoadRecords
を使用してDataFrame
を作成します。
LoadRecords
の詳細は前回の記事を見てください。
main.go
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/thimi0412/gota/dataframe"
)
func main() {
stores := [][]string{}
db, err := sql.Open("mysql", "<user>:password@tcp(<host>:3306)/<db>")
if err != nil {
panic(err.Error())
}
defer db.Close()
// 追加でurlも選択します
rows, err := db.Query("SELECT id, name, address, url FROM store")
if err != nil {
panic(err.Error())
}
// カラムを取得してstoresに詰める
columns, err := rows.Columns()
if err != nil {
panic(err.Error())
}
// 一つ目の要素がカラム名となる
stores = append(stores, columns)
values := make([]sql.RawBytes, len(columns))
scanArgs := make([]interface{}, len(values))
for i := range values {
scanArgs[i] = &values[i]
}
for rows.Next() {
err = rows.Scan(scanArgs...)
if err != nil {
panic(err.Error())
}
var value string
// 取得した値をスライスに詰める
store := []string{}
for _, col := range values {
if col == nil {
value = "NULL"
} else {
value = string(col)
}
store = append(store, value)
}
// 作成したスライスをスライスに詰める
stores = append(stores, store)
}
df := dataframe.LoadRecords(stores)
fmt.Println(df)
}
[84x4] DataFrame
id name address url
0: 1 渋谷店 渋谷区宇田川町12-18 https://shibuya.tokyu-hands.co.jp/
1: 4 江坂店 吹田市豊津町9-40 https://esaka.tokyu-hands.co.jp/
2: 5 町田店 町田市原町田6-4-1東急ツインズ イースト 6F・7F https://machida.tokyu-hands.co.jp/
3: 6 池袋店 豊島区東池袋1-28-10 https://ikebukuro.tokyu-hands.co.jp/
4: 7 三宮店 神戸市中央区下山手通2-10-1 https://sannomiya.tokyu-hands.co.jp/
5: 8 横浜店 横浜市西区南幸1-3-1横浜モアーズ 5F〜7F https://yokohama.tokyu-hands.co.jp/
6: 9 広島店 広島市中区八丁堀16-10 https://hiroshima.tokyu-hands.co.jp/
7: 10 新宿店 渋谷区千駄ヶ谷5-24-2タイムズスクエアビル 2F〜8F https://shinjuku.tokyu-hands.co.jp/
8: 11 札幌店 札幌市中央区南一条西6-4-1 https://sapporo.tokyu-hands.co.jp/
9: 12 心斎橋店 大阪市中央区南船場3-4-12 https://shinsaibashi.tokyu-hands.co.jp/
... ... ... ...
<int> <string> <string> <string>
コードが長くなりましたがやっていることは
- DB接続して、クエリを実行しデータを取得
- スライスを作成
- カラムを取得してスライスに入れる(こいつがヘッダ)
- 選択したカラムの値を入れたスライスを2.で作成したスライスに入れる
-
LoadRecords
に読ませる
手が届かないところ
LoadRecords
は型を指定してDataFrame
で読み込めないので、例えばid
が001
だった場合LoadRecords
で読み込むと上の出力結果のようにid
が1
になってしまいます。
型をしっかりとしてしたい場合はLoadStruct
をしようした方がいいでしょう。
ハンズラボ Advent Calendar 2018 明日8日目は@naokiurです!