素人的自然语言处理100训练:第64题
這是2015年《自然語言處理100本挑戰》的紀錄。我所使用的環境是Ubuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)。您可以在這裡找到之前挑戰的列表。
第七章:数据库
artist.json.gz是一个文件,它是在开放音乐数据库MusicBrainz中,将与艺术家相关的信息转换为JSON格式,并以gzip格式进行压缩的。该文件中每一行都以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的数据存储和检索到键值存储(KVS)和面向文档的数据库中。可以使用LevelDB、Redis、KyotoCabinet等作为KVS。作为面向文档的数据库,选择使用MongoDB,也可以使用CouchDB或RethinkDB等。
64. MongoDB的建立
将艺术家信息(artist.json.gz)注册到数据库。并在以下字段上创建索引:name、aliases.name、tags.value、rating.value。
完成的代码出来了。
# coding: utf-8
import gzip
import json
import pymongo
from pymongo import MongoClient
fname = 'artist.json.gz'
unit_bulk = 10000 # バルクインサートする単位(件)
# MongoDBのデータベースtestdbにコレクションartistを作成
client = MongoClient()
db = client.testdb
collection = db.artist
# gzファイル読み込み
with gzip.open(fname, 'rt') as data_file:
# 1行ずつパースしてbufに詰め込む
buf = []
for i, line in enumerate(data_file, 1):
data_json = json.loads(line)
buf.append(data_json)
# unit_bulk件たまったらartistへバルクインサート
if i % unit_bulk == 0:
collection.insert_many(buf)
buf = []
print('{}件追加完了'.format(i))
# 最後のunit_bulkに入らなかった半端分の追加
if len(buf) > 0:
collection.insert_many(buf)
print('{}件追加完了'.format(i))
# インデックス作成
collection.create_index([('name', pymongo.ASCENDING)])
collection.create_index([('aliases.name', pymongo.ASCENDING)])
collection.create_index([('tags.value', pymongo.ASCENDING)])
collection.create_index([('rating.value', pymongo.ASCENDING)])
执行结果:
10000件追加完了
20000件追加完了
30000件追加完了
40000件追加完了
50000件追加完了
(中略)
890000件追加完了
900000件追加完了
910000件追加完了
920000件追加完了
921337件追加完了
MongoDB 是什么?
artist.json.gz是一个文件,它是在开放音乐数据库MusicBrainz中,将与艺术家相关的信息转换为JSON格式,并以gzip格式进行压缩的。该文件中每一行都以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的数据存储和检索到键值存储(KVS)和面向文档的数据库中。可以使用LevelDB、Redis、KyotoCabinet等作为KVS。作为面向文档的数据库,选择使用MongoDB,也可以使用CouchDB或RethinkDB等。
将艺术家信息(artist.json.gz)注册到数据库。并在以下字段上创建索引:name、aliases.name、tags.value、rating.value。
完成的代码出来了。
# coding: utf-8
import gzip
import json
import pymongo
from pymongo import MongoClient
fname = 'artist.json.gz'
unit_bulk = 10000 # バルクインサートする単位(件)
# MongoDBのデータベースtestdbにコレクションartistを作成
client = MongoClient()
db = client.testdb
collection = db.artist
# gzファイル読み込み
with gzip.open(fname, 'rt') as data_file:
# 1行ずつパースしてbufに詰め込む
buf = []
for i, line in enumerate(data_file, 1):
data_json = json.loads(line)
buf.append(data_json)
# unit_bulk件たまったらartistへバルクインサート
if i % unit_bulk == 0:
collection.insert_many(buf)
buf = []
print('{}件追加完了'.format(i))
# 最後のunit_bulkに入らなかった半端分の追加
if len(buf) > 0:
collection.insert_many(buf)
print('{}件追加完了'.format(i))
# インデックス作成
collection.create_index([('name', pymongo.ASCENDING)])
collection.create_index([('aliases.name', pymongo.ASCENDING)])
collection.create_index([('tags.value', pymongo.ASCENDING)])
collection.create_index([('rating.value', pymongo.ASCENDING)])
执行结果:
10000件追加完了
20000件追加完了
30000件追加完了
40000件追加完了
50000件追加完了
(中略)
890000件追加完了
900000件追加完了
910000件追加完了
920000件追加完了
921337件追加完了
MongoDB 是什么?
# coding: utf-8
import gzip
import json
import pymongo
from pymongo import MongoClient
fname = 'artist.json.gz'
unit_bulk = 10000 # バルクインサートする単位(件)
# MongoDBのデータベースtestdbにコレクションartistを作成
client = MongoClient()
db = client.testdb
collection = db.artist
# gzファイル読み込み
with gzip.open(fname, 'rt') as data_file:
# 1行ずつパースしてbufに詰め込む
buf = []
for i, line in enumerate(data_file, 1):
data_json = json.loads(line)
buf.append(data_json)
# unit_bulk件たまったらartistへバルクインサート
if i % unit_bulk == 0:
collection.insert_many(buf)
buf = []
print('{}件追加完了'.format(i))
# 最後のunit_bulkに入らなかった半端分の追加
if len(buf) > 0:
collection.insert_many(buf)
print('{}件追加完了'.format(i))
# インデックス作成
collection.create_index([('name', pymongo.ASCENDING)])
collection.create_index([('aliases.name', pymongo.ASCENDING)])
collection.create_index([('tags.value', pymongo.ASCENDING)])
collection.create_index([('rating.value', pymongo.ASCENDING)])
10000件追加完了
20000件追加完了
30000件追加完了
40000件追加完了
50000件追加完了
(中略)
890000件追加完了
900000件追加完了
910000件追加完了
920000件追加完了
921337件追加完了
MongoDB 是什么?
MongoDB是一种被称为文档数据库的东西,它具有类似于本次问题中使用的音乐数据库的结构,能够存储和管理这种数据的特点。这是它的官方网站,很遗憾是用英文的,但MongoDB的概述有日文。此外,因为网络上有很多关于MongoDB的解释,所以请自行搜索以获取更详细的信息。
此外,据我了解,MongoDB也有付费版,但本次我们使用的是免费的Community Edition。
安装MongoDB
我以为用conda只需要一步,但是需要编写服务脚本吗?听起来有点麻烦,所以这次我按照官方网站的步骤进行了安装。
我在使用的Ubuntu 16.04 LTS上安装MongoDB Community Edition的步骤可以在”在Ubuntu上安装MongoDB Community Edition”找到。虽然是用英文写的,但并不难。按照”安装MongoDB Community Edition”的指示进行操作,就能成功安装。
segavvy@ubuntu:~$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
[sudo] segavvy のパスワード:
Executing: /tmp/tmp.8h93YVjQSG/gpg.1.sh --keyserver
hkp://keyserver.ubuntu.com:80
--recv
0C49F3730359A14518585931BC711F9BA15703C6
gpg: 鍵A15703C6をhkpからサーバkeyserver.ubuntu.comに要求
gpg: 鍵A15703C6: 公開鍵"MongoDB 3.4 Release Signing Key <packaging@mongodb.com>"をインポートしました
gpg: 処理数の合計: 1
gpg: インポート: 1 (RSA: 1)
segavvy@ubuntu:~$ echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list
deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse
segavvy@ubuntu:~$ sudo apt-get update
無視:1 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 InRelease
取得:2 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 Release [3,452 B]
ヒット:3 http://us.archive.ubuntu.com/ubuntu xenial InRelease
取得:4 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
取得:5 http://us.archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
取得:6 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 Release.gpg [801 B]
取得:7 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse amd64 Packages [2,778 B]
取得:8 http://us.archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]
取得:9 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse arm64 Packages [2,784 B]
取得:10 http://security.ubuntu.com/ubuntu xenial-security/main amd64 DEP-11 Metadata [68.1 kB]
取得:11 http://us.archive.ubuntu.com/ubuntu xenial-updates/main amd64 DEP-11 Metadata [303 kB]
取得:12 http://security.ubuntu.com/ubuntu xenial-security/main DEP-11 64x64 Icons [43.0 kB]
取得:13 http://security.ubuntu.com/ubuntu xenial-security/universe amd64 DEP-11 Metadata [19.4 kB]
取得:14 http://security.ubuntu.com/ubuntu xenial-security/universe DEP-11 64x64 Icons [25.6 kB]
取得:15 http://security.ubuntu.com/ubuntu xenial-security/multiverse amd64 DEP-11 Metadata [212 B]
取得:16 http://us.archive.ubuntu.com/ubuntu xenial-updates/main DEP-11 64x64 Icons [179 kB]
取得:17 http://us.archive.ubuntu.com/ubuntu xenial-updates/universe amd64 DEP-11 Metadata [121 kB]
取得:18 http://us.archive.ubuntu.com/ubuntu xenial-updates/universe DEP-11 64x64 Icons [145 kB]
取得:19 http://us.archive.ubuntu.com/ubuntu xenial-updates/multiverse amd64 DEP-11 Metadata [2,520 B]
取得:20 http://us.archive.ubuntu.com/ubuntu xenial-backports/main amd64 DEP-11 Metadata [208 B]
取得:21 http://us.archive.ubuntu.com/ubuntu xenial-backports/universe amd64 DEP-11 Metadata [212 B]
取得:22 http://us.archive.ubuntu.com/ubuntu xenial-backports/multiverse amd64 DEP-11 Metadata [212 B]
ヒット:23 http://archive.ubuntulinux.jp/ubuntu xenial InRelease
無視:24 http://archive.ubuntulinux.jp/ubuntu-ja-non-free xenial InRelease
ヒット:25 http://archive.ubuntulinux.jp/ubuntu-ja-non-free xenial Release
1,223 kB を 15秒 で取得しました (80.2 kB/s)
AppStream cache update completed, but some metadata was ignored due to errors.
パッケージリストを読み込んでいます... 完了
segavvy@ubuntu:~$ sudo apt-get install -y mongodb-org
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
ubuntu-core-launcher
これを削除するには 'sudo apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
mongodb-org-mongos mongodb-org-server mongodb-org-shell mongodb-org-tools
以下のパッケージが新たにインストールされます:
mongodb-org mongodb-org-mongos mongodb-org-server mongodb-org-shell
mongodb-org-tools
アップグレード: 0 個、新規インストール: 5 個、削除: 0 個、保留: 16 個。
66.6 MB のアーカイブを取得する必要があります。
この操作後に追加で 269 MB のディスク容量が消費されます。
取得:1 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse amd64 mongodb-org-shell amd64 3.4.1 [7,955 kB]
取得:2 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse amd64 mongodb-org-server amd64 3.4.1 [14.2 MB]
取得:3 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse amd64 mongodb-org-mongos amd64 3.4.1 [8,093 kB]
取得:4 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse amd64 mongodb-org-tools amd64 3.4.1 [36.3 MB]
取得:5 http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4/multiverse amd64 mongodb-org amd64 3.4.1 [3,564 B]
66.6 MB を 12秒 で取得しました (5,236 kB/s)
以前に未選択のパッケージ mongodb-org-shell を選択しています。
(データベースを読み込んでいます ... 現在 209736 個のファイルとディレクトリがインストールされています。)
.../mongodb-org-shell_3.4.1_amd64.deb を展開する準備をしています ...
mongodb-org-shell (3.4.1) を展開しています...
以前に未選択のパッケージ mongodb-org-server を選択しています。
.../mongodb-org-server_3.4.1_amd64.deb を展開する準備をしています ...
mongodb-org-server (3.4.1) を展開しています...
以前に未選択のパッケージ mongodb-org-mongos を選択しています。
.../mongodb-org-mongos_3.4.1_amd64.deb を展開する準備をしています ...
mongodb-org-mongos (3.4.1) を展開しています...
以前に未選択のパッケージ mongodb-org-tools を選択しています。
.../mongodb-org-tools_3.4.1_amd64.deb を展開する準備をしています ...
mongodb-org-tools (3.4.1) を展開しています...
以前に未選択のパッケージ mongodb-org を選択しています。
.../mongodb-org_3.4.1_amd64.deb を展開する準備をしています ...
mongodb-org (3.4.1) を展開しています...
man-db (2.7.5-1) のトリガを処理しています ...
mongodb-org-shell (3.4.1) を設定しています ...
mongodb-org-server (3.4.1) を設定しています ...
システムユーザー `mongodb' (UID 121) を追加しています...
新しいユーザー `mongodb' (UID 121) をグループ `nogroup' に追加しています...
ホームディレクトリ `/home/mongodb' を作成しません。
グループ `mongodb' (GID 129) を追加しています...
完了。
ユーザー `mongodb' をグループ `mongodb' に追加しています...
ユーザ mongodb をグループ mongodb に追加
完了。
mongodb-org-mongos (3.4.1) を設定しています ...
mongodb-org-tools (3.4.1) を設定しています ...
mongodb-org (3.4.1) を設定しています ...
由于安装MongoDB核心已经完成,现在确认启动。
segavvy@ubuntu:~$ sudo service mongod start
可以通过”验证MongoDB是否成功启动”的步骤来确认它是否已经正常启动。
2017-01-09T22:00:38.186+0900 I CONTROL [initandlisten] MongoDB starting : pid=4384 port=27017 dbpath=/var/lib/mongodb 64-bit host=ubuntu
2017-01-09T22:00:38.186+0900 I CONTROL [initandlisten] db version v3.4.1
2017-01-09T22:00:38.186+0900 I CONTROL [initandlisten] git version: 5e103c4f5583e2566a45d740225dc250baacfbd7
2017-01-09T22:00:38.186+0900 I CONTROL [initandlisten] OpenSSL version: OpenSSL 1.0.2g 1 Mar 2016
(中略)
2017-01-09T22:00:38.254+0900 I FTDC [initandlisten] Initializing full-time diagnostic data capture with directory '/var/lib/mongodb/diagnostic.data'
2017-01-09T22:00:38.265+0900 I INDEX [initandlisten] build index on: admin.system.version properties: { v: 2, key: { version: 1 }, name: "incompatible_with_version_32", ns: "admin.system.version" }
2017-01-09T22:00:38.265+0900 I INDEX [initandlisten] building index using bulk method; build may temporarily use up to 500 megabytes of RAM
2017-01-09T22:00:38.266+0900 I INDEX [initandlisten] build index done. scanned 0 total records. 0 secs
2017-01-09T22:00:38.266+0900 I COMMAND [initandlisten] setting featureCompatibilityVersion to 3.4
2017-01-09T22:00:38.267+0900 I NETWORK [thread1] waiting for connections on port 27017
因为在最后一行写着“在端口27017上等待连接”,所以看起来应该没问题。
安装PyMongo
接下来是安装PyMongo来使用Python操作MongoDB,但这只需要一行conda命令。
segavvy@ubuntu:~$ conda search pymongo
Fetching package metadata .......
pymongo 2.7.2 py26_0 defaults
2.7.2 py27_0 defaults
2.7.2 py33_0 defaults
2.7.2 py34_0 defaults
2.8 py26_0 defaults
2.8 py27_0 defaults
2.8 py33_0 defaults
2.8 py34_0 defaults
3.0.3 py27_0 defaults
3.0.3 py34_0 defaults
3.0.3 py35_0 defaults
3.3.0 py27_0 defaults
3.3.0 py34_0 defaults
3.3.0 py35_0 defaults
3.3.0 py36_0 defaults
segavvy@ubuntu:~$ conda install pymongo
Fetching package metadata .......
Solving package specifications: ..........
Package plan for installation in environment /home/segavvy/anaconda3:
The following packages will be downloaded:
package | build
---------------------------|-----------------
pymongo-3.3.0 | py35_0 376 KB
The following NEW packages will be INSTALLED:
pymongo: 3.3.0-py35_0
Proceed ([y]/n)? y
Fetching packages ...
pymongo-3.3.0- 100% |################################| Time: 0:00:00 8.30 MB/s
Extracting packages ...
[ COMPLETE ]|###################################################| 100%
Linking packages ...
[ COMPLETE ]|###################################################| 100%
我会确认一下Python的可用性。
segavvy@ubuntu:~$ python
Python 3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 2 2016, 17:53:06)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymongo
>>>
环境已经搭建完毕。
启动、关闭、重启MongoDB
在安装步骤的后半部分,启动、关闭和重新启动的方法被整理在”运行 MongoDB Community Edition”中。
segavvy@ubuntu:~$ sudo service mongod start
segavvy@ubuntu:~$ sudo service mongod stop
segavvy@ubuntu:~$ sudo service mongod restart
使用MongoDB的命令行界面(交互式Shell)
在MongoDB启动时,可以使用mongo命令执行各种操作。使用svjunic整理的MongoDB命令备忘录非常方便。
以下是显示数据库列表的示例。
segavvy@ubuntu:~$ mongo
MongoDB shell version v3.4.1
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.1
Server has startup warnings:
2017-01-14T12:51:31.792+0900 I STORAGE [initandlisten]
2017-01-14T12:51:31.792+0900 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2017-01-14T12:51:31.792+0900 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten]
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten]
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten]
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten]
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2017-01-14T12:51:32.332+0900 I CONTROL [initandlisten]
> show dbs
admin 0.000GB
local 0.000GB
testdb 0.254GB
>
在运行mongo命令后,会出现许多警告信息。在使用正式系统时,最好进行相应的处理。顺便提一下,在数据库列表中的“testdb”在安装后是不存在的。它是根据本次问题执行而创建的。
使用PyMongo进行编程
如果你看一下PyMongo的教程(本次使用conda安装的版本是3.3.0)(最新版本在这里),基本上就能理解怎么使用PyMongo。
在这个问题中,我们创建了一个名为”testdb”的数据库,并在其中创建了一个名为”artist”的集合,并且持续不断地向其中注册JSON数据。
大容量插入
为了处理目前近百万条记录,注册使用了Bulk Insert功能,尽管使用collection.insert_one()(最新)逐一注册也是可以的。
每次执行collection.insert_one()都会向MongoDB服务器发送注册请求,所以批量重复执行时会产生不可忽视的开销。而使用collection.insert_many()(最新)可以将多个数据打包成一个列表,并一次性发送注册请求,从而减少与服务器的往返次数,提高效率。本次使用这个功能将每次注册1万条数据。然而,即使如此,如果接近100万条数据,仍然需要较长时间,因此我们设置每1万条数据显示一次处理进度。
关于Bulk Insert,Tutorial的Bulk Inserts(最新)中有一个概述说明。
创建索引
你可以使用collection.create_index()函数创建索引,从而提高搜索速度。在“Tutorial的Indexing”中有关于此的概要说明。
第65号的练习到此为止了。如果有错误或者其他问题,请指正,谢谢。
实施结果中包含一部分使用100本敲击所使用的语料库数据,这些数据是通过发行的。第7章使用的数据的许可是创作共用 署名-非商业性使用-相同方式共享3.0(非移植)(中文翻译)。