LoginSignup
219
221

More than 5 years have passed since last update.

45歳以上はMongoDBを使ったシステムが使えなくなる件

Posted at

MongoDBを使うシステムが、最近多いと思います。
2.6系(安定版)の最新2.6.7ですが、Date型のインポート処理にバグがありそうです。

「1970/01/01」以前の Date型 を mongoexport すると、負の "$numberLong" として出力されるのですが、それを mongoimport すると、それ以降のフィールドが欠落してしまうのです。

例えば、ユーザマスタに「誕生日」フィールドがあると、45歳以上の人は「1970/01/01」以前の値が入っているわけで、マスタデータを移行したりでもすると、その人のフィールドがガッツリ無くなってしまいます。でも若手は大丈夫だから「どうせ部長の使い方がおかしいんでしょwww」といういつもの「偉い人に限って障害が発生する」パターンが展開されます。

大急ぎで調べた所、以下が判明しました。

2.6形式

"1965-11-17T00:00:00Z" → "$date : { $numberLong": "-130118400000" }
"2014-04-24T00:00:00Z" → "$date": "2014-04-24T09:00:00.000+0900"

2.4形式

"1965-11-17T00:00:00Z" → "$date : -130118400000
"2014-04-24T00:00:00Z" → "$date": 1398297600000

2.4系では "$numberLong" を使わないフォーマットです。また、2.6系は2.4系のエクスポートファイルであれば、正常に読み込むことができるようです。

そこで、2.6系で出力したjsonを安全に読めるように変換するコンバータを作成しました。(node.js版)
(エクスポートしたjsonを標準入力で受け取り、標準出力に吐き出す)

var fs = require('fs'),
  readline = require('readline'),
  rs = process.stdin,
  rl = readline.createInterface({'input': rs, 'output': {}});

var re1 = new RegExp(/({ "[$]date" : { "[$]numberLong" : "-[0-9]+" } })/g);
var re2 = new RegExp(/({ "[$]numberLong" : "(-[0-9]+)" })/);
rl.on('line', function (line) {
  line = line.replace(re1, function (term) {
    term = term.replace(re2, function (a, b, num) {
      return num;
    });
    return term;
  });
  console.log(line);
});
rl.resume();

使い方

$ node convert.js < エクスポート.json > 変換後エクスポート.json

これで、上司に怒られずに済みますね。

219
221
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
219
221