def sortResults(self, rs, sort_index, reverse=False, limit=None, merge=True, actual_result_count=None, b_start=0, b_size=None): # Sort a result set using one or more sort indexes. Both sort_index # and reverse can be lists of indexes and reverse specifications. # Return a lazy result set in sorted order if merge is true otherwise # returns a list of (sortkey, uid, getter_function) tuples, where # sortkey can be a tuple on its own. second_indexes = None second_indexes_key_map = None sort_index_length = 1 if isinstance(sort_index, list): sort_index_length = len(sort_index) if sort_index_length > 1: second_indexes = sort_index[1:] second_indexes_key_map = [] for si in second_indexes: second_indexes_key_map.append(si.documentToKeyMap()) sort_index = sort_index[0] result = [] if hasattr(rs, 'keys'): rs = rs.keys() if actual_result_count is None: rlen = len(rs) actual_result_count = rlen else: rlen = actual_result_count # don't limit to more than what we have if limit is not None and limit >= rlen: limit = rlen # if we want a batch from the end of the result set, reverse sorting # order and limit it, then reverse the result set again switched_reverse = False if b_size and b_start and b_start > rlen / 2: if isinstance(reverse, list): reverse = [not r for r in reverse] else: reverse = not reverse switched_reverse = True b_end = b_start + b_size if b_end >= rlen: overrun = rlen - b_end if b_start >= rlen: # bail out, we are outside the possible range return LazyCat([], 0, actual_result_count) else: b_size += overrun b_start = 0 else: b_start = rlen - b_end limit = b_start + b_size # determine sort_spec if isinstance(reverse, list): sort_spec = [r and -1 or 1 for r in reverse] # limit to current maximum of sort indexes sort_spec = sort_spec[:sort_index_length] # use first sort order for choosing the algorithm first_reverse = reverse[0] else: sort_spec = [] for i in xrange(sort_index_length): sort_spec.append(reverse and -1 or 1) first_reverse = reverse # Special first condition, as it changes post-processing. iterate_sort_index = (merge and limit is None and (rlen > (len(sort_index) * (rlen / 100 + 1)))) # Choose one of the sort algorithms. if iterate_sort_index: sort_func = self._sort_iterate_index elif limit is None or (limit * 4 > rlen): sort_func = self._sort_iterate_resultset elif first_reverse: sort_func = self._sort_nbest else: sort_func = self._sort_nbest_reverse actual_result_count, length, result = sort_func( actual_result_count, result, rs, limit, merge, reverse, sort_index, sort_index_length, sort_spec, second_indexes_key_map) sequence, slen = self._limit_sequence(result, length, b_start, b_size, switched_reverse) if iterate_sort_index: result = LazyCat(LazyValues(sequence), slen, actual_result_count) else: if not merge: return sequence result = LazyValues(sequence) result.actual_result_count = actual_result_count return LazyMap(self.__getitem__, result, len(result), actual_result_count=actual_result_count)
def _createLValues(self, seq): from ZTUtils.Lazy import LazyValues return LazyValues(seq)