Reputation: 11776
Say I have the following 5 documents in a collection:
{"account_id": 11, "event": ISODate("2021-05-03T10:33:18.220Z")},
{"account_id": 11, "event": ISODate("2021-05-03T10:33:19.220Z")},
{"account_id": 11, "event": null},
{"account_id": 99, "event": ISODate("2021-05-03T10:33:20.220Z")},
{"account_id": 99, "event": null}
In a single aggregate
query I'd like to retrieve:
acccount_id: 11
(3)acccount_id: 11
AND event
being not null (2)Essentially, what I'm looking for as a result is this:
{ total: 3, with_event: 2 }
Below is the code I have that satisfies the second point from the above. It matches account_id and event
type of 9 which is date time in Mongo. How do I extend this code to also satisfy point 1?
mongo.accounts.aggregate([
{
"$match": {
"account_id": 11,
"event": {
"$type": 9
}
}
},
{
"$group": {
"_id": null,
"count": {
"$sum": 1
}
}
}
])
Upvotes: 1
Views: 31
Reputation: 36104
You can use $facet
operator to separate both conditions and result,
$match
condition for account_id
total
, $group
by null and count total documentwith_event
match for event and $group
by null and count total document$project
to show required fields, get first element from facet resultmongo.accounts.aggregate([
{ $match: { account_id: 11 } },
{
$facet: {
total: [
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
],
with_event: [
{ $match: { event: { $type: 9 } } },
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
]
}
},
{
$project: {
total: { $arrayElemAt: ["$total.count", 0] },
with_event: { $arrayElemAt: ["$with_event.count", 0] }
}
}
])
Second approach:
$match
condition for account_id
$group
by null and get total
document, and for event
check condition if type is date then count 1 otherwise 0mongo.accounts.aggregate([
{ $match: { account_id: 11 } },
{
$group: {
_id: null,
total: { $sum: 1 },
with_event: {
$sum: {
$cond: [{ $eq: [{ $type: "$event" }, "date"] }, 1, 0]
}
}
}
}
])
Upvotes: 2