def aggregate(self, request):
     """
     Aggregate field values based on start/end time.
     Returns the unique values shared across all FITS files for site, telescope, instrument, filter, proposal, and obstype.
     """
     # TODO: This should be removed after a while, it is just here for temporary API compatibility
     FIELD_MAPPING = {
         'SITEID': 'site_id',
         'TELID': 'telescope_id',
         'FILTER': 'primary_optical_element',
         'INSTRUME': 'instrument_id',
         'OBSTYPE': 'configuration_type',
         'PROPID': 'proposal_id'
     }
     fields = ('site_id', 'telescope_id', 'primary_optical_element',
               'instrument_id', 'configuration_type', 'proposal_id')
     aggregate_field = request.GET.get('aggregate_field', 'ALL')
     if aggregate_field in FIELD_MAPPING:
         aggregate_field = FIELD_MAPPING[aggregate_field]
     if aggregate_field != 'ALL' and aggregate_field not in fields:
         return Response(
             'Invalid aggregate_field. Valid fields are {}'.format(
                 ', '.join(fields)),
             status=status.HTTP_400_BAD_REQUEST)
     query_filters = {}
     for k in FIELD_MAPPING.keys():
         if k in request.GET:
             query_filters[FIELD_MAPPING[k]] = request.GET[k]
     for k in fields:
         if k in request.GET:
             query_filters[k] = request.GET[k]
     if 'start' in request.GET:
         query_filters['start'] = parse(request.GET['start']).replace(
             tzinfo=UTC, second=0, microsecond=0)
     if 'end' in request.GET:
         query_filters['end'] = parse(request.GET['end']).replace(
             tzinfo=UTC, second=0, microsecond=0)
     cache_hash = blake2s(
         repr(frozenset(list(query_filters.items()) +
                        [aggregate_field])).encode()).hexdigest()
     response_dict = cache.get(cache_hash)
     if not response_dict:
         qs = Frame.objects.all()
         qs = DjangoFilterBackend().filter_queryset(request, qs, view=self)
         sites = self._get_aggregate_values(qs, query_filters, 'site_id',
                                            aggregate_field)
         telescopes = self._get_aggregate_values(qs, query_filters,
                                                 'telescope_id',
                                                 aggregate_field)
         filters = self._get_aggregate_values(qs, query_filters,
                                              'primary_optical_element',
                                              aggregate_field)
         instruments = self._get_aggregate_values(qs, query_filters,
                                                  'instrument_id',
                                                  aggregate_field)
         obstypes = self._get_aggregate_values(qs, query_filters,
                                               'configuration_type',
                                               aggregate_field)
         proposals = self._get_aggregate_values(
             qs.filter(public_date__lte=timezone.now()), query_filters,
             'proposal_id', aggregate_field)
         response_dict = {
             'sites': sites,
             'telescopes': telescopes,
             'filters': filters,
             'instruments': instruments,
             'obstypes': obstypes,
             'proposals': proposals
         }
         cache.set(cache_hash, response_dict, 60 * 60)
     response_serializer = self.get_response_serializer(response_dict)
     return Response(response_serializer.data)