【问题标题】:Does Mongoose support the Mongodb `findAndModify` method?Mongoose 是否支持 Mongodb `findAndModify` 方法?
【发布时间】:2011-11-12 03:49:57
【问题描述】:

我想使用 findAndModify 原子地增加一个字段,使用 Mongoose。

但是,下面的代码会抛出错误“TypeError: Object # has no method 'findAndModify'”:

// defining schema for the "counters" table
var tableSchema = new Schema({
    _id: String,
    next: Number        
});

// creating table object for the counters table
var counters_table = mongoose.model('counters', tableSchema);
var tableObj = new counters_table();    

// increment the "next" field on the table object
var query = {_id: 'messagetransaction'};
var update = {'$inc': {next: 1}};
var ret = tableObj.findAndModify(query, [], update, true, true, function(err) {
     if (err) { 
         throw err;
     }
     else { 
         console.log("updated!");
     }
});

【问题讨论】:

  • 根据 mongodb 文档,findAndModify 应如下所示, Collection.prototype.findAndModify = function(query, sort, update,new_doc, remove_doc, function(err) { //}) 但不起作用将其转换为猫鼬类型时!请澄清一下!
  • Mongoose v3 文档:findOneAndUpdatefindOneAndRemove

标签: mongodb mongoose


【解决方案1】:

该功能没有很好的记录(阅读:根本),但是在阅读了源代码之后,我想出了以下解决方案。

创建您的集合架构。

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

在架构上创建一个静态方法,该方法将公开模型集合的 findAndModify 方法。

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

创建您的模型。

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

查找和修改!

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

奖金

Counters.statics.increment = function (counter, callback) {
  return this.collection.findAndModify({ _id: counter }, [], { $inc: { next: 1 } }, callback);
};

Counter.increment('messagetransaction', callback);

【讨论】:

  • 当然,您可以在实例上添加增量方法
  • 如何通过该方法获取findAndModify的返回值?
  • 我想,和其他地方一样——通过从回调中的第二个参数读取它。
  • 我得到了 return = undefined
【解决方案2】:

【讨论】:

【解决方案3】:

为 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);
};

使用这样的东西:

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

希望有人能派上用场

【讨论】:

  • 它确实派上了用场,但 FWIW 我最终想出了基于 Redis 的计数器。更快、更容易。
【解决方案4】:

在版本 3 中,mongoose findOneAndUpdate 方法公开了 mongodb 的 findAndModify 操作。它是这样工作的:

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);
});

更多信息在这里:http://aaronheckmann.tumblr.com/post/48943524629/mongoose-v3-part-2-findandmodify

【讨论】:

    【解决方案5】:

    很多答案,但我找到了这个简单的解决方案。

    Counter.findByIdAndUpdate(ID, {$inc: {next:1}}, function (err, data) {
    
    
    });
    

    【讨论】:

      【解决方案6】:

      我得到了 findAndModify

      • Upsert 一个计数器(如果它不存在则创建并初始化它)
      • 增加计数器
      • 使用递增的值调用回调

      在单个数据库往返中使用以下代码:

      var Counters = new Schema({
        _id:String, // the schema name
        count: Number
      });
      
      Counters.statics.findAndModify = function (query, sort, doc, options, callback) {
          return this.collection.findAndModify(query, sort, doc, options, callback);
      };
      
      var Counter = mongoose.model('Counter', Counters);
      
      /**
       * Increments the counter associated with the given schema name.
       * @param {string} schemaName The name of the schema for which to
       *   increment the associated counter.
       * @param {function(err, count)} The callback called with the updated
       *   count (a Number).
       */
      function incrementCounter(schemaName, callback){
        Counter.findAndModify({ _id: schemaName }, [], 
          { $inc: { count: 1 } }, {"new":true, upsert:true}, function (err, result) {
            if (err)
              callback(err);
            else
              callback(null, result.count);
        });
      }
      

      享受吧! - 柯伦

      【讨论】:

        【解决方案7】:

        接受@furf的上述回复,这是我的promised解决方案:

        // 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);
            }
        };
        

        【讨论】:

          【解决方案8】:

          我建议使用http://www.mongodb.org/display/DOCS/findAndModify+Command 底部显示的直接命令样式。我对 mongoose 不够熟悉,不知道运行命令的方法,但所有驱动程序都提供了一些方法来做到这一点。如果猫鼬没有,你可以直接使用http://www.mongodb.org/display/DOCS/Commands顶部描述的样式。

          也就是说,您应该确保您确实需要 findAndModify 并且 update 不会做您需要它做的事情。要了解update 的能力,请查看http://www.mongodb.org/display/DOCS/Updating

          【讨论】:

            【解决方案9】:

            只是添加到 furf 答案中,如果您在查询中使用 objectId,mongoDB 将无法找到您的文档。 mongoose 层负责将您从路由参数中获得的十六进制字符串对象 id 转换为正确的对象 id。

            要解决这个问题,您需要:

            var ObjectID = require('mongodb').ObjectID;
            
            
            var itemId = req.params.itemId;
            var objectId = ObjectID.createFromHexString(itemId);
            Item.findAndModify({_id: objectId},
            

            【讨论】:

              猜你喜欢
              • 2017-01-10
              • 2021-10-20
              • 1970-01-01
              • 2012-03-10
              • 1970-01-01
              • 2017-03-11
              • 2017-06-10
              • 2016-07-07
              • 2020-09-14
              相关资源
              最近更新 更多