def search(self, Queue=None, order=None, raw_query=None, Format='l', **kwargs):
        """ Search arbitrary needles in given fields and queue.

        Example::

            >>> tracker = Rt('http://tracker.example.com/REST/1.0/', 'rt-username', 'top-secret')
            >>> tracker.login()
            >>> tickets = tracker.search(CF_Domain='example.com', Subject__like='warning')
            >>> tickets = tracker.search(Queue='General', order='Status', raw_query="id='1'+OR+id='2'+OR+id='3'")

        :keyword Queue:      Queue where to search. If you wish to search across
                             all of your queues, pass the ALL_QUEUES object as the
                             argument.
        :keyword order:      Name of field sorting result list, for descending
                             order put - before the field name. E.g. -Created
                             will put the newest tickets at the beginning
        :keyword raw_query:  A raw query to provide to RT if you know what
                             you are doing. You may still pass Queue and order
                             kwargs, so use these instead of including them in
                             the raw query. You can refer to the RT query builder.
                             If passing raw_query, all other **kwargs will be ignored.
        :keyword Format:     Format of the query:
                               - i: only `id' fields are populated
                               - s: only `id' and `subject' fields are populated
                               - l: multi-line format, all fields are populated
        :keyword kwargs:     Other arguments possible to set if not passing raw_query:

                             Requestors, Subject, Cc, AdminCc, Owner, Status,
                             Priority, InitialPriority, FinalPriority,
                             TimeEstimated, Starts, Due, Text,... (according to RT
                             fields)

                             Custom fields CF.{<CustomFieldName>} could be set
                             with keywords CF_CustomFieldName.

                             To alter lookup operators you can append one of the
                             following endings to each keyword:

                             __exact    for operator = (default)
                             __notexact for operator !=
                             __gt       for operator >
                             __lt       for operator <
                             __like     for operator LIKE
                             __notlike  for operator NOT LIKE

                             Setting values to keywords constrain search
                             result to the tickets satisfying all of them.

        :returns: List of matching tickets. Each ticket is the same dictionary
                  as in :py:meth:`~Rt.get_ticket`.
        :raises:  UnexpectedMessageFormat: Unexpected format of returned message.
                  InvalidQueryError: If raw query is malformed
        """
        get_params = {}
        query = []
        url = 'search/ticket'
        if Queue is not ALL_QUEUES:
            query.append("Queue=\'{}\'".format(Queue or self.default_queue))
        if not raw_query:
            operators_map = {
                'gt': '>',
                'lt': '<',
                'exact': '=',
                'notexact': '!=',
                'like': ' LIKE ',
                'notlike': ' NOT LIKE '
            }

            for key, value in iteritems(kwargs):
                op = '='
                key_parts = key.split('__')
                if len(key_parts) > 1:
                    key = '__'.join(key_parts[:-1])
                    op = operators_map.get(key_parts[-1], '=')
                if key[:3] != 'CF_':
                    query.append("{}{}\'{}\'".format(key, op, value))
                else:
                    query.append("'CF.{{{}}}'{}\'{}\'".format(key[3:], op, value))
        else:
            query.append(raw_query)
        get_params['query'] = ' AND '.join('(' + part + ')' for part in query)
        if order:
            get_params['orderby'] = order
        get_params['format'] = Format

        msg = self.__request(url, get_params=get_params)
        lines = msg.split('\n')
        if len(lines) > 2:
            if self.__get_status_code(lines[0]) != 200 and lines[2].startswith('Invalid query: '):
                raise InvalidQueryError(lines[2])
            if lines[2].startswith('No matching results.'):
                return []

        if Format == 'l':
            msgs = map(lambda x: x.split('\n'), msg.split('\n--\n'))
            items = []
            for msg in msgs:
                pairs = {}
                req_matching = [i for i, m in enumerate(msg) if self.RE_PATTERNS['requestors_pattern'].match(m)]
                req_id = req_matching[0] if req_matching else None
                if not req_id:
                    raise UnexpectedMessageFormat('Missing line starting with `Requestors:`.')
                for i in range(req_id):
                    if ': ' in msg[i]:
                        header, content = self.split_header(msg[i])
                        pairs[header.strip()] = content.strip()
                requestors = [msg[req_id][12:]]
                req_id += 1
                while (req_id < len(msg)) and (msg[req_id][:12] == ' ' * 12):
                    requestors.append(msg[req_id][12:])
                    req_id += 1
                pairs['Requestors'] = self.__normalize_list(requestors)
                for i in range(req_id, len(msg)):
                    if ': ' in msg[i]:
                        header, content = self.split_header(msg[i])
                        pairs[header.strip()] = content.strip()
                if pairs:
                    items.append(pairs)

                if 'Cc' in pairs:
                    pairs['Cc'] = self.__normalize_list(pairs['Cc'])
                if 'AdminCc' in pairs:
                    pairs['AdminCc'] = self.__normalize_list(pairs['AdminCc'])

                if 'id' not in pairs and not pairs['id'].startswitch('ticket/'):
                    raise UnexpectedMessageFormat('Response from RT didn\'t contain a valid ticket_id')
                else:
                    pairs['numerical_id'] = pairs['id'].split('ticket/')[1]

            return items
        elif Format == 's':
            items = []
            msgs = lines[2:]
            for msg in msgs:
                if "" == msg:  # Ignore blank line at the end
                    continue
                ticket_id, subject = self.split_header(msg)
                items.append({'id': 'ticket/' + ticket_id, 'numerical_id': ticket_id, 'Subject': subject})
            return items
        elif Format == 'i':
            items = []
            msgs = lines[2:]
            for msg in msgs:
                if "" == msg:  # Ignore blank line at the end
                    continue
                _, ticket_id = msg.split('/', 1)
                items.append({'id': 'ticket/' + ticket_id, 'numerical_id': ticket_id})
            return items
