Mongoose 子文档不会更新
Posted
技术标签:
【中文标题】Mongoose 子文档不会更新【英文标题】:Mongoose Subdocument will not update 【发布时间】:2017-03-17 07:35:20 【问题描述】:我无法确定我是否正确设计了架构,因为我在尝试从配置文件中修补角色属性的更改时收到 500 错误。 (注意:500 错误只是以空 响应,因此它并不能提供真正的信息)
以下是配置文件架构:
var ProfileSchema = new Schema(
name:
type: String,
required: true
,
roles: [
application:
type: Schema.Types.ObjectId,
required: true,
ref: 'Application'
,
role:
type: String,
required: true,
enum: [ 'admin', 'author', 'publisher' ]
]
);
每个配置文件都有一个应用程序的角色,当我将请求发送到控制器操作“更新”时,它失败了:
配置文件更新控制器:
// Updates an existing Profile in the DB
export function update(req, res)
try
if (req.body._id)
delete req.body._id;
console.log('ENDPOINT HIT...');
console.log(`REQUEST PARAM ID: $req.params.id`);
console.log('REQUEST BODY:');
console.log(req.body);
console.log('ENTIRE REQUEST: ');
return Profile.findByIdAsync(req.params.id)
.then(handleEntityNotFound(res))
.then(saveUpdates(req.body))
.then(respondWithResult(res))
.catch(handleError(res));
catch(ex)
console.error('FAILED TO UPDATE PROFILE');
return handleError(res);
我确保 id 和 body 被正确发送,并且我正在到达终点。
这是请求正文 JSON 的示例:
_id: 57e58ad2781fd340563e29ff,
__updated: Thu Oct 27 2016 15:41:12 GMT-0400 (EDT),
__created: Fri Sep 23 2016 16:04:34 GMT-0400 (EDT),
name: 'test',
__v: 11,
roles:[
application: 57b70937c4b9fe460a235375,
role: 'admin',
_id: 58125858a36bd76d8111ba16 ,
application: 581b299f0145b48adf8f57bd,
role: 'publisher',
_id: 581b481898eefb19ed8a73ee
]
当我尝试通过 Id 查找 Profile 时,promise 链直接进入 catch(handleError(res));部分代码并在我的控制台中显示一个空对象。
我的句柄错误函数:
function handleError(res, statusCode)
console.error('HANDLE PROFILE ERROR: ', statusCode);
statusCode = statusCode || 500;
return function(err)
console.error('PROFILE ERROR:');
console.error(JSON.stringify(err, null, 2));
res.status(statusCode).send(err);
;
更新
我意识到代码在遇到我的 saveUpdates 函数时会中断(注意:我正在使用 lodash):
function saveUpdates(updates)
/// the code is fine here ///
return function(entity)
/// once it enters in here, is where it begins to break ///
var updated = _.merge(entity, updates);
if(updated.roles.length != updates.roles.length)
updated.roles = updates.roles;
for(var i in updates.roles)
updated.roles.set(i, updates.roles[i]);
return updated.saveAsync()
.then(updated =>
return updated;
);
;
【问题讨论】:
查看错误findByIdAsync(...).catch((err) => console.log(err); handleError(res); )
您能告诉我们,req.params.id
上到底有什么内容吗? console.log(`REQUEST PARAM ID: $req.params.id`);
向您展示了什么
@GrégoryNEUT,当我控制台记录 params.id 时——这是我检索到的内容:`REQUEST PARAM ID: 57bd9db4f33dcd03c3fd9990`
ok 试试 findOne( _id: req.params.id )
(我找不到 findByIdAsync() mongoose 文档)
@GrégoryNEUT,所以我意识到如果我从我的承诺链中删除 saveUpdates 函数调用——并将模型的方法切换到Profile.findOneAndUpdate
——那么错误就会消失。我确信我的 saveUpdates 功能现在坏了。
【参考方案1】:
经验教训:正确阅读文档。
由于我在此应用程序中使用了 bluebird Promise,因此我忘记在我的 saveUpdates()
回调函数中使用 .spread()
。
解决方案:
function saveUpdates(updates)
return function(entity)
var updated = _.merge(entity, updates);
if(updated.roles.length != updates.roles.length)
updated.roles = updates.roles;
for(var i in updates.roles)
updated.roles.set(i, updates.roles[i]);
return updated.saveAsync()
// use `.spread()` and not `.then()` //
.spread(updated =>
return updated;
);
;
我要感谢导致此结论的以下 SOA:https://***.com/a/25799076/5994486
此外,如果有人对 .spread()
感兴趣,这里是 bluebird 文档的链接:http://bluebirdjs.com/docs/api/spread.html
【讨论】:
以上是关于Mongoose 子文档不会更新的主要内容,如果未能解决你的问题,请参考以下文章
Mongoose - 使用 findOneAndUpdate 更新子文档
更新子文档、NodeJS 和 Mongoose 的更有效方式