使用 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"
}
]
}
我有一个 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"
}
]
}