I have following data in my collection
{
“name": “test”,
"data": {
“statusOne”: “enabled”,
“statusTwo”: “active”
}
}
{
“name": “test”,
"data": {
“statusOne”: “disabled”,
“statusTwo”: “active”
}
}
{
“name": “another-test”,
"data": {
“statusOne”: “disabled”,
“statusTwo”: “active”
}
}
How to write an aggregation query to display the data like below. Need to group by name, statusOne, statusTwo. But segregate the result first based on name field. Then calculate the number of occurrences of statusOne and statusTwo. Both the results need to go into the same output field "data"
“output”: [
{
“name”: “test”,
"data": [
{
“status”: “active”,
“count”: 2
},
{
“status”: “disabled”,
”count”: 1
},
{
“status”: “enabled”,
”count”: 1
}
]
},
{
“name”: “another-test”,
"data": [
{
“status”: “active”,
”count”: 1
},
{
“status”: “disabled”,
”count”: 1
}
]
}
]
Tried to use group by sequence as mentioned here but no luck
[
{
$group: {
_id: {
appName: "$name”,
cs: "$data.statusOne”,
ps: "$data.statusTwo,
},
total: {
$sum: 1,
},
},
},
{
$group: {
_id: "$_id.name”,
total: { $sum: "$total" },
ps: {
$addToSet: {
name: "$_id.ps",
count: "$total",
},
},
cs: {
$addToSet: {
name: "$_id.cs",
count: "$total",
},
},
},
},
{
$project: {
_id: 0,
appName: "$_id",
items: {
$concatArrays: ["$ps", "$cs"],
},
},
},
]
2
Answers
use this and change the collection name .
Here is a generalized solution:
yields
What if there are thousands of tests and we don’t want to $unwind?
You must be careful when throwing
$unwind
into a pipeline. If the average number of statuses per test gets large (say, 100) then there will be a LOT of docs in the pipeline. Below is an alternate solution that exploits$reduce
: