web-dev-qa-db-ja.com

MongooseはMongodbの `findAndModify`メソッドをサポートしていますか?

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

この機能はうまく文書化されていません(まったく読まれていません)が、ソースコードを読んだ後、次の解決策を思いつきました。

コレクションスキーマを作成します。

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);
61
furf
18
juanpaco

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

誰かが役に立つといいな

14
Klimashkin

バージョン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

6
ninja123

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

楽しい! -カラン

3
Curran

多くの答えがありますが、私はこの簡単な解決策を見つけます。

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


});
3
keithics

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

クエリに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},
0
Jonathan David

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 をご覧ください。

0
mstearn