我需要创建具有特定条件的子文档数组。如果 ip
agent
和 language
字段都完全匹配,那么就不需要添加新的子文档,如果其中任何一个下降,那么我需要创建一个新的。
但是当我尝试使用 $push
执行此操作时,它会返回我
Exception: StrictModeError: Path "ip" is not in schema, strict mode is `true`, and upsert is `true`.
findOneAndUpdate
更新整个文档和我的字段集,因为它们出现在数据库中。还尝试按照模式中显示的方式设置它,但它返回相同的错误。
userSchema中的数组
metadata: [mongoose.modelSchemas.UserMetaData],
用户元数据架构
var userMetaDataSchema = new mongoose.Schema({
ip: { type: String, default: '' },
agent: { type: String, default: '' },
language: { type: String, default: '' },
userCreated: {
id: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
name: { type: String, default: '' },
}
});
app.db.model('UserMetaData', userMetaDataSchema);
};
如果我尝试直接使用 findOneAndUpdate
到 UserMetaData
集合而不使用 $push
,它会起作用。
控制台的结果:
{
"_id" : ObjectId("5a00d35f03fc3eb63cbb1c6f"),
"agent" : "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0",
"ip" : "::ffff:192.168.33.10",
"language" : "en-US,en;q=0.5",
"userCreated" : {
"name" : "user2",
"id" : ObjectId("5a00d27a7fdf8e07f40d2123")
},
"__v" : 0
}
查询不起作用
var fieldsToSet = {
$push: {
metadata: {
agent: userAgent,
ip: userIp,
language: languages,
userCreated: {
name: req.user.username,
id: req.user._id,
}
}
}
};
var options = { upsert: true };
User.findOneAndUpdate(conditions, fieldsToSet, options, function(err, user) {....
创建此类数组的最佳方法是什么?谢谢。
最佳答案
这里的错误是由于尝试将 findOneAndUpdate
与 $push
和 {upsert: true}
选项一起使用而引起的,因为如果您想要插入或更新子文档,您应该使用 2 个不同的运算符 $set
进行更新,使用 $push
进行插入。所以这里的解决方案是使用不同的设置进行更新和插入:
var conditions = {
_id: req.user._id,
'metadata.ip': userIp,
'metadata.agent': userAgent,
'metadata.language': userLanguage,
'metadata.userCreated.name': req.user.username
};
var fieldsToSet = {
$set: {
'metadata.$.agent': userAgent,
'metadata.$.ip': userIp,
'metadata.$.language': userLanguage,
}
};
var fieldsToPush = {
$push: {
metadata: {
agent: userAgent,
ip: userIp,
language: userLanguage,
userCreated: {
id: req.user._id,
name: req.user.username,
}
}
}
};
var options = { upsert: true };
// check if thare is a match and overwright
User.findOneAndUpdate(conditions, fieldsToSet, options, function (err, setdocs) {
//if there is no match then push a new subdocument
if (setdocs == null) {
User.findByIdAndUpdate(req.user._id, fieldsToPush, function (err, pushdocs) {
//...
});
}
else {
//....
}
});
});
此解决方案归功于 Neil Lunn我现在找不到这个特定的解决方案
关于node.js - Mongoose - 使用 findoneandupdate 和 $push 添加或更新子文档(当 upsert 为 true 时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47148415/