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

发布于 2024-12-03 18:35:47 字数 729 浏览 0 评论 0原文

我想使用 Mongoose 使用 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!");
     }
});

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 '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!");
     }
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

奶气 2024-12-10 18:35:47

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

创建您的集合架构。

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

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);
○闲身 2024-12-10 18:35:47

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

我希望有人能派上用场

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

海未深 2024-12-10 18:35:47

在版本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

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

晨曦慕雪 2024-12-10 18:35:47

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

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


});

a lot of answers but I find this simple solution.

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


});
我们只是彼此的过ke 2024-12-10 18:35:47

我让 findAndModify

  • 更新插入计数器(如果不存在则创建并初始化它)
  • 递增计数器
  • 带有递增值的回调

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

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

:享受!
- 柯兰

I got findAndModify to

  • 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

帅气尐潴 2024-12-10 18:35:47

根据 @furf 的上述回复,这是我的承诺的解决方案:

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

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);
    }
};
赏烟花じ飞满天 2024-12-10 18:35:47

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

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

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.

暗地喜欢 2024-12-10 18:35:47

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

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

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


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

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.

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},
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文