読者です 読者をやめる 読者になる 読者になる

北野坂備忘録

主にインストールやプログラミングのメモを載せています。

言語処理100本ノック 2015年版 (60~63)

第7章: データベース

artist.json.gzは,オープンな音楽データベースMusicBrainzの中で,アーティストに関するものをJSON形式に変換し,gzip形式で圧縮したファイルである.このファイルには,1アーティストに関する情報が1行にJSON形式で格納されている.JSON形式の概要は以下の通りである.
(略)
artist.json.gzのデータをKey-Value-Store (KVS) およびドキュメント志向型データベースに格納・検索することを考える.KVSとしては,LevelDB,Redis,KyotoCabinet等を用いよ.ドキュメント志向型データベースとして,MongoDBを採用したが,CouchDBやRethinkDB等を用いてもよい.

まずはKVS側の60~63を掲載します。

60. KVSの構築

Key-Value-Store (KVS) を用い,アーティスト名(name)から活動場所(area)を検索するためのデータベースを構築せよ

 KyotoCabinet は別件で見たことがあるので、何も知らない LevelDB か Redis にしたいと思います。今回は LevelDB を採用しました。
 しかしこの設問、60ができているかどうかテストするためには何度も61の作業を行うわけで、設問を分けている意味が分かりません。

#!/usr/bin/env python

import codecs
import json
import plyvel

fin = codecs.open('artist.json', 'r', 'utf_8')

if __name__ == "__main__":
  db = plyvel.DB('artist.ldb',create_if_missing=True)

  for line in fin:
    jsonData = json.loads(line)
    if "name" in jsonData and "area" in jsonData:
      db.put(jsonData["name"].encode(), jsonData["area"].encode())

  db.close()

61. KVSの検索

60で構築したデータベースを用い,特定の(指定された)アーティストの活動場所を取得せよ.

 60の構築中に終わっています。

#!/usr/bin/env python

import plyvel
import sys

if __name__ == "__main__":
  param = sys.argv

  db = plyvel.DB('artist.ldb',create_if_missing=True)

  if len(param)>1:
    name = param[1].encode()
  else:
    name = b"Oasis"

  area = db.get(name)
  print(name,area)

  db.close()

62. KVS内の反復処理

60で構築したデータベースを用い,活動場所が「Japan」となっているアーティスト数を求めよ.

#!/usr/bin/env python

import plyvel

if __name__ == "__main__":

  db = plyvel.DB('artist.ldb',create_if_missing=True)

  n = 0
  for name,area in db:
    if area == b"Japan":
      print(name.decode(),area)
      n += 1

  print(n)

  db.close()

 タイトルの「KVS内の反復処理」という表現が気になりますが、ただの for文で終わらせてしまいました。

結果

龍山一平 b'Japan'
龍門渕透華 b'Japan'
류영기 b'Japan'
2番をつくらなくっちゃネ!実行委員会 b'Japan'
9人の麦わら海賊団 b'Japan'
ALiBi b'Japan'
GREGORY b'Japan'
MANNEQUIN b'Japan'
NHKみんなのうた b'Japan'
SHIOMI b'Japan'
22128

 アーティスト名に「9人の麦わら海賊団」とかが入っていて笑ってしまいました。

63. オブジェクトを値に格納したKVS

KVSを用い,アーティスト名(name)からタグと被タグ数(タグ付けされた回数)のリストを検索するためのデータベースを構築せよ.さらに,ここで構築したデータベースを用い,アーティスト名からタグと被タグ数を検索せよ.

 valueはバイト列でないといけないので、リストそのままでは放り込めません。
 バイト列にする方法はいくつかありますが、json をインポートしているのでそのまま使ってしまいましょう。
 プログラムを格納用の63-1.py, 検索用の63-2.pyに分割します。
 問題は検索側で、jsonで文字列として格納しているためそのままではリストや辞書として扱えません。今回は astモジュールを使用しました。

63-1.py
#!/usr/bin/env python

import codecs
import json
import plyvel

fin = codecs.open('artist.json', 'r', 'utf_8')

if __name__ == "__main__":
  db = plyvel.DB('artisttag.ldb',create_if_missing=True)

  for line in fin:
    jsonData = json.loads(line)
    if "tags" in jsonData:
      print(jsonData["name"],jsonData["tags"])
      tags = json.dumps(jsonData["tags"])
      db.put(jsonData["name"].encode(), tags.encode())

  db.close()
63-2.py
#!/usr/bin/env python

import plyvel
from ast import literal_eval
import sys

if __name__ == "__main__":
  param = sys.argv
  if len(param)>1:
    name = param[1].encode()
  else:
    name = b"Oasis"

  db = plyvel.DB('artisttag.ldb',create_if_missing=True)

  tags = literal_eval(db.get(name).decode())

  for tag in tags:
    print("tag:",tag["value"],"\tcount:",tag["count"])

  db.close()
結果(Oasisで検索)
tag: rock 	count: 1
tag: britpop 	count: 3
tag: british 	count: 4
tag: uk 	count: 1
tag: britannique 	count: 1
tag: rock and indie 	count: 1
tag: england 	count: 1
tag: manchester 	count: 1