getFiltersFromArgs - Returns a dictionary of each filter type, and the corrosponding field/value

        @param kwargs <dict> - Dictionary of filter arguments


        @return - Dictionary of each filter type (minus the ones that are optimized into others), each containing a list of tuples, (fieldName, matchingValue)

def getFiltersFromArgs(kwargs):
    '''
        getFiltersFromArgs - Returns a dictionary of each filter type, and the corrosponding field/value

        @param kwargs <dict> - Dictionary of filter arguments


        @return - Dictionary of each filter type (minus the ones that are optimized into others), each containing a list of tuples, (fieldName, matchingValue)
    '''

    # Create a copy of each possible filter in FILTER_TYPES and link to empty list.
    #  This object will be filled with all of the filters requested
    ret = { filterType : list() for filterType in FILTER_TYPES }

    for key, value in kwargs.items():
        matchObj = FILTER_PARAM_RE.match(key)
        if not matchObj:

            # Default ( no __$oper) is eq
            filterType = 'eq'
            field = key

        else:

            # We have an operation defined, extract it, and optimize if possible
            #  (like if op is a case-insensitive, lowercase the value here)
            groupDict = matchObj.groupdict()

            filterType = groupDict['filterType']
            field = groupDict['field']


            if filterType not in FILTER_TYPES:
                raise ValueError('Unknown filter type: %s. Choices are: (%s)' %(filterType, ', '.join(FILTER_TYPES)))


            if filterType == 'isnull':
                # Convert "isnull" to one of the "is" or "isnot" filters against None
                if type(value) is not bool:
                    raise ValueError('Filter type "isnull" requires True/False.')

                if value is True:
                    filterType = "is"
                else:
                    filterType = "isnot"

                value = None
            elif filterType in ('in', 'notin'):
                # Try to make more efficient by making a set. Fallback to just using what they provide, could be an object implementing "in"
                try:
                    value = set(value)
                except:
                    pass
            # Optimization - if case-insensitive, lowercase the comparison value here
            elif filterType in ('ieq', 'ine', 'icontains', 'noticontains'):
                value = value.lower()
            elif filterType.startswith('split'):
                if (not issubclass(type(value), tuple) and not issubclass(type(value), list)) or len(value) != 2:
                    raise ValueError('Filter type %s expects a tuple of two params. (splitBy, matchPortion)' %(filterType,))



        ret[filterType].append( (field, value) )

    return ret