ことのはじまり
MongoDBにはGridFSというファイルを他のメタデータつきでまるっと格納できる機能があり、コマンドラインからもプログラムからもデータを突っ込めるというのでかなり便利に使っています
これまでNode.js上でMongooseで手軽にMongoDBのデータを出し入れしながらAPIが若干違うGridFSもエレガントに使おうという場合はgridfs-streamと組み合わせるのが定跡のように言われておりました
しかし先日昔の作りかけアプリをES6ベースな書き方になおしたい→node.jsとnpmモジュール関連を一気にバージョンアップしたところコケるアプリがチラホラとありまして
エラーメッセージを見るとアプリ本体やMongoose周りは別段問題はなさそうだったのですが、gridfs-stream関連を使っているあたりで色々出てる感じでした
調べてみるとgridfs-streamで使っているGridStore APIが最近のMongoDB Native Driverでは
どうやらGrid File System APIに移行しなさいと言っているようで
件のコケたアプリのエラーはこれだけが原因というわけでもなかったのですが、見かけたついでなので new GridFS API なるものがどんなものなのか試してみました
Grid File System API
ドキュメントを読むとNode.jsのstreams3にも対応したstreamベースのAPIらしく、今までgridfs-streamを経由してやっていたことをネイティブドライバのモジュールが素でやってくれそうな雰囲気
というわけでMongooseとの組み合わせでデータを出し入れするサンプルを書いてみました
var Mongoose = require('mongoose');
var ObjectId = Mongoose.Types.ObjectId;
var mongoose = Mongoose.connect('mongodb://localhost/something');
var Schema = {};
var Model = {};
Schema.File = new Mongoose.Schema({
filename: {type: String},
contentType: {type: String},
length: {type: Number},
md5: {type: String},
uploadDate: {type: Date},
metadata: Mongoose.Schema.Types.Mixed
}, {strict: false});
Schema.File.statics.writeStream = function(filename, options){
var bucket = new Mongoose.mongo.GridFSBucket(mongoose.connection.db);
return bucket.openUploadStream(filename, options);
};
Schema.File.methods.readStream = function(callback){
var bucket = new Mongoose.mongo.GridFSBucket(mongoose.connection.db);
return bucket.openDownloadStream(this._id);
};
Schema.File.methods.unlink = function(callback){
var bucket = new Mongoose.mongo.GridFSBucket(mongoose.connection.db);
bucket.delete(this._id, function(err){
callback(err);
});
};
Model.File = Mongoose.model('File', Schema.File, 'fs.files');
module.exports = Model;
var fs = require('fs');
var Model = require('model.js');
var readstream = fs.createReadStream('example.txt');
var writestream = Model.File.writeStream('example.txt', {
metadata: {}
});
writestream.once('finish', function(){
console.info('オワタ');
});
readstream.pipe(writestream);