基于日期更新Mongoose文档字段——投标Schema场景技术求助
Hey David, let's walk through how to add date-based field updates for your Bid Mongoose schema. I’ll cover the most practical approaches based on common use cases:
If you need to automatically update bids on a fixed schedule (e.g., mark pending bids as disapproved after 7 days), a cron job is the way to go. This ensures your data stays consistent without relying on user interactions.
Step 1: Install the cron package
npm install node-cron
Step 2: Set up the cron task
Create a script (or add this to your server initialization code) to run the update job:
const cron = require('node-cron'); const Bid = require('./models/Bid'); // Adjust to your Bid model path // Run every day at 1 AM (adjust the cron expression to your needs) cron.schedule('0 1 * * *', async () => { try { // Calculate the cutoff date (e.g., 7 days ago) const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - 7); // Bulk update all pending bids created before the cutoff const updateResult = await Bid.updateMany( { status: 'Pending', createdAt: { $lt: cutoffDate } // Uses the timestamp from mongoose-timestamps }, { $set: { status: 'Disapproved' } } ); console.log(`Updated ${updateResult.modifiedCount} expired pending bids`); } catch (error) { console.error('Failed to update bids:', error); } });
Notes:
- Use a process manager like PM2 to keep your Node.js server running (so the cron job doesn’t stop when the server restarts).
- Adjust the cron expression (
0 1 * * *) to match your desired schedule (e.g.,*/30 * * * *runs every 30 minutes).
If you don’t need real-time batch updates, you can update fields dynamically when a bid is accessed. This is lighter weight and avoids running background tasks.
Option A: Mongoose Pre-Query Middleware
Add a pre-find hook to your schema to check and update the bid before it’s returned to the client:
const BidSchema = new Schema({ // Your existing schema fields... }); // Hook runs before any findOne query BidSchema.pre('findOne', async function(next) { // Clone the query to avoid infinite loops const bidDoc = await this.findOne().clone(); if (bidDoc) { const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - 7); // Update if the bid is pending and expired if (bidDoc.status === 'Pending' && bidDoc.createdAt < cutoffDate) { await Bid.findByIdAndUpdate(bidDoc._id, { status: 'Disapproved' }); } } next(); }); // Don't forget to apply timestamps and create the model BidSchema.plugin(timestamps); const Bid = mongoose.model('Bid', BidSchema);
Option B: Business Logic Layer Handling
Update the bid directly in your service/controller when fetching it:
async function fetchBidById(bidId) { const bid = await Bid.findById(bidId); if (!bid) throw new Error('Bid not found'); const expiryDate = new Date(bid.createdAt); expiryDate.setDate(expiryDate.getDate() + 7); // 7-day expiry window if (bid.status === 'Pending' && new Date() > expiryDate) { bid.status = 'Disapproved'; await bid.save(); } return bid; }
If your goal was to delete expired bids instead of updating fields, you can use a TTL index. Note this only deletes documents, not updates fields:
// Add this to your schema to auto-delete bids 7 days after creation BidSchema.index({ createdAt: 1 }, { expireAfterSeconds: 604800 }); // 604800 seconds = 7 days
- Ensure
mongoose-timestampsis correctly applied to your schema (it addscreatedAtandupdatedAtfields automatically). - If you’re using a custom deadline field (e.g.,
bidDeadlineinstead ofcreatedAt), just swap that in your query conditions. - For bulk updates, always use
updateManyinstead of looping through individual documents—it’s far more efficient.
内容的提问来源于stack exchange,提问作者David Lasry

