Chris Wilson
Chris Wilson

Reputation: 135

why cant i delete gfs.files with an ObjectId?

This has been getting me all day. I can find the actual file with it's _id using gfs.exist(), but then when i run to the next line of code i get an error everytime and the mongoose connection crashes. This seems so simple yet nothing has worked so far.

my code:

/**
 * Created by foolishklown on 10/2/2016.
 */

var Grid = require('gridfs-stream'),
    User = require('../../models/user'),
    mongoose = require('mongoose');


module.exports = function(id, ref, type, res) {
    console.log(ref.green);
    Grid.mongo = mongoose.mongo;

    var conn = mongoose.createConnection('mongodb://localhost/media');
    conn.once('open', function () {
        var gfs = Grid(conn.db);
        gfs.exist({_id: ref}, function(err, found) {
            if(err) {
                console.error('error finding file'.red);
            } else {
                console.info('found file', found);
                gfs.files.remove({_id: ref  }, function(err) {
                    if(err) {
                        console.error('error removing that file');
                        process.exit(1);
                    } else {
                        console.info('removed file: ', found.green);
                        deleteFromUserDb(id, type, ref);
                        res.status(200).send({id: id, type: type, ref: ref});
                    }
                });
            }
        });
    });
    conn.close();

    function deleteFromUserDb(userId, fileType, refId) {
        var userConn = mongoose.createConnection('mongodb://localhost/mean-auth', (error) => {
            if(error) {
                console.error('Error connecting to the mean-auth instance'.red);
                process.exit(1);
            } else {
                User.findById(userId, (err, doc) => {
                    if(err) {
                        console.error('Error finding user with id: ', uid);
                        process.exit(1);
                    } else {
                        console.log('original doc: ', doc);
                        doc.removeMedia(fileType, refId);
                        doc.save();
                        console.log('new doc: ', doc);
                    }
                })
            }
        });
    }
};

