Home > database >  How can I apply conditional filtering to MongoDB documents?
How can I apply conditional filtering to MongoDB documents?

Time:10-13

I am having a really hard time figuring out how to apply multiple levels of filtering to my mongoDB documents (not sure if this phrasing is correct). I am trying to create an app that will allow users to perform a search and retrieve only those documents that match the filters they have chosen to apply. A user might chose to apply only one filter or combine multiple filters.

For example, the user might be looking for a house. The available filters could be location, size and type. If the user applies the location filter with a value of ‘London’, they should get only those houses available in London. If they choose to combine the above location with the type filter with a value of ‘2-bedroom-apartment’, they should get all 2-bedroom apartments available in London.

How can I make sure that the results are conditionally filtered, depending on the filters that the user has applied? I think I am supposed to use $match, but I don’t understand if I can use multiple queries with it.

What I have come up with so far is the following:

const getFilteredData = async(req, res) => {
    try {
        const { filter1, filter2, filter3 } = req.query;
        const filteredData = await dataModel.aggregate([
            {$match:{
                $and:[{filter1:filter1},{filter2: filter2}, {filter3:filter3}]    //1st option: all of the filters are applied by the user
            }}
        ])
        res.status(201).json({data: filteredData});
    }
    catch(err) {
        res.status(404).json({message: err.message});
    }
}

With the above code, the results are filtered only when all 3 filters are being applied. How can I cater to different combinations of filters being applied by the user (only one filter, filter1 & filter3 combined etc)?

Any help will be massively appreciated.

CodePudding user response:

Assuming req.query can be {name: "Coat", city: "Athens"} You can do something like:

const getFilteredData = async(req, res) => {
    try {
        const filtersArr = [];
        for (const filterKey of ['name', 'city', 'category']) {
            if (req.query[filterKey]) {
                const thisFilter = {};
                thisFilter[filterKey] = req.query[filterKey];
                filtersArr.push(thisFilter);
            }
        }
        console.log(filtersArr)
        const filteredData = await filteredDataModel.aggregate([
            {$match:{
                $and: filtersArr    //1st option: all of the filters are applied by the user
            }}
        ])
        res.status(201).json({data: filteredData});
    }
    catch(err) {
        res.status(404).json({message: err.message});
    }
}

You can also use the original req.query like this:

const filteredData = await filteredDataModel.find(req.query)

But iterating using the code allows you to validate the keys that you want...

  • Related