Подтвердить что ты не робот

Поддерживает ли Mongoose метод Mongodb `findAndModify`?

Я хотел бы использовать findAndModify для атомарного приращения поля, используя Mongoose.

Однако код ниже порождает ошибку "TypeError: Object # не имеет метода 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!");
     }
});
4b9b3361

Ответ 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);
});

Bonus

Counters.statics.increment = function (counter, callback) {
  return this.collection.findAndModify({ _id: counter }, [], { $inc: { next: 1 } }, callback);
};

Counter.increment('messagetransaction', callback);

Ответ 2

Достигнуто увеличение рабочей версии для 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();
});

Я надеюсь, что кому-то пригодится

Ответ 4

В версии 3 метод findOneAndUpdate mongoose выдает операцию 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

Я нашел findAndModify для

  • Ускорить счетчик (создать и инициализировать его, если он не существует)
  • Увеличение счетчика.
  • Вызов обратного вызова с добавленным значением

в одном DB roundtrip, используя следующий код:

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

Ответ 6

много ответов, но я нахожу это простое решение.

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


});

Ответ 7

Я бы предложил использовать стиль прямой команды, показанный внизу 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.

Ответ 8

Взяв вышеуказанный ответ @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);
    }
};

Ответ 9

просто добавив к furf ответ, что если вы используете objectId в своем запросе, mongoDB не сможет найти ваш документ. Слой мангуста заботится о преобразовании идентификатора объекта Hex string, который вы получаете из параметров маршрутизации, в соответствующий идентификатор объекта.

чтобы решить эту проблему, вам необходимо:

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


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