概要
画像データをbase64でエンコードされた文字列として保存することはできますが、Mongoにあるものを表示すると、保存した元の文字列は、永続化された最後の文字列の前半程度しかありません. このため、クエリは機能しません。
詳細
次のスキーマを検討してください。
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var imageSchema = new Schema({
mime: String,
bin: String,
uses : [{type: Schema.Types.ObjectId}]
});
module.exports = mongoose.model('Image', imageSchema);
フィールドでは、bin
base64 の画像データを保存しています。そのため、この文字列は潜在的に大きくなる可能性があります (ただし、このテストは、約 40k しかない場合にも失敗します)。
アップデート
さらに分析を行ったところ、この更新されたテスト ブロックは、私が見ている結果をよりよく示しています。
var buffer = getImageFromFileSystem();
var bin = buffer.toString('base64');
var i = new Image({
mime : 'image/jpeg',
bin : bin
});
i.save(function(err, image){
if (err)
console.log(err);
console.log("=== original? "+(image.bin === bin)); //outputs true
console.log("now find it by id and then compare again")
Image.findOne({
_id : image._id
}, function(err, img) {
if (err)
console.log('crap error');
if (img) {
console.log('found one!: '+img.id+', lets compare... ');
console.log("===? "+(img.bin === bin)); //outputs true again!
}
});
//OK so clearly all is well, so let search by the bin str
Image.findOne({
bin : bin
}, function(err, img) {
if (err)
console.log('crap error');
if (!img) {
console.log("none found") // we hit this... what the heck???
});
そこで、データベースでbin
値を調べることにしました。 ここで、その値が、bin
保存した元の文字列に加えて、その末尾に追加された少なくとも 2 倍の文字数であることがわかります。したがって、元の base64 文字列は、MongoDB に格納されている値の先頭にある部分文字列です。したがってfindOne({bin:myBinValue})
、比較はMongo内で行われるため、これを行うと機能しません。ただし、bin
Mongo から値を取得して比較すると、元の値に戻ったように見え、アプリケーションでは javasript の比較は同じです! 何を与える!? このフィールドにはインデックスがありません。
> db.images.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "mydb.images",
"name" : "_id_"
}
]