如何编写MongoDB查询以获取滚动近7天的动态日期数据
Got it, let's break down how to handle rolling 7-day data queries and dynamic date filtering in MongoDB—this is a super common use case, so I'll walk you through step by step with practical examples.
First, let's cover the core logic for fetching data from the last 7 days. The key is calculating the cutoff date (7 days prior to the current time) and filtering your collection against it.
Basic Time-Based Query (Real-Time Cutoff)
This gets all records created from exactly 7 days ago right up to now:
db.yourCollection.find({ createdAt: { $gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // 7 days ago (in milliseconds) $lt: new Date() // Up to the current moment } })
Date-Only Cutoff (00:00:00 to 00:00:00)
If you want to align with calendar days (e.g., from 7 days ago at midnight to today at midnight), manually adjust the date object to strip time components:
// Calculate start of 7 days ago const sevenDaysAgoStart = new Date(); sevenDaysAgoStart.setDate(sevenDaysAgoStart.getDate() - 7); sevenDaysAgoStart.setHours(0, 0, 0, 0); // Calculate start of today const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); db.yourCollection.find({ createdAt: { $gte: sevenDaysAgoStart, $lt: todayStart } })
To make this flexible (e.g., fetch last N days, or a custom date range), wrap the logic in reusable functions or accept dynamic parameters.
Dynamic "Last N Days" Query
Create a function that takes a number of days as input:
function getLastNDaysData(collectionName, days) { const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000); return db.getCollection(collectionName).find({ createdAt: { $gte: cutoffDate } }).sort({ createdAt: -1 }); // Sort newest first } // Example: Fetch last 30 days of data getLastNDaysData("yourCollection", 30);
Custom Date Range Query
If you need to accept arbitrary start/end dates (e.g., user-selected ranges), add logic to parse and validate date inputs:
function getDateRangeData(collectionName, startDate, endDate) { // Convert string inputs to valid Date objects const start = typeof startDate === 'string' ? new Date(startDate) : startDate; const end = typeof endDate === 'string' ? new Date(endDate) : endDate; // Guard against invalid dates if (isNaN(start.getTime()) || isNaN(end.getTime())) { throw new Error("Invalid start or end date"); } return db.getCollection(collectionName).find({ createdAt: { $gte: start, $lt: end // Use $lt to exclude the end date's time component } }); } // Example: Fetch data from Jan 1, 2024 to Jan 10, 2024 getDateRangeData("yourCollection", "2024-01-01", "2024-01-11");
MongoDB stores dates in UTC by default. If your business uses a local time zone (e.g., Asia/Shanghai), adjust the query to account for offsets:
Using Aggregation with Time Zones (MongoDB 5.0+)
Leverage $dateSubtract and $dateAdd to handle time zones natively:
db.yourCollection.aggregate([ { $match: { createdAt: { $gte: { $dateSubtract: { startDate: "$$NOW", unit: "day", amount: 7, timezone: "Asia/Shanghai" } }, $lt: "$$NOW" } } } ])
If you're rolling through large volumes of data, avoid using skip() (it's inefficient for large offsets). Instead, paginate using the last document's date:
// Fetch first page of 7-day data (newest first) const firstPage = db.yourCollection.find({ createdAt: { $gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) } }).sort({ createdAt: -1 }).limit(100).toArray(); // Fetch next page using the last document's createdAt as the cutoff function getNextPage(collectionName, lastDocumentDate, pageSize = 100) { return db.getCollection(collectionName).find({ createdAt: { $gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), $lt: lastDocumentDate } }).sort({ createdAt: -1 }).limit(pageSize).toArray(); } // Example: Get second page const secondPage = getNextPage("yourCollection", firstPage[firstPage.length - 1].createdAt);
内容的提问来源于stack exchange,提问作者Anuj Mishra

