Query for nested groups and push in mongodb - mongodb

I am trying mongoDB for first time. I need to aggregate my data from one collection to another. Trying this code but it doesn't execute because of unexpected error :
"unexpected expression $group"
db.import.aggregate([{
$group: {
_id: {
day: "$Day",
month: "$Month",
year: "$Year"
},
manufacturers: {
$push: {
$group: {
_id: {
manID: "$Man_ID",
man_name: "$Man_Name"
},
types: {
$push: {
model_name: "$Model_name",
body_type: "$Body_type"
}
}
}
}
}
}
},
{ $out: "output_doc" }
], {
allowDiskUse: true,
cursor: {}
});
Expected Output:
["$Day","$Month","$Year",
["$Man_ID","$Man_Name",
["$Model_name","$Body_type"]
]
]

You can just push your new _id field and create your types array without any operator :
db.import.aggregate([{
$group: {
_id: {
day: "$Day",
month: "$Month",
year: "$Year"
},
manufacturers: {
$push: {
_id: {
manID: "$Man_ID",
man_name: "$Man_Name"
},
types: [{ model_name: "$Model_name", body_type: "$Body_type" }]
}
}
}
}])

Related

How to calculate average records per month?

My records like this [{ createdAt }, {createdAt}, {createdAt} ]
I need average records per month.
january => 3 records
february => 2 records etc..
You can try to $group by month and year when counting and by month when averaging:
db.collection.aggregate([
{
$group: {
_id: {
month: {
$month: "$createdAt"
},
year: {
$year: "$createdAt"
},
},
count: {
$sum: 1
}
}
},
{
$group: {
_id: {
month: "$_id.month"
},
average: {
$avg: "$count"
}
}
},
{
$project: {
_id: 0,
month: "$_id.month",
average: 1
}
}
])
Link to playground
Not fully clear what you mean by "average records per month" but I think it would be this:
db.collection.aggregate([
{
$group: {
_id: {
$dateTrunc: {
date: "$createdAt",
unit: "month"
}
},
count: { $count: {} }
}
},
{
$group: {
_id: null,
data: { $push: { k: { $toString: { $month: "$_id" } }, v: "$count" } }
}
},
{ $replaceWith: { $arrayToObject: "$data" } }
])
Getting the month name is not so easy, either you use a external library or build your own with $switch

Mongodb aggregate grouping elements of an array type field

I have below data in my collection:
[
{
"_id":{
"month":"Jan",
"year":"2022"
},
"products":[
{
"product":"ProdA",
"status":"failed",
"count":15
},
{
"product":"ProdA",
"status":"success",
"count":5
},
{
"product":"ProdB",
"status":"failed",
"count":20
},
{
"product":"ProdB",
"status":"success",
"count":10
}
]
},
...//more such data
]
I want to group the elements of products array on the name of the product, so that we have record of how what was the count of failure of success of each product in each month. Every record is guaranteed to have both success and failure count each month. The output should look like below:
[
{
"_id":{
"month":"Jan",
"year":"2022"
},
"products":[
{
"product":"ProdA","status":[{"name":"success","count":5},{"name":"failed","count":15}]
},
{
"product":"ProdB","status":[{"name":"success","count":10},{"name":"failed","count":20}]
}
]
},
...//data for succeeding months
]
I have tried to do something like this:
db.collection.aggregate([{ $unwind: "$products" },
{
$group: {
"_id": {
month: "$_id.month",
year: "$_id.year"
},
products: { $push: { "product": "$product", status: { $push: { name: "$status", count: "$count" } } } }
}
}]);
But above query doesn't work.
On which level I need to group fields so as to obtain above output.
Please help me to find out what I am doing wrong.
Thank You!
Your first group stage needs to group by both the _id and the product name, aggregate a list of status counts and then another group stage which then forms the products list:
db.collection.aggregate([
{$unwind: "$products"},
{$group: {
_id: {
id: "$_id",
product: "$products.product",
},
status: {
$push: {
name: "$products.status",
count: "$products.count"
}
}
}
},
{$group: {
_id: "$_id.id",
products: {
$push: {
product: "$_id.product",
status: "$status"
}
}
}
}
])
Mongo Playground

How to group mongodb aggregate array of objects data To sum numbers on the same date

