Given the following data in a Mongo collection:
{
_id: "1",
dateA: ISODate("2021-12-31T00:00.000Z"),
dateB: ISODate("2022-01-11T00:00.000Z")
},
{
_id: "2",
dateA: ISODate("2022-01-02T00:00.000Z"),
dateB: ISODate("2022-01-08T00:00.000Z")
},
{
_id: "3",
dateA: ISODate("2022-01-03T00:00.000Z"),
dateB: ISODate("2022-01-05T00:00.000Z")
},
{
_id: "4",
dateA: ISODate("2022-01-09T00:00.000Z"),
dateB: null
},
{
_id: "5",
dateA: ISODate("2022-01-11T00:00.000Z"),
dateB: ISODate("2022-01-11T00:00.000Z")
},
{
_id: "6",
dateA: ISODate("2022-01-12T00:00.000Z"),
dateB: null
}
And given the range below:
ISODate("2022-01-01T00:00.000Z") .. ISODate("2022-01-10T00:00.000Z")
I want to find all values with dateA
within given range, then I want to decrease the range starting it from the max dateB
value, and finally fetching all documents that doesn’t contain dateB
.
In resume:
I’ll start with range
ISODate("2022-01-01T00:00.000Z") .. ISODate("2022-01-10T00:00.000Z")
Then change to range
ISODate("2022-01-08T00:00.000Z") .. ISODate("2022-01-10T00:00.000Z")
Then find with
dateB: null
Finally, the result would be the document with
_id: "4"
Is there a way to find the document with _id: "4"
in just one aggregate?
I know how to do it programmatically using 2 queries, but the main goal is to have just one request to the database.
2
Answers
You can use
$max
to find the maxDateB first. Then perform a self$lookup
to apply the$match
and find doc_id: "4"
.Here is the Mongo Playground for your
Assuming the matched initial
dateA
range is not huge, here is alternate approach that exploits$push
and$filter
and avoids the hit of a$lookup
stage:This yields a single doc result (I added an additional doc _id 41 to test the null equality for more than 1 doc):
It is possible to
$unwind
and$replaceRoot
after this but there is little need to do so.