当我更新用户配置文件时,将删除用户模型中位置内部的字段附近,这是我的用户模型,您可以在其中看到附近位置的内部区域:
const userSchema = new Schema({
name: {
type: String,
required: 'Please supply a name',
trim: true
},
location: {
type: {
type: String,
default: 'Point'
},
coordinates: [{
type: Number,
required: 'You must supply coordinates!'
}],
address: {
type: String,
required: 'You must supply an address!'
},
vicinity: {
type: String,
},
},
});
然后我有一个用于更新用户的控制器,我有一个更新对象,附近不th,因为我不想更新它,我只是想在寄存器中保存附近,而不是更新它:
exports.updateAccount = async (req, res) => {
req.body.location.type = 'Point';
const updates = {
email: req.body.email,
name: req.body.name,
photo: req.body.photo,
genres: req.body.genres,
musicLinks: req.body.musicLinks,
location: {
type: req.body.location.type,
coordinates: [
req.body.location.coordinates[0],
req.body.location.coordinates[1],
],
address: req.body.location.address,
// vicinity: req.body.location.vicinity,
}
};
if(!updates.photo) delete updates.photo
const user = await User.findOneAndUpdate(
{ _id: req.user._id },
{ $set: updates },
{ new: true, runValidators: true, context: 'query' }
);
req.flash('success', 'Updated the profile!');
res.redirect('back');
};
但是,每次我更新用户个人资料时,附近区域都会被删除,还请注意,在我为用户提交更新的表单中,没有附近区域,因此它不发送任何要更新的数据。 / p>
我猜是因为在控制器上我有一个更新对象,如:
location: {
type: req.body.location.type,
coordinates: [
req.body.location.coordinates[0],
req.body.location.coordinates[1],
],
address: req.body.location.address,
// vicinity: req.body.location.vicinity,
}
及其缺失的附近。数据库会尝试保存整个位置对象,并且由于没有附近而被删除。
如果是这种情况..我如何对mongo db保留该值而不删除它?谢谢
答案 0 :(得分:2)
之所以会这样,是因为您实际上是在用新对象更新location
字段。 location
对象下的每个键都将被擦除然后重新写入-这就是vicinity
丢失的原因。
要实现目标,可以使用嵌套键语法:
const updates = {
$set: {
email: req.body.email,
name: req.body.name,
photo: req.body.photo,
genres: req.body.genres,
musicLinks: req.body.musicLinks,
'location.type': req.body.location.type,
'location.coordinates': [req.body.location.coordinates[0], req.body.location.coordinates[1]],
'location.address': req.body.location.address,
}
};
之后:
const user = await User.findOneAndUpdate(
{ _id: req.user._id },
updates,
{ new: true, runValidators: true, context: 'query' }
);
答案 1 :(得分:1)
这是设计使然。
实际上,您在$set
的参数中包含了location
的“完整对象”,而这样做只是覆盖该对象。基本上,这就是MongoDB的工作方式。
MongoDB工作原理的另一部分是当您打算部分使用“嵌套路径”更新文档时,您需要将该对象结构处理为"Dot Notation"形式。 / p>
实际上,这是我很久以前拼凑起来的东西的基本版本:
var data = {
email: "bill@example.com",
name: "Bill S Preston",
photo: "",
genres: "Music, Lyrics",
musicLinks: "",
location: {
type: "Point",
coordinates: [
0,
0
],
address: "somewhere"
}
};
一个简单的功能:
function dotNotate(obj,target,prefix) {
target = target || {},
prefix = prefix || "";
Object.keys(obj).forEach(function(key) {
if ( Array.isArray(obj[key] )) {
return target[prefix + key] = obj[key];
} else if ( typeof(obj[key]) === "object" ) {
dotNotate(obj[key],target,prefix + key + ".");
} else {
return target[prefix + key] = obj[key];
}
});
return target;
}
运行该函数会产生:
var updates = dotNotate(data);
{
"email" : "bill@example.com",
"name" : "Bill S Preston",
"photo" : "",
"genres" : "Music, Lyrics",
"musicLinks" : "",
"location.type" : "Point",
"location.coordinates" : [
0,
0
],
"location.address" : "somewhere"
}
当然,{ $set: updates }
仅会部分更新明确指定的字段而不会被覆盖。