HarryH
HarryH

Reputation: 1058

Mongoose/Node dynamic where query

I am trying to use mongoose to filter some results using .where() by passing an array of tags. It works effectively for finding documents that match one of the array items, but I need something more precise.

var tags = ["cow","bus"];
var query = Contact.find({name: query.name}).where('tags').in(tags).exec(callback);

This returns contacts that has a cow or bus inside of its tag array.

What I am looking to do is narrow down and find a contact that has both "cow" and "bus" without matching exactly.

For example

Filter Tags: "cow","bus"
    contact1
        tags: ["cow","bus","chicken"]
    contact2
        tags: ["cow","bus","pokemon"]
    contact3:
        tags: ["bus"]
    contact4:
        tags: ["cow","plane","pie"]
    contact5:
        tags: ["cow","bus"]

I would want the query to return contact 1,2, and 5.

I have found that if I do,

 var query = Contact.find({name: query.name})
                  .where('tags').in(["cow"])
                  .where('tags').in(["bus"]);

it works, but it seems hacky/sloppy and it is hardcodded. I guess its a dynamic $and using a passed array.

Any pointers?

Upvotes: 0

Views: 935

Answers (2)

JohnnyHK
JohnnyHK

Reputation: 311835

You can use the $all query operator for this:

Contact.find({name: query.name, tags: {$all: tags}}).exec(callback);

That will only match docs where name matches query.name and tags contains both 'cow' and 'bus' elements.

Upvotes: 2

HarryH
HarryH

Reputation: 1058

So as I was filling this question out, I tried to do more digging for the sake of saving peoples time. I figured out a solution which seems to work.

I created an array of tag objects and pass it to the $and query param. I am using lodash, but I am sure you could do it without it.

var tags = ["cow","bird"];
var objectTags = [];            

_.each(tags, function(tag){ 
     objectTags.push({tags: tag});      
});

Contact.find({name: query.name, $and: objectTags}).exec(callback);

If anyone knows a more efficient way, feel free to let me know! I hope this helps someone in the future.

Upvotes: 0

Related Questions