Why can't I aggregate with MongoDB with a $match? - mongodb

My code is:
db.essays.aggregate({
$match: {
essayId: 3
},
$group: {
_id: {
year: {
$year: '$essayTime'
},
month: {
$month: '$essayTime'
},
day: {
$dayOfMonth: '$essayTime'
}
},
count: {
$sum: 1
}
}
});
It returns an error: "exception: A pipeline stage specification object must contain exactly one field."
However, if I do it without the $match, then it returns as expected. What am I doing wrong?

Put each pipeline stage into its own object within an array:
db.essays.aggregate([
{ $match: {
essayId: 3
}},
{ $group: {
_id: {
year: {
$year: '$essayTime'
},
month: {
$month: '$essayTime'
},
day: {
$dayOfMonth: '$essayTime'
}
},
count: {
$sum: 1
}
}}
]);

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 group ISODate but maintain date format

I know I can group data inside a collection by
{
$group: {
_id: {
day: {
$dayOfMonth: '$timeplay'
},
month: {
$month: '$timeplay'
},
year: {
$year: '$timeplay'
}
},
listeners: {
$sum: '$count'
}
}
However, it does not show the date in ISOdate format anymore which is what I need it to still do.
Is there a way to create ISOdate based on this information? As the output currently looks like the following
You can use $dateFromParts operator to convert to date from parts,
{
$group: {
_id: {
$dateFromParts: {
day: { $dayOfMonth: "$timeplay" },
month: { $month: "$timeplay" },
year: { $year: "$timeplay" }
}
},
listeners: { $sum: '$count' }
}
}
Playground
Use this
db.collection.aggregate([
{
$group: {
_id: { $dateTrunc: { date: "$timeplay", unit: "day" } },
listeners: { $sum: '$count' }
}
}
])

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 }

Query for nested groups and push in 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" }]
}
}
}
}])