# File lib/dm-aggregates/functions.rb, line 153
      def aggregate(*args)
        query = args.last.kind_of?(Hash) ? args.pop : {}

        query[:fields] ||= []
        query[:fields]  |= args
        query[:fields].map! { |f| normalize_field(f) }

        raise ArgumentError, 'query[:fields] must not be empty' if query[:fields].empty?

        unless query.key?(:order)
          # the current collection/model is already sorted by attributes
          # and since we are projecting away some of the attributes,
          # and then performing aggregate functions on the remainder,
          # we need to honor the existing order, as if it were already
          # materialized, and we are looping over the rows in order.

          directions = direction_map

          query[:order] = []

          # use the current query order for each property if available
          query[:fields].each do |property|
            next unless property.kind_of?(Property)
            query[:order] << directions.fetch(property, property)
          end
        end

        query = scoped_query(query)

        if query.fields.any? { |p| p.kind_of?(Property) }
          query.repository.aggregate(query.update(:unique => true))
        else
          query.repository.aggregate(query).first  # only return one row
        end
      end