mongodb 多 or and 邏輯查詢 python實現
阿新 • • 發佈:2018-12-24
思路:
1:利用棧結構,將 形如 ( A or B ) and C 轉為字尾表示式(逆波蘭式),也就是 A B or C and。
2:其實就可以把or 看成 加減號, and 看成乘除號,就類似於計算器的功能實現。
3:有了字尾表示式,依次處理,遇到or,and 依次處理前兩個數值,就很方便了。
注:mongodb的表示式根據自己需要替換即可, 不過目前還沒有解決not的情況,有待更新。
#encoding: UTF8 def mySplit(s,sep): s1 = s.replace(sep,sep+sep) lis = s1.split(sep) while '' in lis: lis[lis.index('')] = sep return lis def MidfixToPostfix(_midfixStr): pOut = { '#':0, '(':7, ')':1, 'and':4, 'or':2 } pIn = { '#':0, '(':1, ')':7, 'and':5, 'or':3 } string = _midfixStr inputList = string.split(' ') inputLen = len(inputList) tempList = list() #stack tempList.append('#') resultList = list() x=0 while x < inputLen: if inputList[x] not in ['or','and',')','(']: resultList.append(inputList[x]) elif inputList[x] == ')': while tempList[-1]!='(': resultList.append(tempList.pop()) tempList.pop() #去除( else: if pOut[inputList[x]] > pIn[tempList[-1]] : tempList.append(inputList[x]) else: while pOut[inputList[x]] <= pIn[tempList[-1]]: resultList.append(tempList.pop()) tempList.append(inputList[x]) #將操作符入棧 x+=1 while tempList[-1] !='#': resultList.append(tempList.pop()) return resultList def PostfixToMongo(_postfixList): postfixList = _postfixList postfixListLen = len(postfixList) resultList = list() x=0 while x < postfixListLen: key = None op = None value = None if postfixList[x] not in ['or','and']: sep = None for i in postfixList[x]: if i in ['>','<']: sep = i opList = mySplit(postfixList[x],sep) key = opList[0] op = opList[1] value = opList[2] if op == '>': result = "{'temp."+ key +"':{'$gt':"+ value +'}}' #集合的鍵名temp elif op == '<': result = "{'temp."+ key +"':{'$lt':"+ value +'}}' else: print 'something wrong! this is not a operator!' resultList.append(result) elif postfixList[x] == 'or': result = "{'$or':[" + resultList.pop(-1) + ',' + resultList.pop(-1) + ']}' resultList.append(result) elif postfixList[x] == 'and': result = "{'$and':[" + resultList.pop(-1) + ',' + resultList.pop(-1) + ']}' resultList.append(result) else: print 'something wrong! this is not a valid parameter!' x+=1 return resultList.pop(-1) if __name__ == '__main__': string = '( shcnt>10 and fcnt<10 ) and ( vcnt<200 and vcnt>50 )' postfixList = MidfixToPostfix(string) print postfixList resultSql = PostfixToMongo(postfixList) print resultSql