2015-04-12 34 views
2

我的一块蒙戈文档结构是:MongooseJS弄乱当文档被更新前的进口数据

{ "_id": ObjectId("xxxxxx..."), 
"Country" : "UNITED KINGDOM", 
"Line" : "something", 
"Records" : [ 
    {"rdata" : "foo", "rtype" : "X", "name" : "John"}, 
    {"rdata" : "bar", "rtype" : "Y", "name" : "Bill"} 
], ... 

我用猫鼬通过以下模型来访问数据:

var Record = new Schema({ 
rdata: String, 
rtype: String, 
name: String 
}, {_id: false}); 

var ThingSchema = new Schema({ 
Country: String, 
Line : String, 
Records : [Record], 

比方说,我想通过向合适的API URL发送PUT请求来更新我的文档之一的“行”属性,从"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"} 
], ... 

通知,记录阵列是怎么通过覆盖搞砸了我通过复制第一个记录来记录第二个记录。 (如果我打开Mongoose自动添加'_id'到子文档,那么即使数组中的两个记录中的“_id”字段也是相同的)。

它可能是相关的,最初的记录不是通过Mongoose添加 - 而是通过导入JSON文档。任何有关如何开始发现这种情况的建议都会很棒。

回答

2

尝试改变_.merge_.extend,然后调用直接保存在由findById()方法,而不是合并对象updated返回thing文件:

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对象上的保存方法之前调用thing.set(req.body)

answer通过ShitalShah凸显合并之间的区别和扩展,是造成重复在产生与合并,但实质上对象:

这里是如何扩展/分配工作:对于源,复制每个属性其 值原样到达目的地。如果属性值本身是对象,则 不会对其属性进行递归遍历。整个对象 将从源获取并设置到目的地。

以下是合并的工作方式:对于源中的每个属性,检查属性是否为对象本身。如果它是递归下去并尝试 将子对象属性从源映射到目标。实质上我们合并了从源到目标的对象层次结构。 虽然用于扩展/分配,但它很容易从 源到目标的一个级别副本。

JSBin来说明差异

+1

好极了,谢谢! –

+0

@ tom.W不用担心:-) – chridam