mongodb 多 or and 逻辑查询 python实现

来源:互联网 发布:恺英网络待遇 编辑:程序博客网 时间:2024/06/07 18:28

思路:

1:利用栈结构,将 形如 ( A or B ) and C 转为后缀表达式(逆波兰式),也就是 A B or C and。

2:其实就可以把or 看成 加减号, and 看成乘除号,就类似于计算器的功能实现。

3:有了后缀表达式,依次处理,遇到or,and 依次处理前两个数值,就很方便了。


注:mongodb的表达式根据自己需要替换即可, 不过目前还没有解决not的情况,有待更新。


#encoding: UTF8def mySplit(s,sep):s1 = s.replace(sep,sep+sep)lis = s1.split(sep)while '' in lis:lis[lis.index('')] = sepreturn lisdef MidfixToPostfix(_midfixStr):pOut = {'#':0,'(':7,')':1,'and':4,'or':2}pIn = {'#':0,'(':1,')':7,'and':5,'or':3}string = _midfixStrinputList = string.split(' ')inputLen = len(inputList)tempList = list()   #stacktempList.append('#')resultList = list()x=0while 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+=1while tempList[-1] !='#':resultList.append(tempList.pop())return resultListdef PostfixToMongo(_postfixList):postfixList = _postfixListpostfixListLen = len(postfixList)resultList = list()x=0while x < postfixListLen:key = Noneop = Nonevalue = Noneif postfixList[x] not in ['or','and']:sep = Nonefor i in postfixList[x]:if i in ['>','<']:sep = iopList = mySplit(postfixList[x],sep)key = opList[0]op = opList[1]value = opList[2]if op == '>':result = "{'temp."+ key +"':{'$gt':"+ value +'}}'     #集合的键名tempelif 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+=1return resultList.pop(-1)if __name__ == '__main__':string = '( shcnt>10 and fcnt<10 ) and ( vcnt<200 and vcnt>50 )'postfixList = MidfixToPostfix(string)print postfixListresultSql = PostfixToMongo(postfixList)print resultSql


2 0