I'm trying to build a aggregation query but when I use $match
with dates, it doesn't work as I expect. If I use other fields instead of any Date
field, it works as expected. The code examples I'm using is below:
const res = await Reservation.aggregate([{ $match: { createdAt: { $lte: req.endDate } } }]).exec();
const res = await Reservation.find({ createdAt: { $lte: req.endDate } }).exec();
The first line doesn't work but the second one works perfectly. What is the difference between .find()
and .aggregate()
. Thanks for your help!
Mongoose has "schemas" for which it does this magic thing called "autocasting" for you. The typical case the designer(s) have in mind here is that all input from "web" interations like
GET
andPOST
is basically contained in a "string".Whether or not there is some helper that that makes paramters into objects with keys and values, all those "values" are still "strings", or possibly made directly numeric by the same "helpers" where appropriate. This is common web framework design.
So when you issue a
.find()
, this function is completely incapable of altering the returned content other than by omission for fields/properties, so hence the "schema" is applied.The
.aggregate()
method is entirely different. It's entire existence is to modify content contained in documents and collections. The consequence of this is that it is "impossible" for a schema to apply.Hence, the "autocasting" present in methods like
.find()
does not happen, and you are required to cast elements ( such as the "string" your "date" is being sent in as ) to the correct types yourself:Even if all you are doing is a
$match
and that you have not "modified" the schema in any way, mongoose does not "presume" this and does not attempt to cast to the matching field in the schema.The logic here is that a
$match
stage or anything similar that could be bound to a "type", could occur anywhere within the pipeline. As such there is no guarantee that the documents being acted on by a pipeline stage bear any resemblance to the original collection schema.Arguably it "could" possibly consider the fact that this is the first pipeline stage where nothing could possibly have changed and do a similar inspection. But that is not how the current code base worked.
So in short, when using the aggregation pipeline, all objects that need to be specifically cast to a type ( Date, ObjectId, etc ) need to be "manually" cast in your code, rather than assuming mongoose is going to do it for you like in other methods.