Поддерживает ли 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!");
}
});
Ответы
Ответ 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();
});
Я надеюсь, что кому-то пригодится
Ответ 3
Теперь это полностью поддерживается в 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
Ответ 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},