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)

Original source