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!");
}
});
この機能はうまく文書化されていません(まったく読まれていません)が、ソースコードを読んだ後、次の解決策を思いつきました。
コレクションスキーマを作成します。
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);
これは現在、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
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();
});
誰かが役に立つといいな
バージョン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
FindAndModifyを取得しました
次のコードを使用して、単一のDBラウンドトリップで:
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);
});
}
楽しい! -カラン
多くの答えがありますが、私はこの簡単な解決策を見つけます。
Counter.findByIdAndUpdate(ID, {$inc: {next:1}}, function (err, data) {
});
@ 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);
}
};
クエリにobjectIdを使用すると、mongoDBはドキュメントを見つけられないという答えをfurfに追加するだけです。 mongooseレイヤーは、ルーティングパラメーターから取得した16進文字列オブジェクトIDを適切なオブジェクトIDに変換します。
これを解決するには、以下を行う必要があります。
var ObjectID = require('mongodb').ObjectID;
var itemId = req.params.itemId;
var objectId = ObjectID.createFromHexString(itemId);
Item.findAndModify({_id: objectId},
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 をご覧ください。