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`