これ、SQLiteとかkey-value strage(いじったことないけど)にすべき規模かも…。
ってことで、yagさんにもらった、
- 論文1のPMID, 論文1の参考文献1のPMID, 論文1の参考文献2のPMID…
- …
形式のCSVを
- 論文1のPMID, 論文1の参考文献1のPMID
- 論文1のPMID, 論文1の参考文献2のPMID
- …
のペアに書き下して、これを1レコードとしたSQLite形式のDBファイルに書き込んでいくRubyスクリプトを書いた。
(なんだか、なんだかんだで、だいぶRubyになれてきてしまったのだけど…。ぼくRubyよりはむしろPerlを勉強したいとかって、こないだうちいってたのになあ…。)
ちなみに、コメントアウトしてあるあたりをいじると、csv-csv変換器みたいにもなるはず。はじめは、csvをphpMyAdminに喰わせてMySQLに何とかしようかと思ってたんだけど、よく考えたら、二度手間だし。そこまで手間をかける意味、あんまりないかなとか思って、結局いきなりSQLiteにしてみた。
(まだ、じつは動いている途中なので、どこまでまともに動くのかわかんないんだけどね。)
#!/usr/bin/env ruby ### # とりあえず、前処理したcsvから、sqliteの「id,pmid,citedpmid」というような形式のレコードが # いっぱいはいったDBを生成するのをめざす # 最終的にはxmlから差分を直接読み込みたい ### require 'csv' require 'rubygems' require 'sqlite3' CSV.open("medline.csv", 'r') #f = open("med-k-v.csv","a") db = SQLite3::Database.new("medline.db") unless(db.execute("SELECT tbl_name FROM sqlite_master WHERE type == 'table'").flatten.include?("papers")) sql = "create table papers ( id INTEGER PRIMARY KEY AUTOINCREMENT, pmid INTEGER NOT NULL, cited_pmid INTEGER DEFAULT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP );" db.execute(sql) end CSV.open("medline.csv", 'r') do |row| pmid=row.shift puts "##"+row.join(", ") sql = "insert into papers (pmid,cited_pmid) values (:pmid,:cited_pmid);" db.transaction do row.each do |col| #f.puts pmid + ", " + col new_item = {:pmid => pmid, :cited_pmid => col} db.execute(sql,new_item) end end end #f.close db.close puts "end"
と、まあそれだけなんだけど。はい。
db.execute("SELECT tbl_name FROM sqlite_master WHERE type == 'table'").flatten.include?("address_book")テーブルが既に存在すれば true が、しなければ false が返ってくる。
トランザクション
ブロックを与えた場合、終了した時点でコミットする。db.transaction do sql = "insert into 社員 values (?, ?, ?)" db.execute(sql, '橋本', 26, '広報部') db.execute(sql, '小泉', 35, '営業部') db.execute(sql, '亀井', 40, '営業部') end
参考:
- Ruby Reference Manual
- SQLite を Ruby で使う - RubyCocoa メモ
- rubyでsqliteを使う方法 - ぴょぴょぴょ? - Linuxとかプログラミングの覚え書き -
- SQLite/Rubyの使い方 - Hacking My Way 〜 itogのhack日記: うえの書き方だとUTCになるので、JSTがいい場合は…。
ってここにかいたら、やぐさんの手持ちに、ペアの形式のデータあったと教えて下さいました…。
で、それはそれとして、どうも重複がある。どうしよう。いまDBの重複してない部分だけを新しいテーブルにいれる(はず)のクエリを投げてみたんだけど、また、これが時間かかりそうで…。