Edited at

素人の言語処理100本ノック:68

言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。


第7章: データベース


artist.json.gzは,オープンな音楽データベースMusicBrainzの中で,アーティストに関するものをJSON形式に変換し,gzip形式で圧縮したファイルである.このファイルには,1アーティストに関する情報が1行にJSON形式で格納されている.JSON形式の概要は以下の通りである.

フィールド

内容

id
ユニーク識別子
整数
20660

gid
グローバル識別子
文字列
"ecf9f3a3-35e9-4c58-acaa-e707fba45060"

name
アーティスト名
文字列
"Oasis"

sort_name
アーティスト名(辞書順整列用)
文字列
"Oasis"

area
活動場所
文字列
"United Kingdom"

aliases
別名
辞書オブジェクトのリスト

aliases[].name
別名
文字列
"オアシス"

aliases[].sort_name
別名(整列用)
文字列
"オアシス"

begin
活動開始日
辞書

begin.year
活動開始年
整数
1991

begin.month
活動開始月
整数

begin.date
活動開始日
整数

end
活動終了日
辞書

end.year
活動終了年
整数
2009

end.month
活動終了月
整数
8

end.date
活動終了日
整数
28

tags
タグ
辞書オブジェクトのリスト

tags[].count
タグ付けされた回数
整数
1

tags[].value
タグ内容
文字列
"rock"

rating
レーティング
辞書オブジェクト

rating.count
レーティングの投票数
整数
13

rating.value
レーティングの値(平均値)
整数
86

artist.json.gzのデータをKey-Value-Store (KVS) およびドキュメント志向型データベースに格納・検索することを考える.KVSとしては,LevelDB,Redis,KyotoCabinet等を用いよ.ドキュメント志向型データベースとして,MongoDBを採用したが,CouchDBやRethinkDB等を用いてもよい.



68. ソート


"dance"というタグを付与されたアーティストの中でレーティングの投票数が多いアーティスト・トップ10を求めよ.



出来上がったコード:


main.py

# coding: utf-8

import json
import pymongo
from pymongo import MongoClient

# MongoDBのデータベースtestdbにコレクションartistにアクセス
client = MongoClient()
db = client.testdb
collection = db.artist

# 検索
results = collection.find({'tags.value': 'dance'})

# ソート
results.sort('rating.count', pymongo.DESCENDING)

# 10件表示
for doc in results.limit(10):

if 'rating' in doc:
rating = doc['rating']['count']
else:
rating = '(none)' # ratingがないドキュメントもあるので

print('{}(id:{})\t{}'.format(doc['name'], doc['id'], rating))



実行結果:


実行結果

Madonna(id:89)  26

Björk(id:1022) 23
The Prodigy(id:44954) 23
Rihanna(id:262731) 15
Britney Spears(id:791) 13
Maroon 5(id:66179) 11
Adam Lambert(id:627661) 7
Fatboy Slim(id:255) 7
Basement Jaxx(id:1060) 6
Cornershop(id:798) 5


ソート

ソートは検索結果のCursorオブジェクトに対してsort()最新)で実行します。そこから列挙すればソートされた結果が取得できる流れです。


ソート対象のフィールドが存在しなかったり型が違ったりする場合の扱い

ソート対象のフィールドが存在しないドキュメントがある場合や、ドキュメント間でそのフィールドの型が異なる場合のルールは、Comparison/Sort Orderで解説されています。

今回の問題ではrating.countが存在しないドキュメントがヒットしますが、その場合、Non-existent Fieldsの説明によるとnullと同じ扱いになり、nullはどの型よりも小さな値として扱われるようです。今回の問題は大きい順でソートしますので、rating.countが存在しないドキュメントは末尾に寄せられています。もし先頭に寄せられる仕様だった場合は、何か工夫しないといけないところでした。


最初の10件を取り出す

検索結果のCursorオブジェクトに対してlimit()最新)で取り出せます。(@takatsugukatoさん、アドバイスありがとうございます。)

 

69本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。


実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。この第7章で用いているデータのライセンスはクリエイティブ・コモンズ 表示 - 非営利 - 継承 3.0 非移植日本語訳)です。