Does Mongoose support the Mongodb `findAndModify` method?

前端 未结 9 2108
[愿得一人]
[愿得一人] 2020-11-29 23:57

I would like to use findAndModify to atomically increment a field, using Mongoose.

However, the code below throws the error \"TypeError: Object # has no method \'fin

相关标签:
9条回答
  • 2020-11-30 00:25

    In version 3, the mongoose findOneAndUpdate method exposes mongodb's findAndModify operation. It works like so:

    var query = { name: 'Sprinkls' };
    var update = { name: 'Sprinkles' };
    var options = { new: false };
    Cat.findOneAndUpdate(query, update, options, function (err, cat) {
      if (err) ..
      render('cat', cat);
    });
    

    More info here: http://aaronheckmann.tumblr.com/post/48943524629/mongoose-v3-part-2-findandmodify

    0 讨论(0)
  • 2020-11-30 00:28

    This is fully supported in Mongoose 3.x now, though the name is slightly different.

    http://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate

    http://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate

    http://mongoosejs.com/docs/api.html#model_Model.findOneAndRemove

    http://mongoosejs.com/docs/api.html#model_Model.findByIdAndRemove

    0 讨论(0)
  • 2020-11-30 00:37

    The feature is not well (read: at all) documented, but after reading through the source code, I came up with the following solution.

    Create your collection schema.

    var Counters = new Schema({
      _id: String,
      next: Number     
    });
    

    Create a static method on the schema which will expose the findAndModify method of the model's collection.

    Counters.statics.findAndModify = function (query, sort, doc, options, callback) {
      return this.collection.findAndModify(query, sort, doc, options, callback);
    };
    

    Create your model.

    var Counter = mongoose.model('counters', Counters);
    

    Find and modify!

    Counter.findAndModify({ _id: 'messagetransaction' }, [], { $inc: { next: 1 } }, {}, function (err, counter) {
      if (err) throw err;
      console.log('updated, counter is ' + counter.next);
    });
    

    Bonus

    Counters.statics.increment = function (counter, callback) {
      return this.collection.findAndModify({ _id: counter }, [], { $inc: { next: 1 } }, callback);
    };
    
    Counter.increment('messagetransaction', callback);
    
    0 讨论(0)
  • 2020-11-30 00:38

    I would suggest using the direct command style shown at the bottom of http://www.mongodb.org/display/DOCS/findAndModify+Command. I'm not familiar enough with mongoose to know the method for running a command, but all drivers provide some way to do it. If mongoose doesn't, you can do it directly using the style described at the top of http://www.mongodb.org/display/DOCS/Commands.

    That said, you should make sure that you really need findAndModify and that update won't do what you need it to do. To see what update is capable of take a look at http://www.mongodb.org/display/DOCS/Updating.

    0 讨论(0)
  • 2020-11-30 00:41

    Taking the above response from @furf, this is my promised solution:

    // eslint-disable-next-line func-names
    localeTypesSchema.statics.findAndModify = function (query, sort, update, opts, callback) {
        const cb = callback || (() => { });
        try {
            const result = this.collection.findAndModify(query || {}, sort || [], update || {}, opts);
            cb(null, result);
            return Promise.resolve(result);
        } catch (err) {
            cb(err);
            return Promise.reject(err);
        }
    };
    
    0 讨论(0)
  • 2020-11-30 00:42

    Made working version increment for Mongoose 3.x

    var mongoose = require('mongoose');
    
    var CounterSchema = new mongoose.Schema({
        _id: String,
        next: {type: Number, default: 1}
    });
    
    CounterSchema.statics.increment = function (counter, callback) {
        return this.findByIdAndUpdate(counter, { $inc: { next: 1 } }, {new: true, upsert: true, select: {next: 1}}, callback);
    };
    

    Use something like this:

    Counter.increment('photo', function (err, result) {
        if (err) {
            console.error('Counter on photo save error: ' + err); return;
        }
        photo.cid = result.next;
        photo.save();
    });
    

    I hope someone come in handy

    0 讨论(0)
提交回复
热议问题