mongoose - 如何从$ pull中删除元素

时间:2014-11-12 09:22:48

标签: javascript node.js mongodb mongoose

我使用$ 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个拉? 谢谢你的帮助。

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