昨日の休日練習で試した node-csv-parser ( http://qiita.com/items/b8137a66ca35e1b6a729 ) がうまくいったのに気をよくして(^^)v、、、
今日は業務で使ってたSQLite3の旧データベースをMongoDBへさくっと引っ越してみました。
SQLite3のデータをダンプ
まず、旧データベース側のデータを全部出力してみます。
$ sqlite3 hoge.db
sqlite> .output 20120909.dump
sqlite> .dump
これで20120909.dumpというテキストデータが出来上がります。こんなの。
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE hoge (
ctime INTEGER NOT NULL,
date TEXT NOT NULL,
eventName TEXT,
type TEXT,
status TEXT,
clientId TEXT
);
INSERT INTO "hoge" VALUES(1343096611063,'da.2012.7.22','event127878','hoge','tyu','157183_1343096648191');
INSERT INTO "hoge" VALUES(1343096624381,'da.2012.7.22','event129600','hoge','tyu','157183_1343096648191');
INSERT INTO "hoge" VALUES(1343096625820,'da.2012.7.22','event129600','hoge','zumi','157183_1343096648191');
(略)
INSERT INTO "hoge" VALUES(1347159497371,'da.2012.9.9','event138761','hoge','tyu','375533_1347147506930');
CREATE INDEX date ON hoge (date COLLATE NOCASE);
COMMIT;
要するにSQL文がずらずら書かれているやつ。
これを実行すればCREATE TABLE文でテーブルが再構築されて、そこへINSERT文でデータをズンズン入れていけば、リストアできちゃうというわかりやすいバックアップ。
で、同じタイプのDB、つまりSQLite3へ入れるならこれで復元すれば良いのだけれど、今回はこれをMongoDBへ放り込もうという物語。
データ量は数千件程度と少ないので考え考え手作業しながらやてまう。
サイボウズの日付スタイル'da.2012.7.22'とかイベントの書き方'event127878'を流用してることに気付いたあなたはサイボーザー?まぁ、サンプルデータなのでアバウトですけど、このサンプルなど( http://jsgt.org/sb/ws/test.htm )で使ってるやつでサイボウズを四苦ハックしての運用版です。
Mongoのスキーマを決める
スキーマレスなのにスキーマとは、、、という無駄な?ことは考えず、マングース様の言うとおりMongoのスキーマを考えておく。
こんな感じ。
// スキーマ
var hogeSchema = {
ctime : { type: Number, default: Date.now } //サーバーへの登録時
,date : { type: String, required: true, index: true} //スケジュールの日付
,eventName : { type: String} //イベントID
,type : { type: String, required: true } //メッセージのタイプ
,status : { type: String } //メッセージステータス
,clientId : { type: String } //クライアントID
};
新しいデータのサンプル
データサンプルで見るとこんな感じになります。SQLite3の各カラムをJavaScriptのオブジェクトにして放り込もうという作戦。
データサンプル {
ctime : 1342322851988
,date : "da.2012.7.15"
,eventName : "event125197"
,type : "hoge"
,status : "zumi"
,clientId : "609369_1342319334920"
}
作戦会議
さて、上のSQLite3のデータをどうやってMongoへ放り込むと簡単でしょう?
はいっ。テキストデータをnode-csvで読み込んでマングースへ食わせる手がありますっ。
採用っ。
準備
上のデータのSQL文をそぎ落とし、ダブルクオートにしてCSVぽくしてみます。
1343096611063,"da.2012.7.22","event127878","hoge","tyu","157183_1343096648191"
1343096624381,"da.2012.7.22","event129600","hoge","tyu","157183_1343096648191"
1343096625820,"da.2012.7.22","event129600","hoge","zumi","157183_1343096648191"
(略)
1347159497371,"da.2012.9.9","event138761","hoge","tyu","375533_1347147506930"
とりあえず、これを20120909.txtとか名前を付けて保存します
さて、一気にやります。
//CSV perser
var csv = require('csv');
//入力データ
var infile = __dirname+'/20120909.txt';
// マングース降臨
var mongoose = require('mongoose');
// スキーマ
var UketukeSchema = {
ctime : { type: Number, default: Date.now } //サーバーへの登録時
,date : { type: String, required: true, index: true} //スケジュールの日付
,eventName : { type: String} //イベントID
,type : { type: String, required: true } //メッセージのタイプ
,status : { type: String } //メッセージステータス
,clientId : { type: String } //クライアントID
};
// DB接続
var conn = mongoose.createConnection('mongodb://localhost/hoge');
// スキーマ定義
var schema = new mongoose.Schema(UketukeSchema);
// モデル定義
var model = conn.model('Uketuke', schema);
//全削除してから、、、
delAll (function(){})
//全インストール
csv2mongo(infile);
// 全データ削除
function delAll (callback) {
var U = new model();
model
.find({})
.remove()
U.save(function(err) {
if (err) { console.log(err); }
else callback(U);
});
}
// データ挿入
function insert (data, callback) {
var ins = new model();
//ins.ctime = data.ctime; //nowを入れるなら不要
ins.date = data.date;
ins.eventName = data.eventName;
ins.type = data.type;
ins.status = data.status;
ins.clientId = data.clientId;
ins.save(function(err) {
if (err) { console.log('/////////////////////////'+err); }
else callback(data, ins);
});
}
//CSVをマングースへ食わせろっ
function csv2mongo(infile){
csv()
.fromPath(infile) //読み込むCSVファイル
.transform(function(data){
var data ={
ctime : data[0] //データの対応注意
,date : data[1]
,eventName : data[2]
,type : data[3]
,status : data[4]
,clientId : data[5]
};
//DBへ記録
insert(data,
function(data, ins){
console.log('==inserted');
}
);
console.log(data);
return data;
})
.on('data',function(data){
console.log(data);
})
.on('end',function(count){
console.log('Number of lines: '+count);
})
.on('error',function(error){
console.log(error.message);
})
}
実行
node csv2mong.js
出来上がり。
ちなみに、実際にはうちではMongoのレプリカントさんなので、マングースは3匹こんな感じで接続してます。(参考: http://qiita.com/items/b5e99bf4923b84b2bb40 )
//レプリカリスト
var ReplicaSets = ''
+ 'mongodb://192.168.1.11:27020/hoge,'
+ 'mongodb://192.168.1.12:27020/hoge,'
+ 'mongodb://192.168.1.13:27020/hoge,'
// DB接続
var conn = mongoose.connectSet(ReplicaSets);