【发布时间】:2019-01-04 01:39:30
【问题描述】:
在 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();
我的目标是在帐户下找到丢失的模板并从默认值中获取它们。 (a) 如果帐户中不存在 templates,我需要对其进行更新,并且 (b) 如果帐户中已存在模板,我不想更新它。
我尝试了以下方法:
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);
}
);
}
这在 upsert 中成功,但它会输入所有默认模板,即使 templateNames 中有匹配的名称。我已经验证了 templateNames 数组是正确的,并且我也尝试过使用 $addToSet 而不是 $push,所以我一定不懂 Mongo 子文档查询。
关于我做错了什么有什么想法吗?
编辑:我通过在更新之前简单地从默认数组中删除元素来实现这一点,但我仍然想知道如何使用 Mongoose 实现这一点。
【问题讨论】:
-
templateNames和defaults包含什么? -
@AnthonyWinzlet defaults 包含与上面显示的
account相同的文档/模式模板名称包含同一文档上的name属性的数组(例如,[ "Password Reset", "Welcome Message" ]) -
upsert 适用于文档级别,而不是子文档。 addToSet 仅在名称和内容相同时才有效(就像不推送)。你的方法是它应该如何工作。
-
唯一的问题是 $nin 没有做你期望的事情。它仅匹配没有单个模板名称来自 templateNames 的文档,这与“查找丢失的模板”有所不同。
标签: arrays node.js mongodb mongoose