MongoDb bulkWrite没有在nodejs中更新我的文档



我第一次尝试使用MondodDBbulkWrite。我想更新多个文档并删除与我提供的过滤器匹配的ID。我读到我可以使用MongoDBbulkWrite来执行此操作。对于这个应用程序,有一个Post模型和User模型。Post模型有一个名为postLikes的对象值,它包含一个点赞数组。这些点赞只是点赞帖子的用户的userId。因此,我想在删除所选用户时从postLikes数组中删除他们的ID。要删除的选定用户可能超过2个。当它们被选中时,它们的ids将作为数组传递到名为selectedIds的变量中的后端。我想更新Post模型并将其从postLikes阵列中删除的正是这些ids。只有当存在所选用户的点赞时,才会发生这种情况。

它是一个MERN堆栈应用程序。这是我的代码:

const deleteSelectedUsers = async (req, res)=>{
const {selectedIds} = req.body;// this is an array of selected ids sent from frontend
//find all posts
const posts = await Post.find();
//get filter and return all posts with likes.
const filteredPost = posts.filter((singleFilter) => singleFilter.postLikes.length !== 0)
const updatedPosts = filteredPost.map((obj)=>{

selectedIds.map((single)=>{
//this checks to ensure that there is a like by the user and only that id is removed
if(obj.postLikes.includes(single)){
return {
updateOne: {
filter: { _id: obj._id },
update: { $pull: { postLikes: single } },
},
};
}
//console.log(obj.postLikes.includes(single))
})
})
Post.bulkWrite(updatedPosts).then((res) => {
console.log("Documents Updated", res.modifiedCount)
})

}
}

此代码根本没有响应,也没有进行更新。我怎样才能最好地做到这一点?

这是因为在另一个.map中使用.map,而在第一个.map中甚至没有使用return。这将生成一个undefined值的数组。根据我对这个问题的理解,更好的解决方案是:

const findIntersection = (array1, array2) => {
return array1.filter((elem) => {
return array2.indexOf(elem) !== -1;
});
}
const filteredPost = posts.filter((singleFilter) => {
const intersection = findIntersection(selectedIds, singleFilter.postLikes);
return singleFilter.postLikes.length !== 0 && intersection.length !== 0;
});
const updatedPosts = filteredPost.map((obj)=>{
const intersection = findIntersection(selectedIds, obj.postLikes);
return {
updateOne: {
filter: { _id: obj._id },
update: { $pull: { postLikes: { $in: intersection } } },
},
};
});

有了更新后的代码,updatedPosts现在包含了正确的mongoose/mongodb命令。注意此处$in的使用。由于您希望从postLikes中删除多个匹配值,而不是为每个匹配值创建单独的updateOne,因此我们将使用$in在单个udpateOne中发送所有这些值。

您可以进一步精简代码,这样可以避免找到交集,因为$in负责处理该部分。{$pull : { postLikes: { $in: [...] }}}将确保,如果数组中的值与指定数组中的任何元素匹配,它将删除该元素。示例:

const updatedPosts = filteredPost.map((obj)=>{
return {
updateOne: {
filter: { _id: obj._id },
update: { $pull: { postLikes: { $in: selectedIds } } },
},
};
});

所以,这就是我在几乎放弃后解决问题的方法。我将管理员选择的ID存储在一个变量中,如下所示:

cost {selectedIds} = req.body;

我首先找到了所有可用的帖子,如下所示:

const posts = await Post.find();

然后,我过滤掉了根本没有点赞的帖子:

const filteredPost = posts.filter((singleFilter) => singleFilter.postLikes.length !== 0)

我返回了过滤后的帖子ID如下:

const newPost = filteredPost.map((singleMap) => singleMap._id);

然后,我从过滤后的帖子中删除了选定用户的id;postLikes像这样使用猫鼬方法:

const updated = await Post.updateMany({ _id: {$in:  newPost} }, { $pull: { postLikes: { $in: selectedIds } } })

我发现在传递过滤后的posts id时需要使用mongoose$in。一切都很好。这可以帮助任何面临类似挑战的人。

最新更新