MySQLにバッチファイルとかでデータ投入していく時、リレーションを張っている場合は子のテーブルには親テーブルのpkが必要になります。fkの値ですよね。
親テーブルにinsert、新たに発行されたpkの値を変数にいれて、そのまま続けて子テーブルにもinsertしていくサンプル。
久々に書こうとして「あれ?どうやって書いたっけ」って悩んでしまったのでメモしておこう。
insert into oya(body) values(‘hogehoge’);
SET @oya_id = (select last_insert_id() from oya);
insert into ko(oya_id, body) values(@oya_id, ‘ko-hogehoge’);
last_insert_id()ってMySQLだけかも。PostgreSQLとかは確か違う取得の仕方だったと。あ、もちろん各テーブルのpkになるidというカラムはAUTO INCREMENTです。
これを
mysql -u ユーザ名 DB名 < 上記クエリが書かれたファイルへのパス
って実行してやればOKかと。
ちなみにこんなテーブルです。
CREATE TABLE oya(
id int(11) unsigned NOT NULL AUTO_INCREMENT,
body varchar(255) NOT NULL DEFAULT ”,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT DEFAULT CHARSET=utf8;
CREATE TABLE ko(
id int(11) unsigned NOT NULL AUTO_INCREMENT,
oya_id int(11) unsigned NOT NULL,
body varchar(255) NOT NULL DEFAULT ”,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT DEFAULT CHARSET=utf8;

PythonからTokyo Cabinetを操作して全文検索を実装する-まずは環境構築の続き。データの投入と検索です。
#! /usr/bin/python
# -*- coding: utf-8 -*-
from tokyocabinet import table
tc = table.Table()
tc.open(‘test.tct’, table.TDBOWRITER | table.TDBOCREAT)
tc['key'] = {‘value’: ‘Hello Tokyo Cabinet’}
#トークン転置インデックスを作成
tc.setindex(‘value’, table.TDBITTOKEN)
#これは全レコードの件数
print len(tc)
#検索
q = tc.query()
q.addcond(‘value’, table.TDBQCSTRAND, ‘Tokyo’)
#ヒットした件数
print q.count()
#検索結果の出力
for item in q.search():
print item
tc.close()
インデックスの作成は毎回やる必要はないです。コードから作成するサンプルです。これでtest.tctというデータファイルとtest.tct.idx.value.tokというインデックスファイルが作成されます。
トークンは形態素解析して半角スペースでつなげたものを使いました。サンプルはその部分を割愛しましたが、「私負けましたわ」という文章を突っ込む場合には「私 負け まし た わ」となります。
相変わらずMeCabのお世話になってます。
正直パラメータとかは自信無いです。間違ってたらごめんなさい。
某QAサイトからサンプルデータをちょっとお借りして、200万件ほど投入して検索してみましたが、20ミリ秒くらいでヒット件数とレコードを取得できました。
手軽で高速。これはいろいろ活用してみたいですね。
途中まで書いて長くなりそうだったので、環境構築とコーディングの2部構成にします。まずは環境構築です。
全文検索っていっても名寄せとかしてないからただ単にSQLでいうところのLike検索とおんなじなんですけど、RDBじゃなくてKVS使うところがポイントです。
「なんでMySQLとかのRDBじゃなくてKVS?」っていうところは長くなるので割愛します。まぁcount()が遅かった、っていうだけなんですけどね。アレはチューニングでどにかなるのかなぁ。
TokyoCabinetのインストール
wget http://fallabs.com/tokyocabinet/tokyocabinet-1.4.47.tar.gz
tar zxfv tokyocabinet-1.4.47.tar.gz
cd tokyocabinet-1.4.47
./configure
make
make install
これだけ。
インストールにはいろいろ諸々必要なのですが、ハセテツの環境だとbzip2-develだけいれれば大丈夫でした。まぁ足りなければ./configureで教えてくれるでしょう。
Tokyo Tyrantは今回はインストールしません。Pythonから直接Tokyo Cabinetを叩きます。
次はPythonからTokyo Cabinetを叩くためにpython-tokyocabinetをインストールします。
pip install tokyocabinet
/etc/ld.so.conf に
/usr/local/lib
を追記して
/sbin/ldconfig
これまた簡単。’12.4月時点でバージョン0.5がインストールされます。
#! /usr/bin/python
# -*- coding: utf-8 -*-
from tokyocabinet import btree
tc = btree.BTree()
tc.open(‘test.tcb’, btree.BDBOWRITER | btree.BDBOCREAT)
tc['key'] = ‘Hello TokyoCabinet’
print tc['key']
tc.close()
上記サンプルが実行できて、「Hello TokyoCabinet」と表示されれば成功です。

InstagramやPinterestでも利用されているredisをCentOSにインストールしてみました。
現時点での最新版(2.4.10)をダウンロードして解凍、コンパイルしてインストールします。
wget http://redis.googlecode.com/files/redis-2.4.10.tar.gz
tar zxfv redis-2.4.10.tar.gz
cd redis-2.4.10
make
make install
で、セットアップ。起動スクリプトまで用意してくれます。
セットアップ中にいろいろ聞かれますが、デフォルトのままでいいと思います。
cd utils/
./install_server.sh
起動スクリプトはoffになっているはずなので、onにします。
chkconfig –list redis_6379
chkconfig redis_6379 on
で、起動しましょう。
/etc/rc.d/init.d/redis_6379 start
起動したらクライアントツールを立ちあげて、
redis-cli
redis 127.0.0.1:6379> set hoge hogehoge
OK
redis 127.0.0.1:6379> get hoge
“hogehoge”
こんな感じです。
んー、さて、何に使おう。
Pythonで集合の積を求める方法です。
_f0 = set([u'読書',u'インターネット',u'アニメ'])
_f1 = set([u'音楽',u'映画',u'アニメ'])
_a = _f0 & _f1
出力されるのは「アニメ」です。共通項ですね。
AさんとBさんの趣味を列挙して、「これとこれが一緒だから相性は云々」なんていう下世話なことが可能かもですよ。
Python2.7で使いましたが、2.5とかでもたぶん動く、と思います。

ずっとDjango使ってきたんですけど、Djangoだけじゃなくて他のフレームワークも使ってみようということで。そもそもフルスタックって便利なんですけど、もれなく使わない機能も付いてきちゃいますからね。そこがちょっと気にはなっていたんです。
まずは仮想環境の構築と、Pyramidのインストール。単純に「pip install pyramid」にしちゃうと1.3がインストールされます。今はまだ1.2の最新版を使ってみます。
virtualenv -p /usr/local/bin/python2.7 –no-site-packages sample
cd sample/
bin/easy_install pip
bin/pip install pyramid==1.2.7
で、ちらっとテンプレートをみてみます。
bin/paster create –list-templates
basic_package: A basic setuptools-enabled package
paste_deploy: A web application deployed through paste.deploy
pyramid_alchemy: pyramid SQLAlchemy project using traversal
pyramid_routesalchemy: pyramid SQLAlchemy project using url dispatch (no traversal)
pyramid_starter: pyramid starter project
pyramid_zodb: pyramid ZODB starter project
pyramid_starterを使ってプロジェクトを作ってみました。
bin/paster create -t pyramid_starter webapp
最後に必要なモジュール類をインストールしてアプリケーション起動。
cd webapp/
./../bin/pip install -e .
python setup.py develop
./../bin/paster serve development.ini
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
「どのフレームワークがより優れているか」っていう結論を出すつもりはなくて、いろいろ知っておけば選択肢が広がって、ケースバイケースで使い分けられるだろうと。
日々勉強ですわ。
以前はxml出力してクライアントでパースしたり、htmlを出力してそのまま埋め込む、っていうやり方が多かったのですが、最近はjsonを多用しています。
from django.utils import simplejson
from django.core import serializers
def index(request):
_values = simplejson.dumps([{"key0": "value0", "key1":"value1"}], ensure_ascii=False)
return HttpResponse(_values, mimetype=”application/json;charset=utf-8″)
出力するのはこれだけ。非常に簡単。
Django1.3、Python2.7です。Djangoは1.1でも動いた記憶が。Pythonは2.6以降かな。まぁ2.6以降っていってもjsonの取り扱いだけですけど。あ、Python3は知りません。
jQuery側は
$.getJSON(url, function(result, status){
alert(result[0].key0);
alert(result[0].key1);
});
これだけ。jQueryは1.6使ってます。
とっても便利なMemcachedをPythonから利用するメモ。
import memcache
_mc = memcache.Client(['localhost:11211'])
_mc.set(“key”, “value”, 90)
print _mc.get(“key”)
と、これだけ。
setした時の3番目の引数は有効期限、秒数で指定。デフォルトは0(ゼロ)で有効期限なし、ずっと消えない。最大で30日(86400秒x30日、ですね)けど、新しい値がどんどん入ってきて領域が足りなくなると古いのは消されます。ので、永遠に残るっていうわけではないです。
「Memcachedにあったらそれを使う。無ければ値を取得してMemcachedに突っ込んでおく」
っていう使い方がよいと。
ライブラリは
python-memcached
で入ります。
Python2.7、Memcached 1.4.13、python-memcach 1.48、でした。
同じフォームを複数の画面で使う場合、使う画面によって指定するcssのclassが異なるケースがあると思います。
そんな時、view側でフォームのインスタンスを生成した後でattrsを指定できると便利です。そんなサンプルです。
class EntryForm(forms.Form):
body = forms.CharField(widget=forms.Textarea())
こんなフォームがあったとして、viewで使うときには
_form = EntryForm()
_form.fields['body'].widget.attrs['class'] = ‘some_css_class’
です。これで
<textarea id=”id_body” rows=”10″ cols=”40″ name=”body” class=”some_css_class”></textarea>
こんな感じのHTMLが出力されます。
_form.fields['body'].widget.attrs['disabled'] = True
とかもできるので、シチュエーションによって使い分けられると思います。
Django1.3で試しましたが、1.0以降なら動くんじゃないかな?
python_selectを使って複数バージョンのPythonを使い分ける
の続きなんですけど、MacPortsでPython3.2をインストールしてみました。virtualenv使えよ、っていう指摘はごもっとも。
sudo port install python32
まぁこれだけなんですけどね。今日の時点では3.2.1が入りました。あとはpython_selectで使い分けるだけ。
もうちっとディスク容量があれば環境毎にVM作って使い分けるんだけど、Air買うときにケチって120GBしか積まなかったから贅沢できない…。