docs: def _series(self, name, interval, config, buckets, **kws):
      '''
      Fetch a series of buckets.
      '''
      pipe = self._client.pipeline(transaction=False)
      step = config['step']
      resolution = config.get('resolution',step)
      fetch = kws.get('fetch') or self._type_get
      process_row = kws.get('process_row') or self._process_row
  
      rval = OrderedDict()
      for interval_bucket in buckets:
        i_key = '%s%s:%s:%s'%(self._prefix, name, interval, interval_bucket)
  
        if config['coarse']:
          fetch(pipe, i_key)
        else:
          pipe.smembers(i_key)
      res = pipe.execute()
  
      # TODO: a memory efficient way to use a single pipeline for this.
      for idx,data in enumerate(res):
        # TODO: use closures on the config for generating this interval key
        interval_bucket = buckets[idx] #start_bucket + idx
        interval_key = '%s%s:%s:%s'%(self._prefix, name, interval, interval_bucket)
  
        if config['coarse']:
          data = process_row( data )
          rval[ config['i_calc'].from_bucket(interval_bucket) ] = data
        else:
          rval[ config['i_calc'].from_bucket(interval_bucket) ] = OrderedDict()
          pipe = self._client.pipeline(transaction=False)
          resolution_buckets = sorted(map(int,data))
          for bucket in resolution_buckets:
            # TODO: use closures on the config for generating this resolution key
            resolution_key = '%s:%s'%(interval_key, bucket)
            fetch(pipe, resolution_key)
  
          resolution_res = pipe.execute()
          for x,data in enumerate(resolution_res):
            i_t = config['i_calc'].from_bucket(interval_bucket)
            r_t = config['r_calc'].from_bucket(resolution_buckets[x])
            rval[ i_t ][ r_t ] = process_row(data)
  
      return rval