我正在使用 $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 来完成,还是我必须调用 2 次:1 次查找和 1 次 $pull?
感谢您的帮助。
最佳答案
你真的不能这样做,或者至少没有任何东西会返回在任何响应中从数组中“拉出”的“实际”元素,即使更新的 WriteResponse 对象可用于更新的批量操作 API (这是前进的方向)。
真正做到这一点的唯一方法是“了解”您“打算”“拉出”的元素,然后将其与文档修改前的“原始”状态进行比较。基本的 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);
}
);
或者类似的东西。您基本上“扭转”默认 Mongoose .findOneAndUpdate()
(其他方法相同)行为并在修改之前要求“原始”文档。如果您要求“拉取”的元素存在于数组中,那么您将报告它们,或检查/返回 true 或其他任何内容。
所以 mongoose 方法与引用实现不同,默认返回"new"文档。关闭它,然后你就可以“比较”了。
进一步说明:“multi”在这里不是一个有效的选项。该方法根据定义修改“一个”文档。您还声明数组子文档包含一个 _id
。这是默认情况下由“mongoose”完成的。但是数组中的那些 _id
值是“未编入索引”的,除非您在该字段上专门定义了一个索引。唯一的默认索引是“主文档”_id
。
关于javascript - mongoose - 如何从 $pull 中删除元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26883326/