Reputation: 2368
I am trying to create a complex query for mongoDB
's aggregate
framework. It requires a component that programmatically adds an $and
and $or
.
This is the current structure of my object:
const inputObject = {
"details.blackBottom": { "in": ["A","B","C","D"] },
"details.blackTop": { "in": ["L","M"] },
"details.redBottom": { "in": ["A","B","C","D"] },
"details.redTop": { "in": ["L","M"] },
"details.greenBottom": { "in": ["A","B","C","D"] },
"details.greenTop": { "in": ["L","M"] }
}
However, for the object to be useful, I need to reformulate it so that it uses both $or
and $and
. The final output should look like this:
const outputObject = {
"$and": [
{
"$or" : [
{"details.blackBottom": { "in": ["A","B","C","D"] }},
{"details.redBottom": { "in": ["A","B","C","D"] }},
{"details.greenBottom": { "in": ["A","B","C","D"] }}
]
},
{
"$or" : [
{"details.blackTop": { "in": ["L","M"] } },
{"details.redTop": { "in": ["L","M"] } },
{"details.greenTop": { "in": ["L","M"] } }
]
}
]
}
Notice that the $or
components are grouped by the Bottom
and Top
.
How can I turn the inputObject
into the desired outputObject
?
Upvotes: 1
Views: 51
Reputation: 350212
You could do that with a combination of filter
and map
methods:
const inputObject = {
"details.blackBottom": { "in": ["A","B","C","D"] },
"details.blackTop": { "in": ["L","M"] },
"details.redBottom": { "in": ["A","B","C","D"] },
"details.redTop": { "in": ["L","M"] },
"details.greenBottom": { "in": ["A","B","C","D"] },
"details.greenTop": { "in": ["L","M"] }
}
const outputObject = {
$and: ["Bottom", "Top"].map( side => ({
$or: Object.keys(inputObject)
.filter( key => key.endsWith(side) )
.map( key => ({ [key]: inputObject[key] }) )
}) )
};
console.log(outputObject);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2