My Data:
{"_id": "0x026EFF", "Stations": {"MP": false, "AS": true, "RW": true, "FT": true}},
{"_id": "0x026F00", "Stations": {"MP": null, "AS": true, "RW": true, "FT": false}},
{"_id": "0x026F01", "Stations": {"MP": null, "AS": true, "RW": false, "FT": null}},
{"_id": "0x026F02", "Stations": {"MP": null, "AS": null, "RW": true, "FT": false}},
{"_id": "0x026F03", "Stations": {"MP": null, "AS": true, "RW": null, "FT": false}}
Here is my query
Collection.aggregate([
{"$group": {'_id': None,
'MP': {'$sum': {'$cond': ["$Stations.MP", 1, 0]}},
'AS': {'$sum': {'$cond': ["$Stations.AS", 1, 0]}},
'RW': {'$sum': {'$cond': ["$Stations.RW", 1, 0]}},
'FT': {'$sum': {'$cond': ["$Stations.FT", 1, 0]}}
}
},
{'$project': {'_id': 0}}
])
I got
[{"AS":4,"FT":1,"MP":0,"RW":3}]
My question is Can I rewrite my query without "MP", "AS", "RW", "FT"?
CodePudding user response:
$set- Set theStationsfield with convertStationsfrom key-value pair to an array with the documents ofkandvfields.$unwind- DeconstructStationsarray to multiple documents.$group- Group byStations.kand perform sum by condition.$group- Group bynullto combine all documents into one and push the root document intodataarray.$replaceWith- Replace the input document with:5.1.
$arrayToObject- Convert the array from the result 5.1.1 to key-value pair.5.1.1.
$map- Iterate thedataarray and return a new array with the documents containingkandvfields.
db.collection.aggregate([
{
$set: {
Stations: {
$objectToArray: "$Stations"
}
}
},
{
$unwind: "$Stations"
},
{
$group: {
_id: "$Stations.k",
count: {
$sum: {
$cond: {
if: {
$eq: [
"$Stations.v",
true
]
},
then: 1,
else: 0
}
}
}
}
},
{
$group: {
_id: null,
data: {
$push: "$$ROOT"
}
}
},
{
$replaceWith: {
$arrayToObject: {
$map: {
input: "$data",
in: {
k: "$$this._id",
v: "$$this.count"
}
}
}
}
}
])
