Python dictionary to equivalent pymongo statement
parsing, pymongo, python
Solution
Your example code does not run, but given that a dict
{'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': 'M'}, {'column': 'YYY', 'operator': '=', 'value': 'N'}]}, {'column': 'YYY', 'operator': '>=', 'value': '3.0'}]}
should be convertet to
{'$or': [{'$and': [{'XXX': 'M'}, {'YYY': 'N'}]}, {'YYY': {'$gte': 3.0}}]}
use something like this:
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)
I don't know if it's important to convert `'3.0'` to `3.0`. The line
value = float(dic['value']) if dic['operator'] == "!=" else dic['value']
is quite hackish, you want replace it with some appropriate logic to handle those cases.
Problem
I have a python dictionary like this ``` {'OR': [{'AND': [{'column': 'XXX', 'operator': '=', 'value': u'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]}, {'column': 'YYY', 'operator': '>=', 'value': '3.0'}]} ``` Now, i want to convert it to something like ``` {'$or': [{'$and': [{'XXX': 'M'}, {'YYY': 'N'}]}, {'YYY': {u'$gte': 3.0}}]} ``` Which is clearly the equivalent pymongo statement I believe. the code I have written so far is like this : ``` 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 ``` The output it generates is : ``` {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}}]} ``` Which is near to the solution but not the exact one. It works fine for dictionaries like ``` {'AND': [{'column': 'XXX', 'operator': '=', 'value': 'M'}, {'column': 'XXX', 'operator': '=', 'value': 'N'}]} OR {'column': 'YYY', 'operator': '>', 'value': '1000'} ``` can you point to me a direction? (the idea is to create a generic one. so, i would like to generate equivalent to any valid python dictionary into pymongo statement. the minimum is the last one)