概要
python 3.4 から riak 2.0.x を操作します。python クライアントのドキュメントは、http://basho.github.io/riak-python-client/index.html にあります。
準備
riak をインストール
brew コマンドで riak 2.0.4 のインストールが可能です。brew コマンドだと、最新から遅れているようなので、最新にしたい場合は、各自でどうぞ。
% brew install riak
ファイルディスクリプタを変更するために設定をします。これらを実施しないと起動してくれないようです。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>65536</string>
<string>65536</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxproc</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxproc</string>
<string>2048</string>
<string>2048</string>
</array>
<key>RunAtLoad</key>
<true />
<key>ServiceIPC</key>
<false />
</dict>
</plist>
ここでOSを再起動。
起動後に設定を確認。
% launchctl limit
cpu unlimited unlimited
filesize unlimited unlimited
data unlimited unlimited
stack 8388608 67104768
core 0 unlimited
rss unlimited unlimited
memlock unlimited unlimited
maxproc 2048 2048
maxfiles 65536 65536
riak 起動
pong と表示すればOK。
% riak start
% riak ping
pong
設定を変更
allow_multをtrueにします。
まず起動時に自動生成された設定ファイルの場所を確認します。
$ riak config effective | grep allow_mult
buckets.default.allow_mult = false
上記の出力情報ですと false でしたので true に変更します。
$ sudo echo "buckets.default.allow_mult = true" >> /usr/local/Cellar/riak/2.0.4/libexec/etc/riak.conf
riakを再起動してtrueになっていることを確認します。
$ riak restart
$ riak config effective | grep allow_mult
buckets.default.allow_mult = true
riak クライアントをインストール
公式でもある riak-python-client をインストールします。
% pip install riak
KVS としての riak
簡単な例
% ipython
import riak
client = riak.RiakClient()
bucket = client.bucket('manifestations')
obj = bucket.new('4873113938', data={
'title': '初めてのPython 第3版',
'creator': 'Mark Lutz',
'isbn': '4873113938'
}).store() # -> <riak.riak_object.RiakObject at 0x10a663898>
obj = bucket.new('4797372273', data={
'title': 'たのしいRuby 第4版',
'creator': '高橋 征義',
'isbn': '4797372273'
}).store() # -> <riak.riak_object.RiakObject at 0x10a6b4470>
print(bucket.get('4873113938').data) # -> {'creator': 'Mark Lutz', 'title': '初めてのPython 第3版', 'isbn': '4873113938'}
bucket.get_keys() # -> ['4873113938', '4797372273']
print(bucket.multiget(['4873113938','4873113938'])) # -> [<riak.riak_object.RiakObject object at 0x10a6b45f8>, <riak.riak_object.RiakObject object at 0x10a787a90>]
bucket.delete('4873113938')
print(bucket.get('4873113938').data) # -> None
bucket.get_keys() # -> ['4797372273']
カウンターを利用する
数値の増減を操作できる機能。標準であるのは助かります。
increment したあとに、store() しないといけないのは謎ですが...
$ riak-admin bucket-type create counters '{"props":{"datatype":"counter"}}'
$ riak-admin bucket-type activate counters
$ ipython
import riak
from riak.datatypes import Counter
client = riak.RiakClient()
bucket = client.bucket_type('counters').bucket('manifestations')
counter = Counter(bucket, 'manifestations')
counter.value # -> 0
counter.increment()
counter.store()
counter.value # -> 1
全文検索機能(Yokozuna)を使う
準備
初期状態では、検索機能(search)は off になっているはずですが、一応確認しておきます。offであれば、設定を変更して、riakを再起動します。
$ riak config effective | grep "search ="
search = off
$ sudo sed -e 's/search = off/search = on/' -i.back /usr/local/Cellar/riak/2.0.4/libexec/etc/riak.conf
$ riak restart
ok
$ riak ping
pong
$ riak config effective | grep "search ="
search = on
設定
面倒ですが、設定します。
% wget https://raw.githubusercontent.com/basho/yokozuna/develop/priv/default_schema.xml
% ipython
import riak
client = riak.RiakClient()
f = open('default_schema.xml')
content = f.read()
f.close()
schema_name = '_yz_default'
client.create_search_schema(schema_name, content)
client.create_search_index('manifestation_index','_yz_default')
bucket-typeを作成します。
$ riak-admin bucket-type create manifestation_index '{"props":{"search_index":"manifestation_index"}}'
manifestation_index created
$ riak-admin bucket-type activate manifestation_index
manifestations has been activated
データ登録と検索をやってみます。
$ ipython
import riak
client = riak.RiakClient()
bucket = client.bucket_type('manifestation_index').bucket('books')
book = bucket.new('4621088629', {'title_s': '東洋天文学史', 'isbn_s': '4621088629', 'price_i': 1080, 'creator_s': '中村 士', 'date_of_publication_dts': '2014-10-25T00:00:00Z'})
book.store()
book = bucket.new('4864102538', {'title_s': '宇宙探査機', 'isbn_s': '4864102538', 'price_i': 4320, 'creator_s': 'フィリップ・セゲラ', 'date_of_publication_dts': '2013-08-06T00:00:00Z'})
book.store()
book = bucket.new('4422420046', {'title_s': '世界で一番美しい元素図鑑', 'isbn_s': '4422420046', 'price_i': 4104, 'creator_s': 'セオドア・グレイ', 'date_of_publication_dts': '2010-10-22T00:00:00Z'})
book.store()
book = bucket.new('4087472221', {'title_s': '神々の山嶺〈上〉', 'isbn_s': '4087472221', 'price_i': 788, 'creator_s': '夢枕 獏', 'date_of_publication_dts': '2000-08-01T00:00:00Z'})
book.store()
book = bucket.new('408747223X', {'title_s': '神々の山嶺〈下〉', 'isbn_s': '408747223X', 'price_i': 864, 'creator_s': '夢枕 獏', 'date_of_publication_dts': '2000-08-01T00:00:00Z'})
book.store()
book = bucket.new('4163537406', {'title_s': '敵対水域', 'isbn_s': '4163537406', 'price_i': 119, 'creator_s': 'ピーター ハクソーゼン', 'date_of_publication_dts': '1998-01-01T00:00:00Z'})
book.store()
bucket.get_keys() # -> ['4422420046',
'4163537406',
'4087472221',
'408747223X',
'4621088629',
'4864102538']
results = client.fulltext_search('manifestation_index', 'title_s:神*')
for doc in results['docs']:
bucket = client.bucket_type(doc['_yz_rt']).bucket(doc['_yz_rb'])
b = bucket.get(doc['_yz_rk'])
print(b.data)
# -> {'creator_s': '夢枕 獏', 'title_s': '神々の山嶺〈上〉', 'price_i': 788, 'date_of_publication_dts': '2000-08-01T00:00:00Z', 'isbn_s': '4087472221'}
{'creator_s': '夢枕 獏', 'title_s': '神々の山嶺〈下〉', 'price_i': 864, 'date_of_publication_dts': '2000-08-01T00:00:00Z', 'isbn_s': '408747223X'}
results = client.fulltext_search('manifestation_index', 'price_i:[* TO 1000]')
for doc in results['docs']:
bucket = client.bucket_type(doc['_yz_rt']).bucket(doc['_yz_rb'])
b = bucket.get(doc['_yz_rk'])
print(b.data)
# -> {'creator_s': '夢枕 獏', 'title_s': '神々の山嶺〈上〉', 'price_i': 788, 'date_of_publication_dts': '2000-08-01T00:00:00Z', 'isbn_s': '4087472221'}
{'creator_s': '夢枕 獏', 'title_s': '神々の山嶺〈下〉', 'price_i': 864, 'date_of_publication_dts': '2000-08-01T00:00:00Z', 'isbn_s': '408747223X'}
{'creator_s': 'ピーター ハクソーゼン', 'title_s': '敵対水域', 'price_i': 119, 'date_of_publication_dts': '1998-01-01T00:00:00Z', 'isbn_s': '4163537406'}
最後に
ConflictError エラー
riak.riak_object.RiakObject であるインスタンス変数の siblings プロパティを使うとリストで複数件でてきます。この場合は、delete メソッドで削除してから再登録してみると良いです。
一括削除の方法があれば良いのですが...