Mongoose findOneAndUpdate Upsert _id null?
Я хотел бы иметь один метод, который либо создает, либо обновляет документ для политики. Поиск и использование различных методов, таких как этот, я придумал нулевой _id для моего документа. Использование findByIdAndUpdate имеет аналогичный аффект.
Я вижу документ, вставленный в коллекцию, но поле _id равно null:
exports.savePolicy = function (plcy, callback) {
console.log('priority is : ' + plcy.priority)
try {
var policy = new Policy(plcy);
var query = {_id: plcy._id}; //this may be null
var update = {
name: plcy.name || defaults.policyDefaults.name,
longDescription: plcy.longDescription || defaults.policyDefaults.longDescription,
shortDescription: plcy.shortDescription || defaults.policyDefaults.shortDescription,
priority: plcy.priority, colorHex: plcy.colorHex || defaults.policyDefaults.colorHex,
settings: plcy.settings || [],
parentPolicyId: plcy.parentPolicyId || null
}
Policy.findOneAndUpdate(query, update, {upsert: true}, function (err, data) {
callback(err, data);
});
} catch (e) {
log.error('Exception while trying to save policy: ' + e.message);
callback(e, null);
}
Есть ли что-то, что можно сделать для того, чтобы _id не был пустым, если это не обновление?
Ответы
Ответ 1
null
является допустимым значением _id
в MongoDB, поэтому, если вы не хотите, чтобы он использовался в новых документах, вы должны убедиться, что значение null
заменено новым ObjectID
в query
:
var query = {_id: plcy._id};
if (!query._id) {
query._id = new mongoose.mongo.ObjectID();
}
// the rest stays the same...
Ответ 2
У меня была такая же проблема, и я не мог понять, как заставить ее работать. В конце концов я написал свой собственный метод upsert.
var upsert = function(model, data, f){
if (!data._id) {
model.create(data, f);
} else {
var id = data._id;
delete data._id;
model.findOneAndUpdate({_id: id}, data, f);
}
}
Это позволяет мне называть его для любой из моих моделей с одной строкой кода...
upsert(Team, team, f);
Там может быть лучший способ сделать это, но это работает для меня. Я могу делать обновления и вставки, и я не получаю нуль _id при вставке.
Ответ 3
Я не использую Mongoose, но сталкиваюсь с аналогичной проблемой с MongoDB. Для действия Upsert при вставке нового объекта MongoDB установил null
в _id
.
Я звонил:
findOneAndUpdate({my_id:'my_unique_id'}, obj, {upsert: true})
где obj._id
было undefined
.
Проблема заключалась в том, что _id
присутствовал в списке ключей Object.keys(obj)
. Я обнаружил, что я назначал obj._id = some_variable
, где some_variable
был undefined
, и это вызывало _id
для отображения в списке ключей.
Я применил обходное решение, позвонив прямо перед upsert:
if (_.isUndefined(obj._id)) {
delete obj._id;
}
Ответ 4
Спасибо JohnnyHK за полезный ответ выше. Я придумал однострочный вкладыш, так как он так часто использовался:
query = args._id ? { _id: args._id } : { _id: new ObjectId() };
Он полагается на следующее:
const ObjectId = require('mongodb').ObjectID;
Ответ 5
Попробуйте установить для "нового" параметра значение true:
{ upsert: true, new: true }
Дополнительная информация: https://github.com/Automattic/mongoose/issues/2939
Ответ 6
Попробуйте установить для параметра upsert значение true в вашем вызове для обновления. Из документов mongoid: http://docs.mongodb.org/manual/reference/method/db.collection.update/#update-parameter
Дополнительно. Если установлено значение true, создается новый документ, если документ не соответствует критериям запроса. Значение по умолчанию - false, которое не вставляет новый документ, если совпадение не найдено.