言語処理100本ノック 2015の第7章: データベースの10問です。
redisとMongoDBを使うことにします。
redis
// 起動 # redis-server /usr/local/etc/redis.conf // cli # redis-cli
MongoDB
// 起動 # sudo mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb.log // cli # mongo
60. KVSの構築
Key-Value-Store (KVS) を用い,アーティスト名(name)から活動場所(area)を検索するためのデータベースを構築せよ.
gist103c8ead51aad42cfc5b6686caa2039a
bufioのdefault sizeである4096だとReadLine()
しきれないところがあるのでNewReaderSize()
を使っています。
Goでredisを扱うためには、redigoを使っています。
また、set
を使ってKVSを構築すると同じアーティスト名が存在した場合に、上書きされてしまうのでのちのQ62,66で結果に不整合が生じます。
61. KVSの検索
60で構築したデータベースを用い,特定の(指定された)アーティストの活動場所を取得せよ.
giste6d4ca51b7b23914fadd5bdc0ec93c75
// 存在するアーティスト # go run q61.go supercell Japan // 存在しないアーティスト # go run q61.go hoge ` hoge ` is not found.
Q60でKVSの構築は済んでいるので、標準入力で受け取ったアーティストを検索するのみです。検索アーティストは趣味です。2015年当時のデータなので最近のアーティストはないようですが、知っているアーティストで検索すると引っかかるので楽しいです。
62. KVS内の反復処理
60で構築したデータベースを用い,活動場所が「Japan」となっているアーティスト数を求めよ.
gist6ac674e08083ff19c9154084b3d4787d
# go run q62.go 22821
keys *
で全keyを取得して、それを反復してareaを検索しました。
63. オブジェクトを値に格納したKVS
KVSを用い,アーティスト名(name)からタグと被タグ数(タグ付けされた回数)のリストを検索するためのデータベースを構築せよ.さらに,ここで構築したデータベースを用い,アーティスト名からタグと被タグ数を検索せよ.
gista57f35c159e2693ca841051ecbc390ef
# go run q63.go "Fear of War" count |tag -------------------- 1 | punk 1 | sweden 1 | hardcore 1 | fagersta
list型でtagを入れました。検索は適当に複数タグがあるアーティストにしてみました。
64. MongoDBの構築
アーティスト情報(artist.json.gz)をデータベースに登録せよ.さらに,次のフィールドでインデックスを作成せよ: name, aliases.name, tags.value, rating.value
gistb4ce4fe18042ae02c8eafe941f59548b
# go run q64.go before: 392.39824ms after: 1.308422ms
Indexをはる前後でのname
でのクエリの実行時間を測定してみましたが、速くなっていますね。aliases.name
, tags.value
, rating.value
にはIndexをはらずに、name
のみIndexをはると800us程度になるので、むやみやたらにIndexをはればいいわけではないですね。
GolangでMongoDBを扱うためのbsonについては以前記事にまとめましたので、そちらも御覧ください。
65. MongoDBの検索
MongoDBのインタラクティブシェルを用いて,"Queen"というアーティストに関する情報を取得せよ.さらに,これと同様の処理を行うプログラムを実装せよ.
// インタラクティブシェル > db.artist.find({"name": "Queen"}) { "_id" : ObjectId("59aa3c32bb03c3f9e15a51ce"), "name" : "Queen", "tags" : [ { "count" : 1, "value" : "kamen rider w" }, { "count" : 1, "value" : "related-akb48" } ], "rating" : { "count" : 0, "value" : 0 }, "sortname" : "Queen", "ended" : true, "gid" : "420ca290-76c5-41af-999e-564d7c71f1a7", "id" : 701492, "area" : "Japan", "aliases" : [ { "name" : "Queen", "sortname" : "Queen" } ], "begin" : { "year" : 0, "month" : 0, "date" : 0 }, "end" : { "year" : 0, "month" : 0, "date" : 0 }, "gender" : "Female", "type" : "Character" } { "_id" : ObjectId("59aa3c3abb03c3f9e15bdf28"), "name" : "Queen", "tags" : [ { "count" : 2, "value" : "hard rock" }, { "count" : 1, "value" : "70s" }, { "count" : 1, "value" : "queen family" }, { "count" : 1, "value" : "90s" }, { "count" : 1, "value" : "80s" }, { "count" : 1, "value" : "glam rock" }, { "count" : 4, "value" : "british" }, { "count" : 1, "value" : "english" }, { "count" : 2, "value" : "uk" }, { "count" : 1, "value" : "pop/rock" }, { "count" : 1, "value" : "pop-rock" }, { "count" : 1, "value" : "britannique" }, { "count" : 1, "value" : "classic pop and rock" }, { "count" : 1, "value" : "queen" }, { "count" : 1, "value" : "united kingdom" }, { "count" : 1, "value" : "langham 1 studio bbc" }, { "count" : 1, "value" : "kind of magic" }, { "count" : 1, "value" : "band" }, { "count" : 6, "value" : "rock" }, { "count" : 1, "value" : "platinum" } ], "rating" : { "count" : 24, "value" : 92 }, "sortname" : "Queen", "ended" : true, "gid" : "0383dadf-2a4e-4d10-a46a-e9e041da8eb3", "id" : 192, "area" : "United Kingdom", "aliases" : [ { "name" : "女王", "sortname" : "女王" } ], "begin" : { "year" : 1970, "month" : 6, "date" : 27 }, "end" : { "year" : 0, "month" : 0, "date" : 0 }, "gender" : "", "type" : "Group" } { "_id" : ObjectId("59aa3c4bbb03c3f9e15f53d9"), "name" : "Queen", "tags" : [ ], "rating" : { "count" : 0, "value" : 0 }, "sortname" : "Queen", "ended" : true, "gid" : "5eecaf18-02ec-47af-a4f2-7831db373419", "id" : 992994, "area" : "", "aliases" : [ ], "begin" : { "year" : 0, "month" : 0, "date" : 0 }, "end" : { "year" : 0, "month" : 0, "date" : 0 }, "gender" : "", "type" : "" }
gist2f86dd77e7d54026d04bf478bff96fb0
# go run q65.go {Queen [{1 kamen rider w} {1 related-akb48}] {0 0} Queen true 420ca290-76c5-41af-999e-564d7c71f1a7 701492 Japan [{Queen Queen}] {0 0 0} {0 0 0} Female Character} {Queen [{2 hard rock} {1 70s} {1 queen family} {1 90s} {1 80s} {1 glam rock} {4 british} {1 english} {2 uk} {1 pop/rock} {1 pop-rock} {1 britannique} {1 classic pop and rock} {1 queen} {1 united kingdom} {1 langham 1 studio bbc} {1 kind of magic} {1 band} {6 rock} {1 platinum}] {24 92} Queen true 0383dadf-2a4e-4d10-a46a-e9e041da8eb3 192 United Kingdom [{女王 女王}] {1970 6 27} {0 0 0} Group} {Queen [] {0 0} Queen true 5eecaf18-02ec-47af-a4f2-7831db373419 992994 [] {0 0 0} {0 0 0} }
Q64で構築したDBのクエリを投げるだけです。
66. 検索件数の取得
MongoDBのインタラクティブシェルを用いて,活動場所が「Japan」となっているアーティスト数を求めよ.
> db.artist.find({"area": "Japan"}).count() 22821
67. 複数のドキュメントの取得
特定の(指定した)別名を持つアーティストを検索せよ.
gist2ae3e6047aa223568e14a7abef7bd9b5
# go run q67.go supercell {supercell [] {3 100} supercell true 9b15ff5e-5bd1-43c2-821d-e31240aad334 311779 Japan [{超级单体 超级单体} {supercell スーパーセル}] {2007 0 0} {0 0 0} Group}
ほぼQ65と同じですね。
68. ソート
"dance"というタグを付与されたアーティストの中でレーティングの投票数が多いアーティスト・トップ10を求めよ.
gist6ae30eb5984a5b4699604fe6baa6eb0d
# go run q68.go Madonna Björk The Prodigy Rihanna Britney Spears Maroon 5 Adam Lambert Fatboy Slim Basement Jaxx Gigi D’Agostino Cornershop Duran Duran
sortパッケージがgo1.8以上で変わっていたのは知っていたものの試していなかったので触れてよかったです。
69. Webアプリケーションの作成
ユーザから入力された検索条件に合致するアーティストの情報を表示するWebアプリケーションを作成せよ.アーティスト名,アーティストの別名,タグ等で検索条件を指定し,アーティスト情報のリストをレーティングの高い順などで整列して表示せよ.
gistb97736d9ce01ae3766f919d2d749fcb6
テンプレートファイルは以下です。
gist3d7903a98687bfcf6e5ce9f49be189a3
gist308ac9755a102f56f44f9f1eb7307304
どうやらginというHttpRouterが有名そうなので、今回はginを使って、検索フォームから検索し、テーブルで結果を表示するようにしてみました。
CLIからq69.go
を実行した状態で、ブラウザでhttp://localhost:8080/index
へアクセスすると以下のように表示されます。
検索してあげるとこんな感じです。空欄は元データが入っていないところです。
初めてgin
を使ってみましたが、c.JSON
などとすると簡単にjsonを返せるようなのでAPIサーバも書けそうです。
今回のフォームからユーザに入力させる形式のところはインジェクション対策は何もしていないのでこのままでは使えないですが、Goでひと通り書いてみて勉強になりました。
感想
redisは軽くしか触れたことがなかったので、復習も兼ねて勉強になりました。Q68まではサクサク進みますが、Q69は重めですね。実りが多かったのでよかったですが。
いつも通りコードはGithubにも置いてあります。