I would like to be able to dynamically build a Mongo query using Node with multiple OR's. The point of this query is to do an AND search in the database with multiple search terms.
For example, suppose someone wanted to search for records containing the words "dog" and "cereal." The query would only return records that have "dog" and "cereal" somewhere in the record (i.e. the search terms can appear in different columns).
I know that the query should end up looking like this:
query = {
$and: [
{$or: [
{col1: {$regex: "first", $options: "i"}},
{col2: {$regex: "first", $options: "i"}}
]},
{$or: [
{col1: {$regex: "second", $options: "i"}},
{col2: {$regex: "second", $options: "i"}}
]}
]
}
My node code, however, does not produce this. This is the closest I have gotten to figuring this out:
var regexQueryWrapper = {};
regexQueryWrapper["$and"] = [];
var wrapper = {};
wrapper["$or"] = [];
var query = {};
searchTerms.forEach(function(term) {
searchFields.forEach(function(field) {
query[field] = {$regex: term, $options: 'i'};
wrapper["$or"].push(query);
});
regexQueryWrapper["$and"].push(wrapper);
});
What is the best way to do this? Is there a different approach that I am missing?
You're close. You seem to be reusing objects. Here's some adjusted code that builds the query you're looking for, with the temporary objects reinitialized on each forEach iteration:
var regexQueryWrapper = {};
regexQueryWrapper["$and"] = [];
searchTerms.forEach(function(term) {
var wrapper = {"$or": []};
searchFields.forEach(function(field) {
var query = {};
query[field] = {$regex: term, $options: 'i'};
wrapper["$or"].push(query);
});
regexQueryWrapper["$and"].push(wrapper);
});
And an alternative implementation using map
:
var query = {"$and": searchTerms.map(function(term) {
return {"$or": searchFields.map(function(field) {
var o = {};
o[field] = {"$regex": term, "$options": "i"};
return o;
})};
})};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With