我使用$ pull来拉取文档数组中的子文档。
不知道它是否重要但在我的情况下,子文档包含_id所以它们被索引。
以下是描述模式的JSON:
user: {
_id: String,
items: [UserItem]
}
UserItem: {
_id: String,
score: Number
}
现在我的问题是:我使用$ pull从用户删除某些UserItem。
var delta = {$pull:{}};
delta.$pull.items={};
delta.$pull.items._id = {$in: ["mongoID1", "mongoID2" ...]};
User.findOneAndUpdate(query, delta, {multi: true}, function(err, data){
//whatever...
});
我在这里获得的数据是更改后的User对象,当我希望获得的是从阵列中删除的项目(卫星数据)。 这可以通过拨打一个mongo来完成,还是我必须做2个电话:1个发现和1个拉? 谢谢你的帮助。
答案 0 :(得分:2)
你真的不能这样做,或者至少没有任何东西能够返回任何响应中从数组中“拉出”的“实际”元素,即使较新的Bulk Operations API可以使用较新的WriteResponse对象(这是前进的方式)。
你真正做到这一点的唯一方法是“知道”你“想要”“拉”的元素,然后在修改它之前将其与文档的“原始”状态进行比较。基本的MongoDB .findAndModify()
方法允许这样做,.findByIdAndUpdate()
的mongoose包装器和.findOneAndUpdate()
也是如此。
基本使用前提:
var removing = [ "MongoId1", "MongoId2" ];
Model.findOneAndUpdate(
query,
{ "$pull": { "items._id": { "$in": removing } } },
{ "new": false },
function(err,doc) {
var removed = doc.items.filter(function(item) {
return removing.indexOf(item) != -1;
});
if ( removed.length > 0 )
console.log(removed);
}
);
或者那些东西。你基本上“转过”默认的猫鼬.findOneAndUpdate()
(与其他方法相同)的行为,并在修改之前询问“原始”文档。如果您要求“拉”的元素出现在数组中,那么您将报告它们,或者检查/返回true或其他。
因此,mongoose方法与参考实现的不同之处在于默认返回“new”文档。关闭它,然后你可以“比较”。
进一步说明:“multi”在这里不是一个有效的选项。该方法根据定义修改“一个”文档。您还要声明数组子文档包含_id
。默认情况下,这是通过“mongoose”完成的。但是,除非您在该字段上专门定义索引,否则数组中的_id
值将“未编入索引”。唯一的默认索引是“主要文档”_id
。