简体   繁体   中英

Find all n days documents in MongoDB

I've been looking to get data for the last n days. For example, I want to just all the data of the last 3 days. After implementing a solution from another question in StackOverflow I'm not getting all the documents. I am only getting one document. If I want to see the documents for the last 3 days it is only showing data for one particular day.

Here's my Schema:

dayWiseClicks: [
      {
        date: {
          type: Date,
        },
        dailyClicks: {
          type: Number,
          default: 0,
        },
      },
    ],

Here's the data I have before performing the query:

{
    "_id": {
      "$oid": "61eff4bacf8335c7013f8065"
    },
    "dayWiseClicks": [
      {
        "dailyClicks": 3,
        "_id": {
          "$oid": "61eff5db5dca56cae4530db2"
        },
        "date": {
          "$date": "2022-01-24T18:00:00.000Z"
        }
      },
      {
        "dailyClicks": 4,
        "_id": {
          "$oid": "61eff60b5dca56cae4530db6"
        },
        "date": {
          "$date": "2022-01-25T18:00:00.000Z"
        }
      },
      {
        "dailyClicks": 2,
        "_id": {
          "$oid": "61eff64a5dca56cae4530dba"
        },
        "date": {
          "$date": "2022-01-26T18:00:00.000Z"
        }
      },
      {
        "dailyClicks": 7,
        "_id": {
          "$oid": "61f60ce51f14b01f8f5be936"
        },
        "date": {
          "$date": "2022-01-29T18:00:00.000Z"
        }
      },
      {
        "dailyClicks": 11,
        "_id": {
          "$oid": "61f7b1d3931b0f8bc33703d4"
        },
        "date": {
          "$date": "2022-01-30T18:00:00.000Z"
        }
      },
      {
        "dailyClicks": 8,
        "_id": {
          "$oid": "61f8bdf63cc3a51b72474cb9"
        },
        "date": {
          "$date": "2022-01-31T18:00:00.000Z"
        }
      },
      {
        "dailyClicks": 7,
        "_id": {
          "$oid": "61fba7159692624ce8ea04d6"
        },
        "date": {
          "$date": "2022-02-02T18:00:00.000Z"
        }
      }
    ],
    
  }

In theory, if I want to see the last 3 days of data. It should be showing data of 31st Jan, 2nd February but It is only showing Data of 31st January.

Here's the data I am getting:

{
    "message": "Url By ID",
    "result": {
        "_id": "61eff4bacf8335c7013f8065",
        "dayWiseClicks": [
            {
                "dailyClicks": 8,
                "_id": "61f8bdf63cc3a51b72474cb9",
                "date": "2022-01-31T18:00:00.000Z"
            }
        ]
    }
}

Here's my Code:

exports.lastNDays = async (req, res) => {
  try {
    const url = await URL.findById(
      { _id: req.params.id },
      {
        dayWiseClicks: {
          $elemMatch: {
            date: {
              $gte: moment().add(-3, "days"),
            },
          },
        },
      }
    )
    return res.status(200).json({
      message: "Url By ID",
      result: url,
    });
  } catch (error) {
    return res.status(404).json({ error: error.message });
  }
};

Can any one tell me exactly where I am making the mistake?

The aggregation->$filter option seems more suitable for the task, example:

 db.collection.aggregate([{
$match: {
  "_id": {
    "$oid": "61eff4bacf8335c7013f8065"
     }
    }
  },
  {
   $project: {
   dayWiseClicks: {
    $filter: {
      input: "$dayWiseClicks",
      as: "item",
      cond: {
        $gte: [
          "$$item.date",
          {
            "$date": "2022-01-30T18:00:00.000Z"
          }
        ]
       }
      }
     }
    }
   }
 ])

Explained:

  1. $match single document by _id
  2. $filter only the dayWiseClicks greater or equal to certain date.

playground

If your dayWiseClicks are in natural date-ascending order (and it seems that way), then to generically capture the last 3 days of any sequence of dates can be done with $slice :

db.foo.aggregate([
    {$addFields: {dayWiseClicks: {$slice: ["$dayWiseClicks", -3]}}}
]);

You can prepend $match stages as detailed in previous answers.

NOTE: Coming up in v5.4 (available now in 5.2 rapid release for MongoDB Atlas) is the long-awaited sortArray operator. If the dayWiseClicks was not in date order, then making it that way and finding the last 3 dates is freshingly simple:

db.foo.aggregate([
    {$addFields: {dayWiseClicks: {$slice: [{$sortArray:{input: "$dayWiseClicks", sortBy: {"date":1}}, -3]}}}
]);

Similarly, to get the last 3 dates but in descending order:

db.foo.aggregate([
    {$addFields: {dayWiseClicks: {$slice: [{$sortArray:{input: "$dayWiseClicks", sortBy: {"date":-1}}, 3]}}}
]);

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