使用 mongoose 查询语法将有序方程转换为预序方程

convert inorder equation to preorder equation with mongoose query syntax

我有一个 javascript 对象如下。请注意字符串中的空格。

find = { search: "name:someName and ( place:someplace or place:someotherplace )" }

我想将字符串转换成下面的形式

query={ 
        $and: [  
                {name:'someName'} , 
                {$or: [
                       {place:'someplace'}, 
                       {place:'someotherplace'} 
                      ]
                }
              ]
      }

我想要适用于任何此类 AND、OR 方程并将它们转换为相应的 mongoose 查询的通用代码。那就是我想将中序方程转换为先序方程然后修改以获得猫鼬查询。

 function formQuery(searchString) {
    let infixArray = convertStringtoInfix(searchString);
    if (bracketChecker(infixArray)) {
        let postFixArray = convertInfixToPostfix(infixArray);
        let finalQuery = convertPostfixToQuery(postFixArray);
        return finalQuery;
    } else {
        return 'bracket mismatch';
    }
};

function bracketChecker(searchArray) {
    let flag = true;
    let stack = [];
    searchArray.forEach((element) => {
        if (element == '(') {
            stack.push(element);
        }
        if (element == ')') {
            if (stack.length > 0) {
                stack.pop();
            } else {
                flag = false;
            }
        }
    });
    if (stack.length > 0) {
        flag = false;
    }
    return flag;
}

function convertPostfixToQuery(postFixArray) {
    let stack = [];
    postFixArray.forEach((element) => {
        if (typeof element == 'object') {
            //makes it regex ==========================================
            // Object.keys(element).forEach(function(key) {
            //  if (element[key] == 'true') {
            //      element[key] = true;
            //  } else if (element[key] == 'false') {
            //      element[key] = false;
            //  } else {
            //      element[key] = new RegExp(element[key], 'i');
            //  }
            // });
            //=========================================================
            stack.push(element);
        } else {
            let obj = {};
            let lastelement = stack.pop();
            let secondLastElement = stack.pop();
            obj[element] = [ lastelement, secondLastElement ];
            stack.push(obj);
        }
    });
    return stack[0];
    // return { and: /a/i };
}

function convertInfixToPostfix(infixArray) {
    let outputQueue = [];
    let operatorStack = [];
    infixArray.forEach((element) => {
        if (typeof element == 'object') {
            outputQueue.push(element);
        } else if (element == '(') {
            operatorStack.push(element);
        } else if (element == ')') {
            let paranMismatch = false;
            while (operatorStack.length > 0 && operatorStack[operatorStack.length - 1] != '(') {
                outputQueue.push(operatorStack.pop());
                if (operatorStack.length == 0) {
                    paranMismatch = true;
                    break;
                }
            }
            if (paranMismatch) {
                return 'mismatch';
            }
            if (operatorStack[operatorStack.length - 1] == '(') {
                operatorStack.pop();
            }
        } else if (element == 'and' || element == 'or') {
            while (
                operatorStack.length > 0 &&
                operatorStack[operatorStack.length - 1] != '(' &&
                operatorStack[operatorStack.length - 1].length >= element.length
            ) {
                outputQueue.push(operatorStack.pop());
            }
            operatorStack.push(element);
        } else {
            return 'mismatch';
        }
    });
    operatorStack.reverse();
    operatorStack.forEach((element) => {
        if (element == '(') {
            return 'mismatch';
        } else {
            outputQueue.push(element);
        }
    });
    outputQueue = outputQueue.map((element) => {
        if (element == 'and' || element == 'or') return '$' + element;
        else return element;
    });
    return outputQueue;
}

function convertStringtoInfix(str) {
    let output = '';
    [ ...str ].forEach((c) => {
        if (c == '(' || c == ')') {
            output += ' ' + c + ' ';
        } else {
            output += c;
        }
    });
    output = output.split(' ');
    output = output.filter((ele) => ele != '');
    output = output.map((ele) => {
        if (ele.toLowerCase() == 'and' || ele.toLowerCase() == 'or') {
            return ele.toLowerCase();
        } else if (ele == '(' || ele == ')') {
            return ele;
        } else {
            let key = ele.split(':')[0];
            let value = ele.split(':')[1];

            let obj = {};
            obj[key] = value;

            return obj;
        }
    });
    return output;
}
let search = 'name:someName and ( place:someplace or place:someotherplace )'
console.log(formQuery(search))

输出为:-

{
        "$and": [
            {
                "$or": [
                    {
                        "place": "someotherplace"
                    },
                    {
                        "place": "someplace"
                    }
                ]
            },
            {
                "name": "someName"
            }
        ]
    }