Search arbitrary needles in given fields and queue.

        Example::

            >>> tracker = Rt('http://tracker.example.com/REST/1.0/', 'rt-username', 'top-secret')
            >>> tracker.login()
            >>> tickets = tracker.search(CF_Domain='example.com', Subject__like='warning')
            >>> tickets = tracker.search(Queue='General', order='Status', raw_query="id='1'+OR+id='2'+OR+id='3'")

        :keyword Queue:      Queue where to search. If you wish to search across
                             all of your queues, pass the ALL_QUEUES object as the
                             argument.
        :keyword order:      Name of field sorting result list, for descending
                             order put - before the field name. E.g. -Created
                             will put the newest tickets at the beginning
        :keyword raw_query:  A raw query to provide to RT if you know what
                             you are doing. You may still pass Queue and order
                             kwargs, so use these instead of including them in
                             the raw query. You can refer to the RT query builder.
                             If passing raw_query, all other **kwargs will be ignored.
        :keyword Format:     Format of the query:
                               - i: only `id' fields are populated
                               - s: only `id' and `subject' fields are populated
                               - l: multi-line format, all fields are populated
        :keyword kwargs:     Other arguments possible to set if not passing raw_query:

                             Requestors, Subject, Cc, AdminCc, Owner, Status,
                             Priority, InitialPriority, FinalPriority,
                             TimeEstimated, Starts, Due, Text,... (according to RT
                             fields)

                             Custom fields CF.{<CustomFieldName>} could be set
                             with keywords CF_CustomFieldName.

                             To alter lookup operators you can append one of the
                             following endings to each keyword:

                             __exact    for operator = (default)
                             __notexact for operator !=
                             __gt       for operator >
                             __lt       for operator <
                             __like     for operator LIKE
                             __notlike  for operator NOT LIKE

                             Setting values to keywords constrain search
                             result to the tickets satisfying all of them.

        :returns: List of matching tickets. Each ticket is the same dictionary
                  as in :py:meth:`~Rt.get_ticket`.
        :raises:  UnexpectedMessageFormat: Unexpected format of returned message.
                  InvalidQueryError: If raw query is malformed