Mongoose: Model.remove([]).exec() deletes ALL records from collection instead of none.

Created on 5 Jun 2017  路  7Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?
bug

What is the current behavior?
Passing an empty array to remove api drops all records from collection

If the current behavior is a bug, please provide the steps to reproduce.

Model.remove([]).exec()

What is the expected behavior?
No records should be deleted.

Please mention your node.js, mongoose and MongoDB version.

Nodejs 4.7.4
MongoDB 3.4.x (Wired Tiger)
Mongoose 4.8

discussion enhancement

Most helpful comment

oof, my guess is mongoose is treating the [] the same as {} as thats how you can remove all your documents in the collection, i.e. Model.remove({})

Do you think [] and {} should be treated separately, or are you saying you would like for {} to also be treated as remove none instead of remove all:

const mongoose = require('mongoose');
const co = require('co');
mongoose.Promise = global.Promise;
const GITHUB_ISSUE = `gh-5323`;


exec()
  .then(() => {
    console.log('successfully ran program');
    process.exit(0);
  })
  .catch(error => {
    console.error(`Error: ${ error }\n${ error.stack }`);
  });


function exec() {
  return co(function*() {
    const db = mongoose.createConnection(`mongodb://localhost:27017/${ GITHUB_ISSUE }`)
    const schema = new mongoose.Schema({
      name: String
    });

    const Model = db.model('Model', schema);

    yield Model.remove({});

    yield Model.create([
      { name: 'test-1' },
      { name: 'test-2' }
    ]);

    yield Model.remove([]); // removes all docs
    // yield Model.remove({}); // removes all docs

    console.log(yield Model.find());
  });
}

All 7 comments

yeah, this a bit annoying

oof, my guess is mongoose is treating the [] the same as {} as thats how you can remove all your documents in the collection, i.e. Model.remove({})

Do you think [] and {} should be treated separately, or are you saying you would like for {} to also be treated as remove none instead of remove all:

const mongoose = require('mongoose');
const co = require('co');
mongoose.Promise = global.Promise;
const GITHUB_ISSUE = `gh-5323`;


exec()
  .then(() => {
    console.log('successfully ran program');
    process.exit(0);
  })
  .catch(error => {
    console.error(`Error: ${ error }\n${ error.stack }`);
  });


function exec() {
  return co(function*() {
    const db = mongoose.createConnection(`mongodb://localhost:27017/${ GITHUB_ISSUE }`)
    const schema = new mongoose.Schema({
      name: String
    });

    const Model = db.model('Model', schema);

    yield Model.remove({});

    yield Model.create([
      { name: 'test-1' },
      { name: 'test-2' }
    ]);

    yield Model.remove([]); // removes all docs
    // yield Model.remove({}); // removes all docs

    console.log(yield Model.find());
  });
}

Thanks

Hey, I have got similar problem. I am trying to remove just one document but instead mongoose is deleting all documents in collection. Does anyne know how to sort this out?

deleteAccount: async (req, res, next) => {
    try {
      const { id } = req.body

      const user = await User.findOne({ id })

      if (!user) {
        return res.status(400).json({ error: 'User does not exists' })
      }

      if (process.env.NODE_ENV !== 'test') {
        nodemailerConfig.sendEmail('[email protected]', user.local.email, 'Pomy艣lne usuni臋cie konta - Yes Chef', accountDeletedEmailTemplate)
      }

      User.remove({ id }).exec()

      res.status(200).json({ authentication: 'Account deleted successfully' })
    } catch (error) {
      next(error, error.message)
    }
  }

@Rachomir just use User.deleteOne({ id }) to ensure at most one doc is deleted

@vkarpov15 But then it will not run .pre("remove") hook. Right ?
https://mongoosejs.com/docs/api.html#model_Model.deleteOne

Its actually bad. I think .remove should have option to add something like - {justOne: true}. Like all other functions - update or find...

Remove has an option called single: https://mongoosejs.com/docs/api.html#query_Query-deleteOne . MongoDB is deprecating remove in favor of explicit deleteOne vs deleteMany because too many people have mixed up whether remove deletes just one or all docs that match filter. In Mongoose 5.3 you will be able to do pre(/^delete/) with a regexp though

Was this page helpful?
0 / 5 - 0 ratings