black_sheep07
black_sheep07

Reputation: 2368

Modify Javascript object by reference

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

Answers (1)

trincot
trincot

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

Related Questions