В MongoDB это упрощенная структура моего документа account:
{
"_id" : ObjectId("5a70a60ca7fbc476caea5e59"),
"templates" : [
{
"name" : "Password Reset",
"content" : "AAAAAAAA"
},
{
"name" : "Welcome Message",
"content" : "BBBBBB"
}
]
}
Есть похожая коллекция default_templates
let accnt = await Account.findOne({ _id: req.account._id }, { templates: 1 });
let defaults = await DefaultTemplate.find({}).lean();
Моя цель - найти недостающие шаблоны в учетной записи и получить их по умолчанию. (а) Мне нужно обновить templates, если он не существует в учетной записи, и (б) я не хочу обновлять шаблон, если он уже существует в учетной записи.
Я пробовал следующее:
if (!accnt.templates || accnt.templates.length < defaults.length) {
const accountTemplates = _.filter(accnt.templates, 'name');
const templateNames = _.map(accountTemplates, 'name');
Account.update({ _id: req.account._id, 'templates.name' : { $nin: templateNames } },
{ '$push': { 'templates': { '$each' : defaults } } }, { 'upsert' : true },
function(err, result) {
Logger.error('error %o', err);
Logger.debug('result %o', result);
}
);
}
Это будет успешным при обновлении, но он войдет во все шаблоны по умолчанию, даже если в templateNames есть соответствующее имя. Я проверил, что массив templateNames правильный, и я также пробовал использовать $addToSet вместо $push, поэтому я не должен понимать запросы вложенного документа Mongo.
Есть идеи о том, что я делаю неправильно?
Обновлено: я заставил это работать, просто удалив элементы из массива значений по умолчанию перед обновлением, но я все же хотел бы знать, как это можно сделать с помощью Mongoose.
@AnthonyWinzlet по умолчанию содержит документ / схему, идентичную показанной выше для account. TemplateNames содержит массив этих свойств name в том же документе (например, [ "Password Reset", "Welcome Message" ])
upsert работает на уровне документа, а не суб-документов. addToSet работает (например, не нажимает) только тогда, когда и имя, и контент идентичны. Ваш подход таков, как он должен работать.
Единственное, $ nin делает не то, что вы ожидаете. Он сопоставляет только документы, в которых нет единого шаблона с именем из templateNames, что несколько отличается от «поиска отсутствующих шаблонов».



Вы можете попробовать с операцией bulkWrite в mongodb
Account.bulkWrite(
req.body.accountTemplates.map((data) =>
({
updateOne: {
filter: { _id: req.account._id, 'templates.name' : { $ne: data.name } },
update: { $push: { templates: { $each : data } } },
upsert : true
}
})
)
})
что содержат
templateNamesиdefaults?