简体   繁体   中英

MongoDB Find documents created in past 7 days and return 0 on days where no document was created

I'm trying to find documents from last 7 days in my Mongo Database.

I'm able to receive data in desired format where specific date and numOfTickets created on that given date are returned:

{
    "datesUsed": {
        "startDate": "2022-04-02T14:42:14.223Z",
        "endDate": "2022-04-09T14:42:14.223Z"
    },
    "data": [
        {
            "date": "02/04/2022",
            "numOfTickets": 1
        },
        {
            "date": "03/04/2022",
            "numOfTickets": 1
        },
        {
            "date": "04/04/2022",
            "numOfTickets": 2
        },
        {
            "date": "06/04/2022",
            "numOfTickets": 1
        },
        {
            "date": "07/04/2022",
            "numOfTickets": 1
        },
        {
            "date": "08/04/2022",
            "numOfTickets": 2
        },
        {
            "date": "09/04/2022",
            "numOfTickets": 1
        }
    ]
}

The problem is that Mongo only returns data on days where a document was created, but returns nothing on days where no document was created - in this case 05/04/2022.

What I'm trying to achieve is to also include another JSON object that would say something in these terms:

{
            "date": "05/04/2022",
            "numOfTickets": 0
}

This is what I have so far:

const companyId = req.query.companyId;
    let dates = [];
    const data = [];
    // Last 7 days
    const endDate = new Date();
    const startDate = new Date(Date.now() - 604800000);

    // Find tickets from past 7 days
    const allCompanyTickets = await ticketModel
      .find({
        company_id: companyId,
        createdAt: { $gte: new Date(startDate), $lte: new Date(endDate) },
      })
      .sort({ createdAt: 1 });

      console.log(allCompanyTickets)

    // Push them to an array
    allCompanyTickets.forEach((ticket) => {
      dates.push(ticket.createdAt.toLocaleDateString());
    });

    // Count occurences of days in the dates array
    function countOccurrences(arr) {
      return arr.reduce(function (a, b) {
        a[b] = a[b] + 1 || 1;
        return a;
      }, []);
    }

    // Make an object from the data above
    const datesOrdered = countOccurrences(dates);

    // Give the data above keys and push it to a new array
    for (let key in datesOrdered) {
      const tempObj = { date: key, numOfTickets: datesOrdered[key] };
      data.push(tempObj);
    }

    res.status(200).json({ datesUsed: { startDate, endDate }, data: data });

Something like this

db.ticketModel.aggregate([
  {
    $set: {
      datesUnused: {
        $range: [ 0, { $dateDiff: { startDate: "$startDate", endDate: "$endDate", unit: "day" } } ]
      }
    }
  },
  {
    $set: {
      datesUnused: {
        $map: {
          input: "$datesUnused",
          in: { 
            date: { 
               $dateAdd: { 
                  startDate: { $dateTrunc: { date: "$datesUsed.startDate", unit: "day" }, 
                  unit: "day", 
                  amount: "$$this" 
               } 
            },
            numOfTickets: 0
          }
        }
      }
    }
  },
  {
    $set: {
      data: {
        $filter: {
          input: "$datesUnused",
          cond: { $not: { $in: [ "$$this.date", "$data.date" ] } }
        }
      }
    }
  }
])

Mongo Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM