student student - 3 months ago 18
Javascript Question

What is wrong with this command line argument using $or operator in node.js application?



var MongoClient = require('mongodb').MongoClient,
assert = require('assert');

var allOptions = [{
overview: "wiki",
}, {
milestones: "CMO"
}];

var numQueriesFinished = 0;
var companiesSeen = {};

for (var i = 0; i < allOptions.length; i++) {
var query = queryDocument(allOptions[i]);
queryMongoDB(query, i);
}



function queryMongoDB(query, queryNum) {

MongoClient.connect('mongodb://localhost:27017/crunchbase', function(err, db) {

assert.equal(err, null);
console.log("Successfully connected to MongoDB for query: " + queryNum);

var cursor = db.collection('companies').find(query);

var numMatches = 0;

cursor.forEach(
function(doc) {
numMatches = numMatches + 1;
if (doc.permalink in companiesSeen) return;
companiesSeen[doc.permalink] = doc;
},
function(err) {
assert.equal(err, null);
console.log("Query " + queryNum + " was:" + JSON.stringify(query));
console.log("Matching documents: " + numMatches);
numQueriesFinished = numQueriesFinished + 1;
if (numQueriesFinished == allOptions.length) {
report();
}
return db.close();
}
);

});

}


function queryDocument(options) {

var query = {};

if ("overview" in options) {

query.overview = {
$or: [overview: {
"$regex": options.overview,
"$options": "i"
},
tag_list: {
"$regex": options.overview,
"$options": "i"
}
]
};
}

if ("milestones" in options) {
query["milestones.source_description"] = {
"$regex": options.milestones,
"$options": "i"
};
}

return query;

}


function report(options) {
var totalEmployees = 0;
for (key in companiesSeen) {
totalEmployees = totalEmployees + companiesSeen[key].number_of_employees;
}

var companiesList = Object.keys(companiesSeen).sort();
console.log("Companies found: " + companiesList);
console.log("Total employees in companies identified: " + totalEmployees);
console.log("Total unique companies: " + companiesList.length);
console.log("Average number of employees per company: " + Math.floor(totalEmployees / companiesList.length));
}





In the above code, I need to write an assignment statement to ensure that if "overview" appears in the
options
object, we will match documents that have the value of
options.overview
in either the "overview" field or "tag_list" field of companies documents.

I tried the
$or
:

query.overview = {$or: [overview : {"$regex": options.overview, "$options": "i"}, tag_list : {"$regex": options.overview, "$options": "i"}]};


I'm getting the below error:

enter image description here

And when I try @MykolaBorysyuk's answer:
query.overview = {$or: [{overview : {"$regex": options.overview, "$options":"i"}}, {tag_list : {"$regex": options.overview, "$options": "i"}} ]};


I get

enter image description here

What is wrong with this command line argument using $or operator in node.js application?

Answer

From docs https://docs.mongodb.com/manual/reference/operator/query/or/

$or operator in array should contain objects. So query should look like this.

query.overview = {$or: [{overview : {"$regex": options.overview, "$options":"i"}}, {tag_list : {"$regex": options.overview, "$options": "i"}} ]};

Edit.

Here is your problem. When you using $or operator you must pass it first always. So query can look like this {$or: [...]} but cant look like this {somefield: {$or:[]}} <- that will cause your error. https://gyazo.com/cb993ecdcbc8f37052878a34d9a27549

To fix your code do this

var cursor = db.collection('companies').find(query.overview);

To fix your query builder:

function queryDocument(options) {
  var query = {};
  var arrayOfParams = [];

 if ("overview" in options) {
    arrayOfParams.push({overview: {
      "$regex": options.overview,
      "$options": "i"
    }});

    arrayOfParams.push({tag_list: {
      "$regex": options.overview,
      "$options": "i"
    }});  
 }

 if ("milestones" in options) {
    arrayOfParams.push({milestones: {
      "$regex": options.milestones,
      "$options": "i"
    }});
 }
  query.overview = {$or: arrayOfParams};
  return query;
}

Hope this helps.