Nicolas Albarracin
Nicolas Albarracin

Reputation: 217

Mongoose not bringing in any results

I'm trying to build a kind of complex query in mongoose, my problem is all the parameters this query can receive are non mandatory and that is bringing me problems. Right now I did this:

let query = {
            publicationType: req.body.searchParams.publicationType
        };
        if (req.body.searchParams.address) {
            query.address = {};
            if (req.body.searchParams.address.city) {
                query.address.city = req.body.searchParams.address.city;
            }
        }
        try {
            const dwellings = await model.Dwelling.find({
                $and: [{$or: [{publicationType: req.body.searchParams.publicationType}]},
                    {
                        $or: [{
                            address: [query.address]
                        }]
                    }]
            }).lean().exec();
            console.log(dwellings);
            res.send({dwellings});
        } catch (err) {
            next(err);
        }
    });

This was to try out if the city parameter is working, if I search only by publication type I get the desired results, if I add city I get 0 results even when I'm supposed to get more, I debugged mongoose to see how the query was being built and it's like this:

Mongoose: dwelling.find({ '$and': [ { '$or': [ { publicationType: 'Venta' } ] }, { '$or': [ { address: { '$in': [ { city: 'La Plata' } ] } } ] } ] }, { fields: {} })
[]

Upvotes: 1

Views: 50

Answers (2)

Nicolas Albarracin
Nicolas Albarracin

Reputation: 217

so with the guidness of drew Maclnnis i figured out how to make it work at least

const query = {};
        if (req.body.searchParams.publicationType !== '') {
            query['publicationType'] = req.body.searchParams.publicationType;
        }
        if (req.body.searchParams.address) {
            if (req.body.searchParams.address.streetNumber !== undefined) {
                query['address.streetNumber'] = req.body.searchParams.address.streetNumber;
            }
            if (req.body.searchParams.address.streetName !== undefined) {
                query['address.streetName'] = req.body.searchParams.address.streetName;
            }
            if (req.body.searchParams.address.city !== undefined) {
                query['address.city'] = req.body.searchParams.address.city;
            }
            if (req.body.searchParams.address.state !== undefined) {
                query['address.state'] = req.body.searchParams.address.state;
            }
            if (req.body.searchParams.address.country !== undefined) {
                query['address.country'] = req.body.searchParams.address.country;
            }
            if (req.body.searchParams.address.zip !== undefined) {
                query['address.zip'] = req.body.searchParams.address.zip;
            }
        }
        if (req.body.searchParams.price) {
            if (req.body.searchParams.price.min !== undefined) {
                query['price'] = {$gt: req.body.searchParams.price.min};
            }
            if (req.body.searchParams.price.max !== undefined) {
                query['price'] = {$lt: req.body.searchParams.price.max};
            }
        }
        try {
            const dwellings = await model.Dwelling.find({
                '$and': [
                    query
                ]
            }).lean().exec();
            console.log(dwellings);
            res.send({dwellings});
        } catch (err) {
            next(err);
        }

can this be optimized?

Upvotes: 0

Drew MacInnis
Drew MacInnis

Reputation: 8567

In your code you are building an $and expression of two $or expressions but each $or expression has only one argument each, so you are effectively building this $and find expression (note, I'm using the mongo shell syntax below):

db.dwellings.find({ 
   '$and': [ 
       { publicationType: 'Venta' }, 
       { address: { '$in': [ { city: 'La Plata' } ] } } 
   ]
});

... in words: "find the dwellings with publicationType Venta and address.city La Plata.

if I add city I get 0 results even when I'm supposed to get more

Since you mention you expect to get more results when you add in address.city I suspect you really want the top-level expression to be $or not $and, like this:

db.dwellings.find({ 
   '$or': [ 
       { publicationType: 'Venta' }, 
       { address: { '$in': [ { city: 'La Plata' } ] } } 
   ]
});

You may want to experiment more with your query in mongo shell before expressing it as code. If you happen to have Docker available on your workstation, I find running mongo in a container a useful way to prototype things while developing, for example:

docker run --name mongo -d mongo:3.7
# after mongo is up and running...
docker exec -it mongo mongo

In the interactive mongo shell you can insert documents for testing and experiment with find expressions, example:

use stackoverflow;
dwell1 = { publicationType: 'Venta', address: { city: 'Somewhere' } };
dwell2 = { publicationType: 'Something', address: { city: 'La Plata' } };
db.dwellings.insert(dwell1);
db.dwellings.insert(dwell2);

# Try results of $and
db.dwellings.find({ '$and': [ 
   { publicationType: 'Venta' }, 
   { address: { '$in': [ { city: 'La Plata' } ] } } 
]  });

# ... compare to results of $or
db.dwellings.find({ '$or': [ 
   { publicationType: 'Venta' }, 
   { address: { '$in': [ { city: 'La Plata' } ] } } 
]  });

... once you have inserted some documents for testing, confirm whether you want an $and or $or expression in your find.

Upvotes: 1

Related Questions