i have tried using gfs.files.remove({_id: ref}, function(.....) to no avail

i have also tried using gfs.files.remove({_id: ref}, {_id: 1}, function(....)

i have also tried both of the above using gfs.remove() without gfs.files.remove.....

it must be something simple but its been beating me up all day... thanks

new edit 10/15.......... i am now trying to use just the native mongodb driver. I can find the file both with the string, and casting it to an objectId. It seems like the operation completes no problem, but when i use the shell to see if the file has been deleted it still exists in both fs.files and fs.chunks. This one is killing me!

deleteFile: function(userId, fileType, objId, res) {
        var ObjectId = require('mongodb');
        var client = mongodb.MongoClient;
        var _id = new ObjectId(objId);


        client.connect(mediaUri, (err, db) => {
            assert.equal(null, err);
            db.collection('fs.files').find({_id: _id}, (err, doc) => {
                if(err) {
                    console.error('error finding that document in files collection'.red);
                } else {
                    console.info('found the document: ', doc);
                    console.info('the document type is: ', typeof(doc));
                }
            });
            db.collection('fs.chunks').find({_id: _id   }, (err, doc) => {
                if(err) {
                    console.error('error finding that document in the chunks collection'.red);
                } else {
                    console.info('found the document(s): ', doc);
                    console.info('the document type is: ', typeof(doc));
                }
            });

            db.collection('fs.files').deleteOne({_id: _id}, (err, doc) => {
                console.log('document returned for deletion is: ', doc);
            });
            db.collection('fs.chunks').deleteOne({_id: _id}, (err, doc) => {
                console.log('documents deleted: ', doc);
                res.status(200).send({id: userId, type: fileType, ref: objId});
            });
            db.close();
        })
    }

Upvotes: 1

Views: 2351

Answers (2)

calumj_dev
calumj_dev

Reputation: 25

If you import the ObjectId object as follows:

const ObjectId = mongoose.Types.ObjectId;

at the top of your file as with a normal import, you can write the delete as follows:

const mongoose = require('mongoose');
const Grid = require('gridfs-stream');
const ObjectId = mongoose.Types.ObjectId
Grid.mongo = mongoose.mongo // assign the mongo driver to the Grid

const mongooseURI = 'mongodb://localhost/media';
const conn = mongoose.createConnection(mongooseURI, {useNewUrlParser:true});

conn.once('open', () => {
        const gfs = Grid(conn.db);
        gfs.exist({_id: ref}, (err, found) => {
            if(err) {
                console.error('error finding file'.red);
            } else {
                console.info('found file', found);
                gfs.files.deleteOne({_id:new ObjectId(ref)}, (err, result) => {
                    if(err) {
                        console.error('error removing that file');
                        process.exit(1);
                    } else {
                        console.info('removed file: ', found.green);
                        deleteFromUserDb(id, type, ref);
                        res.status(200).send({id: id, type: type, ref: ref});
                    }
                });
            }
        });

Hope this helps!

Upvotes: 0

Chris Wilson
Chris Wilson

Reputation: 135

i was doing the cast wrong, and using the wrong methods. After using a new constructor for mongodb.ObjectID() instead of mongodb.ObjectiD(), i had some success, plus i was calling on a few of the wrong methods. I consulted the documentation and straightened things out.

My final code for CRUD operations is:

/**
 * Created by foolishklown on 10/13/2016.
 */
var assert = require('assert'),
    path = require('path'),
    Grid = require('gridfs-stream'),
    fs = require('fs'),
    mongodb = require('mongodb'),
    mongoose = require('mongoose'),
    User = require('../../models/user'),
    mediaUri = 'mongodb://localhost/media',
    userUri = 'mongodb://localhost/mean-auth';

module.exports = {


    writeFile: function (file, userId, fileType, fileInfo, res) {
        var fileId;
        var fileTitle = file.originalFilename;
        var conn = mongoose.createConnection('mongodb://localhost/media', (error) => {
            if (error) {
                console.error('Error connecting to mongod media instance'.red);
                process.exit(1);
            } else {
                console.info('Connected successfully to mongod media instance in the write file!'.blue);
            }
        });
        // The following line is designating a file to grab/read, and save into mongo
        //  in our case it will be something from ng-file-upload that the user wants to upload
        var myFile = file.path;

        // Connect gridFs and mongo
        Grid.mongo = mongoose.mongo;

        conn.once('open', function () {
            console.log('connection open, ready for I/O!');
            var gfs = Grid(conn.db);

            // This write stream is how well write to mongo
            var writeStream = gfs.createWriteStream({
                // Name the file the way you want it stored in mongo
                filename: file.originalFilename,
                type: fileType,
                info: fileInfo
            });

            // Create a read stream, so that we can read its data, and then with that well use the
            //  write stream to write to the DB via piping the writestream
            var readStream = fs.createReadStream(myFile)
                .on('end', () => {
                    writeToUserDb(userId, fileType, readStream.id, fileInfo, fileTitle);
                    res.status(200).send(
                        {
                            ref: readStream.id,
                            type: fileType,
                            user: userId,
                            mediaInfo: fileInfo,
                            title: fileTitle
                        }
                    );
                })
                .on('error', () => {
                    res.status(500).send('error in writing with gridfs');
                })
                .pipe(writeStream);
            writeStream.on('close', function (file) {
                console.log(file.filename + 'written to DB');
                fs.unlink(myFile);
                myFile = null;
                conn.close();
            });
        });

        function writeToUserDb(uid, type, fileId, authInfo, title) {
            console.info('called to write to user db without a \'this\' reference');
            var userConn = mongoose.createConnection('mongodb://localhost/mean-auth', (error) => {
                if (error) {
                    console.error('Error connecting to the mean-auth instance'.red);
                    process.exit(1);
                } else {
                    User.findById(uid, (err, doc) => {
                        if (err) {
                            console.error('Error finding user with id: ', uid);
                            process.exit(1);
                        } else {
                            console.log('original doc: ', doc);
                            doc.addMedia(type, fileId, authInfo, title);
                            doc.save();
                            console.log('new doc: ', doc);
                        }
                    })
                }
            });
            userConn.close();
        }
    },

    downloadFile: function (userId, file, fileType, objId, location, res) {
        console.info('called to download file');
        var id = new mongodb.ObjectID(objId);
        var conn = mongoose.createConnection(mediaUri, (error) => {
            assert.ifError(error);

            var gfs = Grid(conn.db, mongoose.mongo);

            gfs.findOne({_id: id}, (err, result) => {
                if (err) {
                    res.status(400).send(err);
                } else if (!result) {
                    res.status(404).send('Error finding file')
                } else {
                    res.set('Content-Type', result.contentType);
                    res.set('Content-Disposition', 'attachment; filename="' + result.filename + '"');
                    var readStream = gfs.createReadStream({
                        _id: id,
                        root: 'resume'
                    });
                    readStream.on('error', (err) => {
                        res.end();
                    });
                    readStream.pipe(res);
                }
            });
        });
        conn.close();
    },

    deleteFile: function (userId, fileType, objId, res) {
        var client = mongodb.MongoClient;
        var id = new mongodb.ObjectID(objId);

        console.log('object id to find is: ', id);
        client.connect('mongodb://localhost/media', (err, db) => {
            db.collection('fs.files', {}, (err, files) => {
                files.remove({_id: id}, (err, result) => {
                    if (err) {
                        console.log(err);
                        res.status(500);
                    }
                    console.log(result);
                });
            });
            db.collection('fs.chunks', {}, (err, chunks) => {
                chunks.removeMany({files_id: id}, (err, result) => {
                    if (err) {
                        console.log(err);
                        res.status(500);
                    }
                    console.log(result);
                });
            });
            db.close();
        });
        res.status(200).send({id: userId, type: fileType, ref: id});
    },

    getAll: function (req, res) {
        var uid = req.query.id;
        var conn = mongoose.createConnection('mongodb://localhost/mean-auth', (err) => {
            if (err) {
                console.error('Error connecting to mean-auth instance to read all');
                process.exit(1);
            } else {
                User.findById(uid, (err, doc) => {
                    if (err) {
                        console.error('Error finding user with id: ', uid);
                        process.exit(1);
                    } else {
                        if (doc) {
                            console.log('original doc: ', doc);
                            res.status(200).send({media: doc.media});
                        } else {
                            res.status(200);
                        }
                    }
                })
            }
        });
    }
};

Upvotes: 1

Related Questions