1

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?

1 Answer 1

2

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; }

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.