Mongoose从集合中除指定文档外批量移除用户ID的实现
Got it, let's break down how to solve this problem properly. You want to remove a specific user ID from the vote arrays in your MongoDB documents, but you need to exclude any document where value is 'Тата'. Here's a clean, efficient Mongoose implementation that replaces your current route logic:
Updated Route Code
router.post('/', passport.authenticate('jwt', {session: false}), async (req, res) => { try { // Destructure values for cleaner code const { value: targetValue, habalkaId } = req.body; const userId = String(req.user._id); // Check if the target value exists (matches your original logic) const existingDoc = await FirstName.findOne({ value: targetValue }); if (existingDoc) { // Logs for debugging (keep these if you need them) console.log(existingDoc); console.log(req.body); console.log(userId); // Batch update all documents EXCEPT those with value: 'Тата' const updateResult = await FirstName.updateMany( { value: { $ne: 'Тата' }, // Exclude the 'Тата' documents [`vote.${habalkaId}`]: userId // Only target docs where the user ID exists in the array }, { $pull: { [`vote.${habalkaId}`]: userId // Remove the user ID from the specific vote array } } ); console.log(`Successfully updated ${updateResult.modifiedCount} documents`); return res.json({ success: true, message: `Removed user ID from ${updateResult.modifiedCount} documents` }); } else { // Create new document as you originally did const newFirstName = new FirstName({ value: targetValue, vote: { [habalkaId]: [userId] } }); await newFirstName.save(); return res.json({ success: true, message: 'New document created', doc: newFirstName }); } } catch (err) { console.error('Error during operation:', err); return res.status(500).json({ success: false, error: 'An error occurred while processing your request' }); } });
Key Details & Improvements
- Async/Await: Replaces callback hell with cleaner, more readable code that's easier to debug.
- Batch Updates: Uses Mongoose's
updateMany()instead of fetching all documents and looping through them. This is far more efficient, especially as your collection grows. - Targeted Filtering: The query
{ value: { $ne: 'Тата' }, [vote.${habalkaId}]: userId }ensures we only touch documents that:- Don't have
value: 'Тата' - Actually contain the user ID we want to remove (avoids unnecessary updates)
- Don't have
- $pull Operator: MongoDB's native
$pullis designed specifically for removing elements from arrays—it's reliable and handles edge cases (like duplicate IDs) automatically.
Optional: Clean Up Empty Vote Keys
If you want to remove the habalkaId key from the vote object once its array is empty (after removing the user ID), add this right after the updateMany() call:
// Remove empty vote arrays await FirstName.updateMany( { value: { $ne: 'Тата' }, [`vote.${habalkaId}`]: { $size: 0 } // Target arrays that are now empty }, { $unset: { [`vote.${habalkaId}`]: "" } // Delete the empty key } );
Notes on Your Model
Your existing FirstNameSchema works perfectly for this use case—since vote is defined as an Object, Mongoose supports dynamic keys like the habalkaId values you're using.
内容的提问来源于stack exchange,提问作者Стас Рябцев
相关产品推荐
相关产品推荐

