kaytrance
kaytrance

Reputation: 2757

Find all documents within last n days

My daily collection has documents like:

..
{ "date" : ISODate("2013-01-03T00:00:00Z"), "vid" : "ED", "san" : 7046.25, "izm" : 1243.96 }
{ "date" : ISODate("2013-01-03T00:00:00Z"), "vid" : "UA", "san" : 0, "izm" : 0 }
{ "date" : ISODate("2013-01-03T00:00:00Z"), "vid" : "PAL", "san" : 0, "izm" : 169.9 }
{ "date" : ISODate("2013-01-03T00:00:00Z"), "vid" : "PAL", "san" : 0, "izm" : 0 }
{ "date" : ISODate("2013-01-03T00:00:00Z"), "vid" : "CTA_TR", "san" : 0, "izm" : 0 }
{ "date" : ISODate("2013-01-04T00:00:00Z"), "vid" : "CAD", "san" : 0, "izm" : 169.9 }
{ "date" : ISODate("2013-01-04T00:00:00Z"), "vid" : "INT", "san" : 0, "izm" : 169.9 }
...

I left off _id field to spare the space here. My task is to "fetch all documents within last 15 days". As you can see I need somehow to:

  1. Get 15 unique dates. The newest one should be taken as the newest document in collection (what I mean that it isn't necessary the today's date, it's just the latest one in collection based on date field), and the oldest.. well, maybe it's not necessary to strictly define the oldest day in query, what I need is some kind of top15 starting from the newest day, if you know what I mean. Like 15 unique days.
  2. db.daily.find() all documents, that have date field in that range of 15 days.

In the result, I should see all documents within 15 days starting from the newest in collection.

Upvotes: 37

Views: 50311

Answers (3)

Xavier Guihot
Xavier Guihot

Reputation: 61686

Starting in Mongo 5, it's a nice use case for the $dateSubtract operator:

// { date: ISODate("2021-12-05") }
// { date: ISODate("2021-12-02") }
// { date: ISODate("2021-12-02") }
// { date: ISODate("2021-11-28") } <= older than 5 days
db.collection.aggregate([
  { $match: {
    $expr: {
      $gt: [
        "$date",
        { $dateSubtract: { startDate: "$$NOW", unit: "day", amount: 5 } }
      ]
    }
  }}
])
// { date: ISODate("2021-12-05") }
// { date: ISODate("2021-12-02") }
// { date: ISODate("2021-12-02") }

With $dateSubtract, we create the oldest date after which we keep documents, by subtracting 5 (amount) "days" (unit) out of the current date $$NOW (startDate).

And you can obviously add a $sort stage to sort documents by date.

Upvotes: 8

Moacy Barros
Moacy Barros

Reputation: 1947

I just tested the following query against your data sample and it worked perfectly:

db.datecol.find(
{
    "date": 
    {
        $gte: new Date((new Date().getTime() - (15 * 24 * 60 * 60 * 1000)))
    }
}
).sort({ "date": -1 })

Upvotes: 95

Aravind Yarram
Aravind Yarram

Reputation: 80194

You need to run the distinct command to get all the unique dates. Below is the example. The "values" array has all the unique dates of the collection from which you need to retrieve the most recent 15 days on the client side

db.runCommand ( { distinct: 'datecol', key: 'date' } )
{
    "values" : [
       ISODate("2013-01-03T00:00:00Z"),
       ISODate("2013-01-04T00:00:00Z")
    ],
    "stats" : {
       "n" : 2,
       "nscanned" : 2,
       "nscannedObjects" : 2,
       "timems" : 0,
       "cursor" : "BasicCursor"
    },
    "ok" : 1
}

You then use the $in operator with the most recent 15 dates from step 1. Below is an example that finds all documents that belong to one of the mentioned two dates.

db.datecol.find({
  "date":{
     "$in":[
        new ISODate("2013-01-03T00:00:00Z"), 
        new ISODate("2013-01-04T00:00:00Z")
      ]
  }
})

Upvotes: -1

Related Questions