I have this structure of a document:
{
"1": {
"type1": 1,
"type2": 2
},
"2": {
"type1": 11,
"type2": 12
}
}
// There can by multiple values at all levels, not just 2
Now I want to to query for all type2
with a filter, conceptually:
"*.type2" > 10
And I want to return only one field as well, so that the result would look like that:
{
"10": {
"type2": 20
},
"20": {
"type2": 25
}
}
Is it possible to achieve in MongoDB with a single query?
CodePudding user response:
One option is to iterate over the keys and keep only the type2
with value greater than 10.
In order to iterate over the keys we are using $objectToArray
. In order to keep only the type2
, we use $reduce
to iterate (which allow to format the item), instead of a simple $filter
that will just return the un-formatted matching items. The last step is just to format back the array to a dictionary.
db.collection.aggregate([
{$project: {
_id: 0,
data: {$reduce: {
input: {$objectToArray: "$$ROOT"},
initialValue: [],
in: {$concatArrays: [
"$$value",
{$cond: [
{$gt: ["$$this.v.type2", 10]},
[{k: "$$this.k", v: {type2: "$$this.v.type2"}}],
[]
]}
]}
}}
}},
{$replaceRoot: {newRoot: {$arrayToObject: "$data"}}}
])
See how it works on the playground example