2011-09-07 65 views
28

我想用findAndModify自动增加一个字段,使用Mongoose。Mongoose是否支持Mongodb findAndModify方法?

但是,下面的代码引发错误“类型错误:对象#有没有方法‘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!"); 
    } 
}); 
+0

按照MongoDB的文档findAndModify应该如下, Collection.prototype.findAndModify = function(query,sort,update,new_doc,remove_doc,function(err){ //}) 但将其转换为猫鼬类型时不起作用!请在此澄清我! – Raja

+4

在v3中添加了新功能:http://aaronheckmann.posterous.com/mongoose-v3-part-2-findandmodify – EvdB

+2

Mongoose v3文档:[findOneAndUpdate](http://mongoosejs.com/docs/api.html#query_Query -findOneAndUpdate)或[findOneAndRemove](http://mongoosejs.com/docs/api.html#model_Model.findOneAndRemove) – aaronheckmann

回答

1

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

也就是说,你应该确保你真的需要findAndModify而且update不会做你需要它做的事情。看看update是能够看看http://www.mongodb.org/display/DOCS/Updating

59

该功能并不完善(阅读:完全)记录,但通读源代码后,我想出了以下解决方案。

创建您的集合架构。

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

当然,你可以在实例上添加一个增量方法 – furf

+3

如何获取findAndModify的返回值这种方法? –

+0

我想,与其他地方一样 - 通过从回调中的第二个参数中读取它。 – incarnate

3

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

享受! - Curran

14

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

我希望有人能派上用场

+0

确实很方便,但FWIW我最终提出了以Redis为基础的计数器。更快,更容易。 – incarnate

14
+1

这些只允许查找单个条目 – Tom

+3

MongoDB具有相同的限制(http://docs.mongodb.org/manual/reference/command/findAndModify/)。 – juanpaco

3

很多答案,但我觉得这个简单的解决方案。

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


}); 
0

只是增加furf答案,如果您在查询中使用对象ID,MongoDB的将无法找到您的文档。猫鼬层负责将从路由参数获得的Hex字符串对象id转换为适当的对象ID。

来解决这一点,你需要:

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


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

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