Constructing an sql query with the rules you show would be very easy. Not the same case with constructing a mongo query.
I made a similar engine where i stored the rule as sql rule, then wrote a module to construct mongo query from the sql query (a simple one).
In order to match the mongo rule against a javascript object, i used the sift library (does not have same regex support as mongo query engine) - https://github.com/crcn/sift.js
So, if possible i would suggest you store the data in an sql database, then apply the sql rule you construct after you have done proper escaping (to avoid sql injection)
This is the function i used at the frontend to construct sql-type rule -
(rule
here is an array of expressions mapped to each row in the UI)
function getRuleString(rule) {
var andOrStack = [];
var lastExpressionDepth = 0;
var tempRuleString = '';
var countOpenBrackets = 0;
if(!rule || !rule.expressionRows) {
return '';
}
rule.expressionRows.forEach(function(expressionRow, index) {
expressionRow.depth = parseInt(expressionRow.depth, 10);
if(lastExpressionDepth !== expressionRow.depth) {
// if this is an outer expression than the previous
if((lastExpressionDepth - expressionRow.depth) > 0) {
for(var i=0; i<(lastExpressionDepth - expressionRow.depth); i++) {
tempRuleString += ' ) ';
}
tempRuleString += ' ' + andOrStack.pop() + ' ';
} else {
tempRuleString += ' ' + andOrStack.pop() + ' ( ';
}
lastExpressionDepth = expressionRow.depth;
} else {
if(index > 0) {
tempRuleString += ' ' + andOrStack.pop() + ' ';
}
}
tempRuleString += expressionRow.firstColumn + ' ' + expressionRow.operator + ' "' + expressionRow.expression + '"';
andOrStack.push(expressionRow.andOr);
});
tempRuleString += Array.apply(null, Array(tempRuleString.split('(').length-tempRuleString.split(')').length)) // jshint ignore: line
.map(String.prototype.valueOf, ' ) ').join('');
return tempRuleString;
}