Node.js
MongoDB
mongoose

MongoDBの新しいGridFS APIを使ってみる

More than 1 year has passed since last update.


ことのはじまり

MongoDBにはGridFSというファイルを他のメタデータつきでまるっと格納できる機能があり、コマンドラインからもプログラムからもデータを突っ込めるというのでかなり便利に使っています

これまでNode.js上でMongooseで手軽にMongoDBのデータを出し入れしながらAPIが若干違うGridFSもエレガントに使おうという場合はgridfs-streamと組み合わせるのが定跡のように言われておりました

しかし先日昔の作りかけアプリをES6ベースな書き方になおしたい→node.jsとnpmモジュール関連を一気にバージョンアップしたところコケるアプリがチラホラとありまして

エラーメッセージを見るとアプリ本体やMongoose周りは別段問題はなさそうだったのですが、gridfs-stream関連を使っているあたりで色々出てる感じでした

調べてみるとgridfs-streamで使っているGridStore APIが最近のMongoDB Native Driverでは

The GridStore API is deprecated

どうやらGrid File System APIに移行しなさいと言っているようで

件のコケたアプリのエラーはこれだけが原因というわけでもなかったのですが、見かけたついでなので new GridFS API なるものがどんなものなのか試してみました


Grid File System API

ドキュメントを読むとNode.jsのstreams3にも対応したstreamベースのAPIらしく、今までgridfs-streamを経由してやっていたことをネイティブドライバのモジュールが素でやってくれそうな雰囲気

というわけでMongooseとの組み合わせでデータを出し入れするサンプルを書いてみました


model.js

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;



writer.js

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);