TokyoCabinet::TDBの検索について その2

昨日TokyoCabinet::TDB(テーブルデータベース)の検索クエリまとめと参照したページまとめ - 深く、広く、高くの続き。

検索結果を受けてデータベースを更新する

参考:mixi engineer blog
検索条件を設定したTDBQRYオブジェクトでprocを使う。procの返り値で動作が決定されるので、ブロックの最後に必ず

  • TDBQRY::QPPUT(そのレコードを更新)
  • TDBQRY::QPOUT(そのレコードを削除)
  • 0(何もしない)

を書いておく。
ただ、ドキュメンテーションの中では見つけられなかったけど、このprocは新規作成か書き込みモード(TDB::OWRITER | TDB::OCREAT)でデータベースを開いたときにしか使えない様子。(たとえ0(何もしない)を指定しても)

#TDBを開く
db.put("1",{"lang"=>"ruby,c++,perl,c",
		"age"=>40,
		"area"=>"kanto"})
db.put("2",{"lang"=>"perl,c,python,micon",
		"age"=>32,
		"area"=>"kansai"})
db.put("3",{"lang"=>"c++,perl,python",
		"age"=>24,
		"area"=>"kanto"})
db.put("4",{"lang"=>"c,micon",
		"age"=>19,
		"area"=>"kansai"})
#langにmiconを含み、ageが30以下ならば、areaをtohokuに変更する
qry = TDBQRY::new(db)
qry.addcond("lang", TDBQRY::QCSTRAND,"micon")
qry.addcond("age", TDBQRY::QCNUMLE, 30)
qry.proc{|pkey, cols|
	cols["area"] = "tohoku"
	TDBQRY::QPPUT
}#=>db["4"]["area"]が"tohoku"に変更されている
#TDBを閉じる

メタ検索

参考:mixi engineer blog
分かりやすい事例としては、いくつかの検索結果の和集合を得たい時に。これは実際すごい便利。この辺のパワフルさがTokyoCabinetの魅力。後はうっすいうっすいラッパーを書けば大概のことは出来てしまう。

#データは上と同じ
#ageが30以下であるか、langにpythonを含む集合を得たい
qry1 = TDBQRY::new(db)
qry1.addcond("age", TDBQRY::QCNUMLE, 30)
qry2 = TDBQRY::new(db)
qry2.addcond("lang", TDBQRY::QCSTRAND,"python")
result = qry1.metasearch([qry2], TDBQRY::MSUNION)
p result #=> ["3", "4", "2"]

self.metaserchはTDBQRYオブジェクトの配列と、メタ検索のtypeを引数として取る。typeは全部で3種類で。

  • TDBQRY::MSUNION・・・検索結果のどれかに含まれるprimary keys(和集合)
  • TDBQRY::MSISECT・・・検索結果全てに含まれるprimary keys(積集合)
  • TDBQRY::MSDIFF・・・selfの検索結果に含まれていて、引数のTDBQRYオブジェクトのいずれにも含まれないprimary keys(差集合)

第2引数は省略できて、その時はTDBQRY::MSUNIONを指定したものとみなされる。
詳しくはClass: TokyoCabinet::TDBQRY [Tokyo Cabinet]