How to group by two fields mongoDB aggregation - mongodb

I have the following documents in mongoDB:
{
_id: "YYYY-MM-DD",
workedTimes: [
{..., driver: {username: string} }
]
}
every workedTime has a driver with a userName prop, and i want to group them by date and driver.username with a aggregation but i can't get it
I've tried something like this
$group: {
"_id": "$workedTimes.driver.username",
"date": {
$push: "$_id"
},
"clocks": {
$push: {
"date": "$_id",
"workedTimes": "$workedTimes"
}
}
}
but i cant get the output i want
I want a output something like this
{
date: 2022-08-24
username: driver1
workedTimes: []
},
{
date: 2022-08-24
username: driver2
workedTimes: []
},
{
date: 2022-08-25
username: driver1
workedTimes: []
}

Maybe this is what you are looking for:
db.collection.aggregate([
{ // Your other stages here },
{
"$unwind": "$workedTimes" // your $unwind stage
},
{
"$group": {
"_id": {
_idField: "$_id",
_driver: "$workedTimes.driver.username"
},
"_workedTimes": {
"$push": "$workedTimes"
}
}
},
{
"$project": {
date: "_id.$_idField",
driver: "$_id._driver",
workedTimes: "$_workedTimes",
_id: 0
}
}
])
Maybe the fields syntaxis is a little weird, but I think this works.

Related

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 use $match (multiple conditions) and $group in Mongodb

have list of records with the following fields - postBalance, agentId, createdAt, type. I want to filter by “type” and date. After this is done I want to get the $last postBalance for each agent based on the filter and sum up the postBalance. I have been struggling with this using this query
db.transaction.aggregate(
[{ $match: {
$and: [ {
createdAt: { $gte: ISODate('2022-09-15'), $lt:
('2022-09-16') } },
{ type: "CASH_OUT"}]}},
{
$group:
{
_id: {createdAt: {$last: "$createdAt"}},
totalAmount: { $sum: "$postBalance" },
}
}
]
)
An empty array is returned with this query and there are data in the collection.
Below are samples of the documents
{
"_id": {
"$oid": "6334cefd0048787d5535ff16"
},
"type": "CASH_OUT",
"postBalance": {
"$numberDecimal": "23287.625"
},
"createdAt": {
"$date": {
"$numberLong": "1664405245000"
}
},
}
{
"_id": {
"$oid": "6334d438c1ab8a577677cbf3"
},
"userID": {
"$oid": "62f27bc29f51747015fdb941"
},
"aggregatorID": "0000116",
"transactionFee": {
"$numberDecimal": "0.0"
},
"type": "AIRTIME_VTU",
"postBalance": {
"$numberDecimal": "2114.675"
},
"walletHistoryID": 613266,
"walletID": 1720,
"walletActionAt": {
"$date": {
"$numberLong": "1664406584000"
}
},
{
"type": "FUNDS_TRANSFER",
"postBalance": {
"$numberDecimal": "36566.39"
},
"createdAt": {
"$date": {
"$numberLong": "1664407090000"
}
}
}
This is the output I am expecting
{
"date" : 2022-10-09,
"CASHOUT ": 897663,088,
"FUNDS_TRANSFER": 8900877,
"AIRTIME_VTU": 8890000
}
How can my query be aggregated to get this? Thanks
It look like you want something like:
db.collection.aggregate([
{$match: {
createdAt: {
$gte: ISODate("2022-09-15T00:00:00.000Z"),
$lt: ISODate("2022-09-30T00:00:00.000Z")
}
}
},
{$group: {
_id: "$type",
createdAt: {$first: "$createdAt"},
totalAmount: {$sum: "$postBalance"}
}
},
{$group: {
_id: 0,
createdAt: {$first: "$createdAt"},
data: {$push: {k: "$_id", v: "$totalAmount"}}
}
},
{$project: {
data: {$arrayToObject: "$data"},
createdAt: 1,
_id: 0
}
},
{$set: {"data.date": "$createdAt"}},
{$replaceRoot: {newRoot: "$data"}}
])
See how it works on the playground example

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 Combine Unwinded Documents

I am creating a mongo aggregate pipeline where I unwind a document by a field (doors) that is a list. Then, I filter by a condition on a property in the individual door.
How would I combine the filtered results back together such that the result is in its original form?
Here is an example of a document in my collection:
{ "uuid": "00000000-0000-0000-0000-000000000000",
"name": "Building1",
"doors": [
{
"doorUuid": "11111111-1111-1111-1111-111111111111",
"creationTime": null
},
{
"doorUuid": "22222222-2222-2222-2222-222222222222",
"creationTime": 1560194908942
},
{
"doorUuid": "33333333-3333-3333-3333-333333333333",
"creationTime": 1560195008942
}
]
}
For example, if I wanted to filter out all doors with null creationTime's, the output I want would have the same structure above but with only two doors.
$group with $push:
MongoPlayground
db.collection.aggregate([
{
$unwind: "$doors"
},
{
$match: {
"doors.creationTime": {
$ne: null
}
}
},
{
$group: {
_id: "$_id",
name: {
$last: "$name"
},
uuid: {
$last: "$uuid"
},
doors: {
$push: "$doors"
}
}
}
])

grouping data in mongo using json data stored

This is the data I have in my mongo db:
{
"_id": ObjectId("556d1c7716efd4a035d8e473"),
"products": [
{
"gtin": 77770000222313,
"gpc": 10000068
},
{
"gtin": 77770000222312,
"gpc": 10000068
}
]
}
How do I aggregate this so that I get gpc value and then an array under that of the gtins? Something like:
{
"gpc":10000068,
"gtin":[77770000222312,77770000222313]
}
Use aggregation framework
db.collection.aggregate(
[
{ $unwind: "$products" },
{ $group: { _id: "$products.gpc", gtin: { $push: "$products.gtin" }}},
{ $project: { gpc: "$_id", gtin: 1, _id: 0 }}
]
)