def aggregate(self): errors = [] params = request.params # get and check parameters dataset = self._dataset(params, errors) drilldowns = self._drilldowns(params, errors) cuts = self._cuts(params, errors) order = self._order(params, errors) page = self._to_int('page', params.get('page', 1), errors) pagesize = self._to_int('pagesize', params.get('pagesize', 10000), errors) if errors: return {'errors': errors} # find a suiteable cube dimensions = set([cut[0] for cut in cuts] + drilldowns) # we can e.g. cut on cofog1.name, but the dimension is cofog1 dimensions = [d.split('.')[0] for d in dimensions] cube = find_cube(dataset, dimensions) if cube is None: return {'errors': ['We cannot aggregate with this combination ' 'of drilldowns and cuts']} try: result = cube.query(drilldowns, cuts, page=page, pagesize=pagesize, order=order) except ValueError: # fixme: add task to compute the cube return {'errors': ['We cannot aggregate at the moment. ' 'Please come back later.']} return result
def totals(self): if self._totals is None: self._totals = {} cube = find_cube(self.view.dataset, self.view.base_dimensions) if cube is None: log.warn("Run-time has view without cube: %s", self.view.base_dimensions) return self._totals results = cube.query(['year'], self.cuts) for entry in results.get('drilldown'): self._totals[str(entry.get('year'))] = entry.get('amount') return self._totals
def aggregate(self): dataset_name = request.params.get('dataset', request.params.get('slice')) dataset_name = dataset_aliases.get(dataset_name, dataset_name) dataset = model.dataset.find_one_by('name', dataset_name) if dataset is None: abort(400, "Dataset %s not found" % dataset_name) drilldowns, cuts, statistics = [], [], [] for key, value in sorted(request.params.items()): if not '-' in key: continue op, key = key.split('-', 1) if 'include' == op: cuts.append((key, value)) elif 'per' == op: if 'time' == key: abort(400, "Time series are no longer supported") statistics.append((key, value)) elif 'breakdown' == op: drilldowns.append(key) dimensions = set(drilldowns + [k for k, v in cuts] + \ ['year'] + [v for k, v in statistics]) cube = find_cube(dataset, dimensions) if cube is None: abort(400, "No matching data cube available with dimensions: %r" % dimensions) result = cube.query(drilldowns + ['year'], cuts) #TODO: handle statistics as key-values ??? what's the point? for k, v in statistics: result = statistic_normalize(dataset, result, v, k) # translate to old format: group by drilldown, then by date. translated_result = defaultdict(dict) for cell in result['drilldown']: key = tuple([cellget(cell, d) for d in drilldowns]) translated_result[key][cell['year']] = cell['amount'] dates = sorted(set([d['year'] for d in result['drilldown']])) # give a value (or 0) for each present date in sorted order translated_result = [(k, [v.get(d, 0.0) for d in dates]) \ for k, v in translated_result.items()] return {'results': translated_result, 'metadata': { 'dataset': dataset['name'], 'include': cuts, 'dates': map(unicode, dates), 'axes': drilldowns, 'per': statistics, 'per_time': [] } }
def view(self, dataset, dimension, format='html'): c.dataset = model.dataset.find_one_by('name', dataset) if not c.dataset: abort(404, _('Sorry, there is no dataset named %s') % dataset) if dimension in ENTRY_FIELDS or "." in dimension: abort(400, _('This is not a dimension')) c.meta = model.dimension.find_one({"dataset": c.dataset['name'], "key": dimension}) if c.meta is None: c.meta = {} # TODO: pagination! try: page = int(request.params.get('page')) except: page = 1 cube = find_cube(c.dataset, [dimension]) # ok if cube is not None: try: result = cube.query([dimension], page=page, pagesize=PAGE_SIZE, order=[('amount', True)]) except Exception as e: error = str(e) if "too much data for sort" in error: error = """Database tuning required: the dataset specified is so large that it cannot be searched quickly enough to fulfil your request in reasonable time. Please request that an administrator add an index to speed up this query.""" abort(403, error) items = result.get('drilldown', []) c.values = [(d.get(dimension), d.get('amount')) for d in items] else: abort(403, "none") items = distinct(dimension, dataset_name=c.dataset['name']) c.values = [(i, 0.0) for i in items] if format == 'json': return to_jsonp({ "values": c.values, "meta": c.meta}) c.page = Page(c.values, page=page, items_per_page=PAGE_SIZE) return render('dimension/view.html')
def aggregates(self): if self._aggregates is None: if self.view.drilldown is None: return [] res = defaultdict(dict) drilldowns = [] cube = find_cube(self.view.dataset, self.view.full_dimensions) if cube is None: log.warn("Run-time has view without cube: %s", self.view.full_dimensions) return [] results = cube.query(['year', self.view.drilldown], self.cuts) for entry in results.get('drilldown'): d = entry.get(self.view.drilldown) if not d in drilldowns: drilldowns.append(d) res[drilldowns.index(d)][str(entry.get('year'))] = \ entry.get('amount') self._aggregates = [(drilldowns[k], v) for k, v in res.items()] # sort aggregations by time if self.time is not None: self._aggregates = sorted(self._aggregates, reverse=True, key=lambda (k, v): v.get(self.time, 0)) return self._aggregates
def compute(self): # TODO: decide if this is a good idea if not find_cube(self.dataset, self.full_dimensions): Cube.define_cube(self.dataset, self.signature, self.full_dimensions)