我的Mongo文档结构是:
{ "_id": ObjectId("xxxxxx..."),
"Country" : "UNITED KINGDOM",
"Line" : "something",
"Records" : [
{"rdata" : "foo", "rtype" : "X", "name" : "John"},
{"rdata" : "bar", "rtype" : "Y", "name" : "Bill"}
], ...
我正在使用Mongoose通过以下模型访问数据:
var Record = new Schema({
rdata: String,
rtype: String,
name: String
}, {_id: false});
var ThingSchema = new Schema({
Country: String,
Line : String,
Records : [Record],
假设我要通过向相应的API网址发送PUT请求来更新我的某个文档的“Line”属性,从"Line" : "something"
到"Line" : "way more interesting"
。我可以看到发送的数据没问题。这就是API的作用:
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Thing.findById(req.params.id, function (err, thing) {
if (err) { return handleError(res, err); }
if(!thing) { return res.send(404); }
var updated = _.merge(thing, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, updated);
});
});
};
API以200 / OK返回 - 但我看到以下更新数据:
{ "_id": ObjectId("xxxxxx..."),
"Country" : "UNITED KINGDOM",
"Line" : "way more interesting", <-- updated correctly
"Records" : [
{"rdata" : "foo", "rtype" : "X", "name" : "John"},
{"rdata" : "foo", "rtype" : "X", "name" : "John"}
], ...
注意,如何通过复制第一个记录来覆盖我的第二个记录,从而弄乱了Records数组。 (如果我通过Mongoose打开自动添加'_id'到子文档,那么即使“_id”字段在数组中的两个记录上也是相同的。)
可能相关的是,最初的记录不是通过Mongoose添加的 - 而是通过导入JSON文档。关于如何开始找出这种情况发生的任何建议都会很棒。
答案 0 :(得分:2)
尝试将_.merge
更改为_.extend
,然后直接在 thing
方法而不是合并对象返回的findById()
文档上调用保存updated
:
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Thing.findById(req.params.id, function (err, thing) {
if (err) { return handleError(res, err); }
if(!thing) { return res.send(404); }
_.extend(thing, req.body);
thing.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, thing);
});
});
}
另一个选择是在thing.set(req.body)
对象上调用save方法之前在实体上使用set方法,即thing
。
ShitalShah的 answer 突出显示了合并和扩展之间的差异,这种差异导致合并后的对象产生重复,但基本上是:
以下是extend / assign的工作原理:对于源中的每个属性,复制它 价值按原样到达目的地。如果属性值本身是对象, 它们的属性没有递归遍历。整个对象 将从源头获取并设置到目的地。
以下是合并的工作原理:对于源中的每个属性,请检查是否存在 财产是对象本身。如果它然后递归下来并尝试 将子对象属性从源映射到目标。所以 基本上我们将对象层次结构从源合并到目标。 而对于extend / assign,它是简单的一级属性副本 来源目的地。
JSBin 来说明差异