1. 程式人生 > >mongodb 多 or and 邏輯查詢 python實現

mongodb 多 or and 邏輯查詢 python實現

思路:

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