我正在使用Angular Fullstack作为网络应用。
我通过$http.post()
我的对象发布我的数据:
{ title: "Some title", tags: ["tag1", "tag2", "tag3"] }
当我编辑我的对象并尝试$http.put()
时,例如:
{ title: "Some title", tags: ["tag1"] }
在控制台中我得到HTTP PUT 200
但是当我刷新页面时,我仍然使用所有3个标签来回放该对象。
这是我在MongoDB中保存的方式:
exports.update = function(req, res) {
if (req.body._id) {
delete req.body._id;
}
Question.findByIdAsync(req.params.id)
.then(handleEntityNotFound(res))
.then(saveUpdates(req.body))
.then(responseWithResult(res))
.catch(handleError(res));
};
function saveUpdates(updates) {
return function(entity) {
var data = _.merge(entity.toJSON(), updates);
var updated = _.extend(entity, data);
return updated.saveAsync()
.spread(function(updated) {
return updated;
});
};
}
有人可以解释如何使用已删除的项目保存对象吗?
我做错了什么?
答案 0 :(得分:1)
从数据库中检索后,在客户端(意味着你的nodejs客户端是数据库而不是浏览器)代码中使用_.merge
或_.extend
之类的东西是非常糟糕的做法。同样值得注意的是_.merge
是问题,因为它不会“带走”东西,而是“扩充”已经存在的信息。不是你想要的,但也有更好的方法。
你应该简单地使用像$set
这样的“原子操作符”来代替:
Question.findByIdAndUpdateAsync(
req.params.id,
{ "$set": { "tags": req.body.tags } },
{ "new": true }
)
.then(function(result) {
// deal with returned result
});
您还应该定位您的端点,而不是编写“通用”对象。因此,obove仅针对相关“标签”的“PUT”进行特定目标,而不是触及对象中的其他字段。
如果你真的必须抛出一个完整的对象并希望从所有内容中获得更新,那么使用帮助器来正确修复更新语句:
function dotNotate(obj,target,prefix) {
target = target || {},
prefix = prefix || "";
Object.keys(obj).forEach(function(key) {
if ( typeof(obj[key]) === "object" ) {
dotNotate(obj[key],target,prefix + key + ".");
} else {
return target[prefix + key] = obj[key];
}
});
return target;
}
var update = { "$set": dotNotate(req.body) };
Question.findByIdAndUpdateAsync(
req.params.id,
update,
{ "new": true }
)
.then(function(result) {
// deal with returned result
});
哪个正确的结构无关紧要你扔在它上面的对象。
虽然在这种情况下,可能只是直接就足够了:
Question.findByIdAndUpdateAsync(
req.params.id,
{ "$set": req.body },
{ "new": true }
)
.then(function(result) {
// deal with returned result
});
还有其他原子操作符的方法,您也可以适合您的逻辑进行处理。但最好考虑每个元素执行这些操作,至少是根文档属性,以及像孩子一样单独处理的数组。
所有原子操作都与“在数据库中”和“在修改时”的文档进行交互。从数据库中提取数据,对其进行修改,然后保存回来,不会提供数据尚未更改的相关数据,并且您可能正在覆盖已经发布的其他更改。
我说你的“浏览器客户端”应该已经知道“tags”数组有另外两个条目然后你的“修改请求”应该只是$pull
要从数组中删除的条目,像这样:
Question.findByIdAndUpdateAsync(
req.params.id,
{ "$pull": { "tags": { "$in": ["tag2", "tag3"] } } },
{ "new": true }
)
.then(function(result) {
// deal with returned result
});
然后,“无论”修改时服务器上文档的当前状态如何,这些更改将是唯一的。因此,如果在添加“tag4”时修改了其他内容,并且客户端在发送修改之前尚未获得此类更改的信息,那么返回响应也将包括该内容,并且所有内容都将同步。
了解MongoDB的update modifiers,因为它们可以很好地为您服务。