After grouping in aggregation I have elements that look the following way:
{_id: ID, items: ["yes", "no", "yes", "no", "no", "yes", "no", "no", "no"]}
I'd like to project how many times is certain value present in items array
To end up with a document in the format of:
{_id: ID, yes: 3, no: 6}
答案 0 :(得分:2)
Use a combination of $filter
and $size
operators to filter the items array based on a given condition and return the count respectively. For example, run the following pipeline to get the desired result. Of course this assumes the distinct binary elements from the items list "yes"
and "no"
are known beforehand:
db.collection.aggregate([
{
"$project": {
"yes": {
"$size": {
"$filter": {
"input": "$items",
"as": "item",
"cond": {
"$eq": ["$$item", "yes"]
}
}
}
},
"no": {
"$size": {
"$filter": {
"input": "$items",
"as": "item",
"cond": {
"$eq": ["$$item", "no"]
}
}
}
}
}
}
])
For a solution where the distinct elements are not known in advance, then you would need to $unwind
the items array, group the flattened documents and aggregate the counts as:
db.collection.aggregate([
{ "$unwind": "$items" },
{
"$group": {
"_id": "$items",
"id": { "$first": "$_id" },
"count": { "$sum": 1 }
}
},
{
"$group": {
"_id": "$id",
"counts": {
"$push": {
"item": "$_id",
"count": "$count"
}
}
}
}
])
Sample Output
{
"_id" : ID,
"counts" : [
{
"item" : "yes",
"count" : 3
},
{
"item" : "no",
"count" : 6
}
]
}
答案 1 :(得分:0)
You could add two more phase to your aggregation pipeline
{ $unwind: '$items' }
Then group by items
again,
{ $group: { _id: '$items', count: { $sum: 1 }}}
This will generates an array like:
[{ _id: 'yes', count: 3}, { _id: 'no', count: 6}]
答案 2 :(得分:0)
db.collection.aggregate([
"$project" : {
_id : 1,
"yes" : {
$size : {
"$map" : {
input : "$items",
as : "Yes",
in : {"$eq" : ["$$Yes","yes"]}
}
}
}
"no" : {
"$size" : {
"$map" : {
input : "$items",
as : "No",
in : {"$eq" : ["$$No","no"]}
}
}
}
}
])