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.
CodePudding user response:
One option is:
- Use
$objectToArray
to create an array from the keys and values $filter
it to keep onlytrue
values- Use
$map
to 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