Reputation: 1058
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
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
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