Mongoose 是不是支持 Mongodb `findAndModify` 方法?

Posted

技术标签:

【中文标题】Mongoose 是不是支持 Mongodb `findAndModify` 方法?【英文标题】: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 文档:findOneAndUpdate 或 findOneAndRemove 【参考方案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】:

现在 Mongoose 3.x 完全支持此功能,但名称略有不同。

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

【讨论】:

这些只允许查找单个条目 MongoDB 有同样的限制 (docs.mongodb.org/manual/reference/command/findAndModify)。 这些现在都被弃用了。 @chovy 在当前版本(5.11.19)中没有一个被弃用【参考方案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,

【讨论】:

以上是关于Mongoose 是不是支持 Mongodb `findAndModify` 方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mongodb/mongoose 的嵌套数组中检查是不是存在并更新对象?

“基本模式”只返回一种类型而不是 2 (mongodb - mongoose)

MongoDb - 要创建一个新的ObjectId,请尝试`Mongoose.Types.ObjectId`而不是使用`Mongoose.Schema.ObjectId`

奇怪的 mongodb 和 mongoose 错误:不是 master 和 slaveOk=false 错误

MongoDB 上的 MultiPolgyon 搜索

使用Mongoose时,为什么在index.js中MongoDB不是必需的?