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

Javascript mongoose-如何从$pull中删除元素,javascript,node.js,mongodb,mongoose,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={}; delt

我使用$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...
});
这里我在数据中得到的是更改后的用户对象,而我希望得到的是从阵列中删除的项目(卫星数据)。 这可以通过一次呼叫mongo来完成,还是我必须进行两次呼叫:1次查找和1次$pull?

感谢您的帮助。

您真的无法做到这一点,或者至少不会返回任何响应中从数组中“提取”的“实际”元素,即使新的批量操作API提供了新的WriterResponse对象(这是一种前进的方式)

真正做到这一点的唯一方法是“知道”要“拉”的元素,然后将其与文档修改前的“原始”状态进行比较。基本的MongoDB方法允许这样做,以及的mongoose包装器和

基本使用前提:

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);
    }
);
或者类似的东西。基本上,您可以“扭转”默认mongoose
.findOneAndUpdate()
(与其他方法相同)行为,并在修改“原始”文档之前请求它。如果请求“拉”的元素存在于数组中,则报告它们,或检查/返回true或其他内容

因此,mongoose方法与参考实现不同,默认情况下返回“新”文档。关闭此选项,然后可以“比较”


进一步说明:“多”在此处不是有效选项。该方法根据定义修改“一个”文档。您还可以声明数组子文档位于
\u id
中。默认情况下,这是由“猫鼬”完成的。但是数组中的那些
\u id
值是“未索引”的,除非您在该字段上专门定义索引。唯一的默认索引是“主文档”
\u id

,根据这一点,唯一的方法可能是执行javascript并将其加载到mongo。但我如何从猫鼬身上做到这一点@TzaliMaimon不,您不需要将代码加载到服务器,这样做是非常不明智的。我不确定你在这里不清楚什么,所以也许你需要再次阅读答案。它将“原始”内容与您要求删除的内容进行比较。这样你才能知道什么“已经”被删除了。到时候我会说清楚的。你建议做的事不切实际。因为我的子文档是索引的,所以这只意味着我正在尝试使用O(1)中的CRUD ID执行所有CRUD操作。你要我做的是在O(n)中搜索我删除的内容。所以你的解决方案对我来说是非常清楚的,只是我的问题要求你不能接受。现在请您发表评论:您说将代码加载到mongo是不明智的。你能链接一篇关于这个主题的文章或解释原因吗?感谢you@TzaliMaimon文档修改一次。返回与修改发生在同一个电汇事务中。您将返回原始表单,并且在文档被修改之前要求更新的内容将告诉您修改的实际内容。非常简单。关于你的回答,你不明白我在说什么:我没有说文档的更新发生了n次。看看你的代码。查看过滤器功能?这意味着您要遍历文档数组字段中的所有项,以搜索与您删除的项匹配的项。因此,如果我有一个由n个项组成的数组,则需要O(n)次才能在数组中找到该元素。用你的话来说很“简单”。