NodeJS-Mongo: Querying the database and gridfs and returning both the document and the image to the user

I am trying to build a application with nodejs,express and mongodb. I am storing images using GRIDfs. I am able to retrieve the document and image separately.

How can I query both the mongo database and the gridfs and return both the document and image as a response to user?

This is my code ->

wines.js

var mongo = require('mongodb') ;

var Server = mongo.Server,
    Db=mongo.Db,
    BSON=mongo.BSONPure,
    fs = require('fs'),
    Binary=mongo.Binary,
    GridStore=mongo.GridStore,
    Code=mongo.Code,
    ObjectID=mongo.ObjectID,
    assert=require('assert'); 

 var buffer = "";

var Grid = require('gridfs-stream');
var server = new Server('localhost',27017,{auto_reconnect:true});

db = new Db('winedb',server) ; 

db.open(function(err,db){
    if(!err){
        console.log("Connected to 'wine.db' database") ; 
        db.collection('wines',{strict:true},function(err,collection){
               if(err){
                    console.log("The 'wines' collection doesn't exist creating it") ;
                    populateDB() ;  
               }

        });




}

});





exports.findById = function(req,res){
    var id = req.params.id ;
    console.log('Retrieving wine:'+id) ; 
    db.collection('wines',function(err,collection){
            collection.find({'_id':new BSON.ObjectID(id)}).toArray(function(err,items){ 

           res.writeHead(200,{'Content-Type':'application/json'});    
           res.writeContinue(items) ;
           res.addTrailers({'Content-Type':'image/jpeg'}); 

           var gfs = Grid(db,mongo);


    try {


        var readstream = gfs.createReadStream({'_id':ObjectID(items[0].image_id)});

        readstream.pipe(res);
        console.log("sending image") ; 



} catch (err) {
    console.log(err);
    console.log("File not found.");
} 
        });



});


}    


var populateDB = function(){

    var wines = [
        {
        name: "CHATEAU DE SAINT COSME",
        year: "2009",
        grapes: "Grenache / Syrah",
        country: "France",
        region: "Southern Rhone",
        description: "The aromas of fruit and spice...",
        picture: "saint_cosme.jpg"
    },
    {
        name: "LAN RIOJA CRIANZA",
        year: "2006",
        grapes: "Tempranillo",
        country: "Spain",
        region: "Rioja",
        description: "A resurgence of interest in boutique vineyards...",
        picture: "lan_rioja.jpg"
    }];


    db.collection('wines',function(err,collection){
            collection.insert(wines,{safe:true },function(err,result){});
    });

       var gfs = Grid(db,mongo);
       var fileId = new ObjectID();

         var writestream = gfs.createWriteStream({
            filename:'white',
            mode:'w',
            contentType:'image/png',
            _id:fileId,
         });

         fs.createReadStream('./images/white.jpg').pipe(writestream);

            db.collection('wines',function(err,collection){
                 collection.update({year:'2009'},{$set:{image_id:fileId}},{safe:true},function(err,result){

                if(err){
                    console.log('Error updating wine:'+err) ;
                }
                else{
                    console.log(''+result+'document(s) updated') ; 

                }
            }
    )}
);






};

server.js

var express = require('express')  , 
wines = require('./routes/wines'); 

var Grid = require('gridfs-stream')  ; 
var app = express(); 

app.configure(function(){
    app.use(express.logger('dev'));
    app.use(express.bodyParser()); 
}) ; 
app.get('/wines',wines.findAll); 

app.get('/wines/:id',wines.findById);

app.post('/wines',wines.addWine) ; 

app.put('/wines/:id',wines.updateWine); 

app.delete('/wines/:id',wines.deleteWine) ; 

app.get('/image/:id',wines.display); 

app.listen(3000) ; 
console.log('Listening on port 3000') ; 

Alternatively you can store your image in S3. Get the url. Store that URL into your BSON document. When u send the response, the client-side will request the image url and display the url.

This is ofcourse if you are considering only sending the image for display. If you need the image for processing and need to send it between systems, you can convert the image into base64 string and add it as a field into your BSON document. However there if the image size is huge if may cause traffic for multiple requests.

You can also use Kraken.IO to optimize your images.