Search code examples
javascriptnode.jsexpressmongoosemongoose-populate

Is it possible to convert a buffer to base64string in populate mongoose?


I have a mongoose Image Schema as below:

const ImageSchema = new mongoose.Schema({
    img:
    {
        data: Buffer,
        contentType: String
    }
})

mongoose.model('Image',ImageSchema)

and a Chapter schema

const chapterSchema = new mongoose.Schema({
        chapter_no:{ type: Number, min: 0, max: 50 },
        published:Boolean,
        u_img:{type:mongoose.Schema.Types.ObjectId, ref:"Image"}
        
})
mongoose.model('Chapter', chapterSchema)

I'll do population for the image

Chapter.find()
    .populate({
        path:"u_img",
        select:["img"]
    })

    .exec(function(err,chapters){
        if(err) res.send(err)
        res.send(chapters)
    })

and I'm trying to convert the buffer to base64string for every single image in the chapter. Could anyone please help me? is there a way to do conversion on populate function in mongoose? or I have to map and doing conversion inside the exec func? or is there another way?


Solution

  • Well, populate area of concern is more about stitching related documents (in your case images for a given chapter) together than massaging those documents into some usable state.

    Still, there's an option you might find helpful (introduced in Mongoose 5.12):

    [options.transform=null] «Function» Function that Mongoose will call on every populated document that allows you to transform the populated document.

    So you can modify your query like this:

    Chapter.find()
      .populate({
        path:"u_img",
        select:["img"],
        options: {
          transform: doc => new Buffer(doc.data).toString('base64')
        }
      })
    

    As alternative, you can do this transformation of stitched entities in your exec function, like this:

    .exec(function(err, chapters){
      if(err) res.send(err)
      chapters.forEach(chapter => { 
        chapter.img = new Buffer(chapter.img.data).toString('base64');
      });
      res.send(chapters)
    })
    

    ... basically following the receipt given here.