Пример #1
0
    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
Пример #2
0
 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
Пример #3
0
    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': []
                    }
                }
Пример #4
0
    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')
Пример #5
0
 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
Пример #6
0
 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)