I’m a little lost on how to use aggregate to obtain very specific type of results.
My db documents have the following format
{
_id: 122434
houseDetails: {
hasBedroom: {
flag: true,
},
hasKitchen: {
flag: false
},
hasBalcony: {
flag: false
},
hasFoyer: {
flag: true
},
}
}
(This is a basic example of the structure of the document, the details are different)
I’m trying to query all the documents where the nested houseDetails properties are true.
So in the end I’d like the result to look like
{
_id: 122434,
houseDetails: [hasBedroom, hasFoyer]
}
I can use $match to find all the documents where at least one of the properties is true but I seem to be lost as to how to project only the names with the value true into an array.
>Solution :
One option is:
- Use
$objectToArrayto create an array from the keys and values $filterit to keep onlytruevalues- Use
$mapto format the items
db.collection.aggregate([
{$project: {houseDetails: {$objectToArray: "$houseDetails"}}},
{$project: {
houseDetails: {
$filter: {
input: "$houseDetails",
cond: {$eq: ["$$this.v.flag", true]}
}
}
}
},
{$project: {
houseDetails: {
$map: {
input: "$houseDetails",
in: "$$this.k"
}
}
}
}
])
See how it works on the playground example
You can also use $reduce to do it in two steps only:
db.collection.aggregate([
{$project: {houseDetails: {$objectToArray: "$houseDetails"}}},
{$project: {
houseDetails: {
$reduce: {
input: "$houseDetails",
initialValue: [],
in: {
$setUnion: [
"$$value",
{$cond: [{$eq: ["$$this.v.flag", true]}, ["$$this.k"], []]}
]
}
}
}
}
}
See how it works on the playground example – reduce