¿Apoya Mongoose el método Mongodb `findAndModify`?

Me gustaría usar findAndModify para incrementar atómicamente un campo, usando Mongoose.

Sin embargo, el código siguiente arroja el error “TypeError: Object # no tiene el método ‘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!"); } }); 

La función no está bien (léase: en absoluto) documentada, pero después de leer el código fuente, se me ocurrió la siguiente solución.

Crea tu esquema de colección.

 var Counters = new Schema({ _id: String, next: Number }); 

Cree un método estático en el esquema que expondrá el método findAndModify de la colección del modelo.

 Counters.statics.findAndModify = function (query, sort, doc, options, callback) { return this.collection.findAndModify(query, sort, doc, options, callback); }; 

Crea tu modelo

 var Counter = mongoose.model('counters', Counters); 

Encuentra y modifica!

 Counter.findAndModify({ _id: 'messagetransaction' }, [], { $inc: { next: 1 } }, {}, function (err, counter) { if (err) throw err; console.log('updated, counter is ' + counter.next); }); 

Prima

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

Incremento de versión de trabajo hecho para 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); }; 

Usa algo como esto:

 Counter.increment('photo', function (err, result) { if (err) { console.error('Counter on photo save error: ' + err); return; } photo.cid = result.next; photo.save(); }); 

Espero que alguien sea útil

En la versión 3, el método mongoose findOneAndUpdate expone la operación findAndModify de mongodb. Funciona así:

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

Más información aquí: http://aaronheckmann.tumblr.com/post/48943524629/mongoose-v3-part-2-findandmodify

Tengo findAndModify para

  • Upsert a counter (crear e inicializar si no existe)
  • Incrementa el contador
  • Llamar a una callback con el valor incrementado

en una ida y vuelta DB simple utilizando el siguiente código:

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

¡Disfrutar! – Curran

muchas respuestas pero encuentro esta solución simple.

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

Tomando la respuesta anterior de @furf , esta es mi solución 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); } }; 

Sugeriría usar el estilo de comando directo que se muestra en la parte inferior de http://www.mongodb.org/display/DOCS/findAndModify+Command . No estoy lo suficientemente familiarizado con la mongoose para conocer el método para ejecutar un comando, pero todos los controladores proporcionan alguna forma de hacerlo. Si la mongoose no lo hace, puede hacerlo directamente utilizando el estilo descrito en la parte superior de http://www.mongodb.org/display/DOCS/Commands .

Dicho esto, debe asegurarse de que realmente necesita findAndModify y esa update no hará lo que necesita hacer. Para ver qué update es capaz de echar un vistazo a http://www.mongodb.org/display/DOCS/Updating .

simplemente agregando a furf, responda que si usa objectId en su consulta, mongoDB no podrá encontrar su documento. La capa de mongoose se encarga de convertir el Id. De objeto de cadena hexadecimal que obtienes de los parámetros de enrutamiento al id de objeto adecuado.

Para resolver esto necesitas:

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