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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7334390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:14:22  来源:igfitidea点击:

Does Mongoose support the Mongodb `findAndModify` method?

mongodbmongoose

提问by Raja

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

我想使用 findAndModify 使用 Mongoose 以原子方式递增字段。

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

但是,下面的代码会抛出错误“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!");
     }
});

回答by furf

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.

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

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

回答by Klimashkin

Made working version increment for Mongoose 3.x

为 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

我希望有人能派上用场

回答by ninja123

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

在版本 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);
});

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

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

回答by keithics

a lot of answers but I find this simple solution.

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

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


});

回答by Curran

I got findAndModify to

我找到了 findAndModify

  • Upsert a counter (create and initialize it if it doesn't exist)
  • Increment the counter
  • Call a callback with the incremented value
  • 向上插入一个计数器(如果它不存在则创建并初始化它)
  • 增加计数器
  • 使用递增的值调用回调

in a single DB roundtrip using the following code:

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

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

Enjoy! - Curran

享受!- 可兰

回答by David

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

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

回答by mstearn

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.

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

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

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

回答by Jonathan David

just adding to furf answer that if you use objectId in your query, mongoDB will not be able to find your document. The mongoose layer takes care of converting the Hex string object id you get from the routing params to the proper object id.

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

to solve this you need to:

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

var ObjectID = require('mongodb').ObjectID;


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