I'm trying to create charts but I can't combine the data to be like "Expected result below"
What can I use to return "Expected result".
I tried using $group in $group and $reduce and it didn't work well.
I hope someone can help me solve this task
Current result is
[
{
"_id":"5fd4c3586e83b334d97c5218",
"consumption":5,
"charts":[
{
"date":"2020-10",
"consumption":1
},
{
"date":"2020-10",
"consumption":1
},
{
"date":"2020-11",
"consumption":1
},
{
"date":"2020-11",
"consumption":1
}
]
}
]
Expected result is
[
{
"_id":"5fd4c3586e83b334d97c5218",
"consumption":5,
"charts":[
{
"date":"2020-10",
"consumption":2
},
{
"date":"2020-11",
"consumption":2
},
}
]
You need to go with aggregations
db.collection.aggregate([
{ $unwind: "$charts" },
{
$group: {
_id: { _id: "$_id", month: "$charts.date.month", year: "$charts.date.year" },
consumption: { $first: "$consumption" },
total: { $sum: "$charts.consumption" },
date: { $first: "$charts.date" }
}
},
{
$group: {
_id: "$_id._id",
consumption: { $first: "$consumption" },
charts: {
$push: {
date: "$date",
consumption: "$total"
}
}
}
}
])
Working Mongo playground

MongoDB Aggregate Query, Logins Averages

let pipeline = [{
$match: {
time: { $gt: 980985600 },
user_id: mongoose.Types.ObjectId("60316a2e7641bd0017ced7b1")
}
},
{
$project: {
newDate: { '$toDate': "$time" },
user_id: '$user_id'
}
},
{
$group: {
_id: { week: { $week: "$newDate" }, year: { $year: "$newDate" }},
count: { $sum: 1 }
}
}]
I am currently trying to perform an aggregate through mongoose to find the average logins per week for a specific user. So far I have been able to get to the total number of logins each week, but was curious if there was a way to find the average of these final groupings within the same function. How would I go about doing this?
Just add one last stage to your query:
{
$group: {
_id: null,
avg: { $avg: "$count" }
}
}
So try this:
let pipeline = [
{
$match: {
time: { $gt: 980985600 },
user_id: mongoose.Types.ObjectId("60316a2e7641bd0017ced7b1")
}
},
{
$project: {
newDate: { '$toDate': "$time" },
user_id: '$user_id'
}
},
{
$group: {
_id: { week: { $week: "$newDate" }, year: { $year: "$newDate" } },
count: { $sum: 1 }
}
},
{
$group: {
_id: null,
avg: { $avg: "$count" }
}
}
];

How to get sum of counted records using group by in mongodb?

I am trying to get the sum of count which I get from group, match. How can I get the same.
I have this code...
VisitorCompany.aggregate(
[
{
$match: {
$and:[
{ entry_date: { $gt: start, $lt: end } }
]
}
},
{
$group:
{
_id:
{
day: { $dayOfMonth: "$entry_date" },
month: { $month: "$entry_date" },
year: { $year: "$entry_date" }
},
count: { $sum:1 },
entry_date: { $first: "$entry_date" }
}
},
{
$project:
{
entry_date:
{
$dateToString: { format: "%Y-%m-%d", date: "$entry_date" }
},
count: 1,
_id: 0
}
},
{ $sort : { entry_date : -1 } },
])
and the output is ...
{
"count": 2,
"entry_date": "2018-12-12"
},
{
"count": 1
"entry_date": "2018-12-11"
}
Is anyone have idea that how to get sum of count i.e. 3 (2+1), means total number of records before group. thanks in advance.
Below modified query of yours will be giving you the sum of count, I have just added the
$group:{_id:"", sum:{$sum: "$count"}}}
to the existing aggregation pipeline query
Modified query
VisitorCompany.aggregate(
[
{
$match: {
$and:[
{ entry_date: { $gt: start, $lt: end } }
]
}
},
{
$group:
{
_id:
{
day: { $dayOfMonth: "$entry_date" },
month: { $month: "$entry_date" },
year: { $year: "$entry_date" }
},
count: { $sum:1 },
entry_date: { $first: "$entry_date" }
}
},
{
$project:
{
entry_date:
{
$dateToString: { format: "%Y-%m-%d", date: "$entry_date" }
},
count: 1,
_id: 0
}
},
{ $sort : { entry_date : -1 } },
{$group:{_id:"", sum:{$sum: "$count"}}}
])
The result
{ "_id" : "", "sum" : 3 }