我有一个像这样的python字典
{'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': u'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}, {'column': 'YYY', 'operator': '>=', 'value': '3.0'}]}
现在,我想将其转换为类似
的内容{'$or': [{'$and': [{'XXX': 'M'}, {'YYY': 'N'}]}, {'YYY': {u'$gte': 3.0}}]}
我相信这显然是相当于pymongo的声明。
到目前为止我写的代码是这样的:FILTMAP = {'>=': '$gte', '<=': '$lte', '>': '$gt', '<': '$lt', "!=":"$ne"}
CONJUNCTION_MAP = {"AND":"$and", "OR":"$or"}
def gen_mongo_filters_json(filter, supplied_key="")
first_key = filters.keys()[0]
if first_key == 'OR' or first_key == 'AND':
if supplied_key == "":
return_dict[CONJUNCTION_MAP[first_key]] = []
else:
temp_dict[CONJUNCTION_MAP[first_key]] = []
#return_dict[supplied_key] = temp_dict
for i in range (len(filters[first_key])):
if supplied_key == "":
return_dict[CONJUNCTION_MAP[first_key]].append(gen_mongo_filters_json(filters[first_key][i], first_key))
else:
temp_dict[CONJUNCTION_MAP[first_key]].append(gen_mongo_filters_json(filters[first_key][i], first_key))
return_dict[CONJUNCTION_MAP[supplied_key]].append(temp_dict)
else:
operator = filters['operator']
if operator == "=":
ret_dict = {filters['column']:filters['value']
return ret_dict
else:
operator = FILTMAP[operator]
ret_dict = {filters['column']:{operator:filters['value']}}
return ret_dict
return return_dict
它生成的输出是:
{u'$or': [{u'$and': [{u'Engine': u'MSN'}, {u'Engine': u'Google'}]}, {u'$and': [{u'Engine': u'MSN'}, {u'Engine': u'Google'}]}, {...}, {u'Imps': {u'$gte': 3.0}}]}
哪个接近解决方案但不是确切的解决方案。它适用于像
这样的词典{'AND': [{'column': 'XXX', 'operator': '=', 'value': 'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}
OR
{'column': 'YYY', 'operator': '>', 'value': '1000'}
你能指点我一个方向吗?
(想法是创建一个通用的。所以,我想生成相当于任何有效的python字典到pymongo语句。最小的是最后一个)
答案 0 :(得分:3)
你的示例代码没有运行,但是给出了一个dict
{'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': 'M'}, {'column': 'YYY', 'operator': '=', 'value': 'N'}]}, {'column': 'YYY', 'operator': '>=', 'value': '3.0'}]}
应转换为
{'$or': [{'$and': [{'XXX': 'M'}, {'YYY': 'N'}]}, {'YYY': {'$gte': 3.0}}]}
使用类似的东西:
FILTMAP = {'>=': '$gte', '<=': '$lte', '>': '$gt', '<': '$lt', "!=":"$ne"}
CONJUNCTION_MAP = {"AND":"$and", "OR":"$or"}
def convert_column(dic):
if not dic['operator'] in FILTMAP:
return {dic['column']: dic['value']}
else:
value = float(dic['value']) if dic['operator'] == "!=" else dic['value']
return {dic['column']: {FILTMAP[dic['operator']]: value}}
def convert(dic):
for k,v in dic.items():
if isinstance(v, list):
if k in CONJUNCTION_MAP:
k = CONJUNCTION_MAP[k]
return {k: [convert(i) for i in v]}
else:
return convert_column(dic)
我不知道将'3.0'
转换为3.0
是否很重要。这条线
value = float(dic['value']) if dic['operator'] == "!=" else dic['value']
是非常hackish,你想用一些适当的逻辑替换它来处理这些情况。
答案 1 :(得分:0)
感谢您的回答。我也想出了一些东西。这是完整的代码
FILTMAP = {'>=': '$gte', '<=': '$lte', '>': '$gt', '<': '$lt', "!=":"$ne"}
CONJUNCTION_MAP = {"AND":"$and", "OR":"$or"}
def gen_mongo_filters_json(filters, supplied_key=""):
return_dict = {}
temp_dict = {}
first_key = filters.keys()[0]
if first_key == 'OR' or first_key == 'AND':
if supplied_key == "":
return_dict[CONJUNCTION_MAP[first_key]] = []
else:
temp_dict[CONJUNCTION_MAP[first_key]] = []
#return_dict[supplied_key] = temp_dict"""
for i in range (len(filters[first_key])):
if supplied_key == "":
return_dict[CONJUNCTION_MAP[first_key]].append(gen_mongo_filters_json(filters[first_key][i], first_key))
else:
for i in range (len(filters[first_key])):
temp_dict[CONJUNCTION_MAP[first_key]].append(gen_mongo_filters_json(filters[first_key][i], first_key))
return temp_dict
else:
operator = filters['operator']
if operator == "=":
ret_dict = {filters['column']:filters['value']}
return ret_dict
else:
operator = FILTMAP[operator]
ret_dict = {filters['column']:{operator:filters['value']}}
return ret_dict
return return_dict
if __name__ == "__main__":
print gen_mongo_filters_json({'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': 'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}, {'AND': [{'column': 'PPP', 'operator': '=', 'value': 'R'}, {'column': 'DDD', 'operator': '=', 'value': 'T'}]}]})
enter code here
请告诉我您的评论
我试过
{'column': 'YYY', 'operator': '>', 'value': '1000'}
{'AND': [{'column': 'XXX', 'operator': '=', 'value': 'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}
{'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': u'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}, {'column': 'YYY', 'operator': '>=', 'value': '3.0'}]}
{'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': u'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}, {'AND': [{'column': 'PPP', 'operator': '=', 'value': u'R'}, {'column': 'DDD', 'operator': '=', 'value': 'T'}]}]}
这是输出
{u'YYY': {u'$gt': u'1000'}}
{u'$and': [{u'XXX': u'M'}, {u'XXX': u'N'}]}
{u'$or': [{u'$and': [{u'XXX': u'M'}, {u'XXX': u'N'}]}, {u'YYY': {u'$gte': u'3.0'}}]}
{u'$or': [{u'$and': [{u'XXX': u'M'}, {u'XXX': u'N'}]}, {u'$and': [{u'PPP': u'R'}, {u'DDD': u'T'}]}]}
感谢您的回答。它也很好。我现在就试试。
还有一件事,我实际上在示例代码中省略了“值”的考虑。我很感谢你指出这一点。我已经有办法实现这一目标。不管怎样,谢谢。