0

概要

画像データを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);

フィールドでは、binbase64 の画像データを保存しています。そのため、この文字列は潜在的に大きくなる可能性があります (ただし、このテストは、約 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内で行われるため、これを行うと機能しません。ただし、binMongo から値を取得して比較すると、元の値に戻ったように見え、アプリケーションでは javasript の比較は同じです! 何を与える!? このフィールドにはインデックスがありません。

> db.images.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "ns" : "mydb.images",
                "name" : "_id_"
        }
]
4

0 に答える 0