'Manipulate how you load this document\'s fields. Used by `.only()`
and `.exclude()` to manipulate which fields to retrieve. If called
directly, use a set of kwargs similar to the MongoDB projection
document. For example:
Include only a subset of fields:
posts = BlogPost.objects(...).fields(author=1, title=1)
Exclude a specific field:
posts = BlogPost.objects(...).fields(comments=0)
To retrieve a subrange of array elements:
posts = BlogPost.objects(...).fields(slice__comments=5)
:param kwargs: A set of keyword arguments identifying what to
include, exclude, or slice.
.. versionadded:: 0.5'

def fields(self, _only_called=False, **kwargs):

    operators = ['slice']
    cleaned_fields = []
    for (key, value) in kwargs.items():
        parts = key.split('__')
        if (parts[0] in operators):
            op = parts.pop(0)
            value = {('$' + op): value}
        key = '.'.join(parts)
        cleaned_fields.append((key, value))
    def _sort_key(field_tuple):
        (key, value) = field_tuple
        if isinstance(value, int):
            return value
        else:
            return 2
    fields = sorted(cleaned_fields, key=_sort_key)
    queryset = self.clone()
    for (value, group) in itertools.groupby(fields, (lambda x: x[1])):
        fields = [field for (field, value) in group]
        fields = queryset._fields_to_dbfields(fields)
        queryset._loaded_fields += QueryFieldList(fields, value=value, _only_called=_only_called)
    return queryset
