예제 #1
0
    def _get_aggregated_query(self, start, limit):
        max_size = (start or 0) + (limit or 0)
        query = HQESQuery(self.table_name).size(0)
        for filter in self.filters:
            query = query.filter(filter)

        innermost_agg_col = self.aggregation_columns[-1]
        innermost_agg = TermsAggregation(innermost_agg_col, innermost_agg_col)

        aggregations = []
        for col in self.top_level_columns:
            for agg in col.aggregations(self.config, self.lang):
                innermost_agg.aggregation(agg)

        top_agg = innermost_agg
        # go through aggregations in reverse order so that they are nested properly
        # todo: Refactor NestedTermAggregationsHelper to support this use case
        for agg_column in self.aggregation_columns[:-1][::-1]:
            top_agg = TermsAggregation(agg_column,
                                       agg_column).aggregation(top_agg)

        top_agg.size(max_size)

        if self.order_by:
            # todo sort by more than one column
            # todo sort by by something other than the first aggregate column
            col, desc = self.order_by[0]
            if col == self.aggregation_columns[
                    0] or col == self.top_level_columns[0].field:
                top_agg = top_agg.order('_term', desc)

        query = query.aggregation(top_agg)

        return query.run()
예제 #2
0
def get_form_counts_by_user_xmlns(domain, startdate, enddate, user_ids=None,
                                  xmlnss=None, by_submission_time=True):

    missing_users = False

    date_filter_fn = submitted_filter if by_submission_time else completed_filter
    query = (
        FormES()
        .domain(domain)
        .filter(date_filter_fn(gte=startdate, lt=enddate))
        .aggregation(
            TermsAggregation('user_id', 'form.meta.userID').aggregation(
                TermsAggregation('app_id', 'app_id').aggregation(
                    TermsAggregation('xmlns', 'xmlns')
                )
            )
        )
        .size(0)
    )

    if user_ids:
        query = (query
            .user_ids_handle_unknown(user_ids)
            .remove_default_filter('has_user'))
        missing_users = None in user_ids
        if missing_users:
            query = query.aggregation(
                MissingAggregation('missing_user_id', 'form.meta.userID').aggregation(
                    TermsAggregation('app_id', 'app_id').aggregation(
                        TermsAggregation('xmlns', 'xmlns')
                    )
                )
            )

    if xmlnss:
        query = query.xmlns(xmlnss)

    counts = defaultdict(lambda: 0)
    aggregations = query.run().aggregations
    user_buckets = aggregations.user_id.buckets_list
    if missing_users:
        user_buckets.append(aggregations.missing_user_id.bucket)

    for user_bucket in user_buckets:
        app_buckets = user_bucket.app_id.buckets_list
        for app_bucket in app_buckets:
            xmlns_buckets = app_bucket.xmlns.buckets_list
            for xmlns_bucket in xmlns_buckets:
                key = (user_bucket.key, app_bucket.key, xmlns_bucket.key)
                counts[key] = xmlns_bucket.doc_count

    return counts
예제 #3
0
def get_form_count_breakdown_for_domain(domain):
    query = (FormES(for_export=True).domain(domain).aggregation(
        TermsAggregation("app_id", "app_id").aggregation(
            TermsAggregation("xmlns", "xmlns.exact"))).remove_default_filter(
                "has_xmlns").remove_default_filter("has_user").size(0))
    query_result = query.run()
    form_counts = {}
    for app_id, bucket in query_result.aggregations.app_id.buckets_dict.items(
    ):
        for sub_bucket in bucket.xmlns.buckets_list:
            xmlns = sub_bucket.key
            form_counts[(domain, app_id, xmlns)] = sub_bucket.doc_count
    return form_counts
예제 #4
0
def get_all_xmlns_app_id_pairs_submitted_to_in_domain(domain):
    query = (FormES().domain(domain).aggregation(
        TermsAggregation("app_id", "app_id").aggregation(
            TermsAggregation("xmlns", "xmlns.exact"))).remove_default_filter(
                "has_xmlns").remove_default_filter("has_user").size(0))
    query_result = query.run()
    form_counts = set()
    for app_id, bucket in query_result.aggregations.app_id.buckets_dict.iteritems(
    ):
        for sub_bucket in bucket.xmlns.buckets_list:
            xmlns = sub_bucket.key
            form_counts.add((xmlns, app_id))
    return form_counts
예제 #5
0
def get_form_count_breakdown_for_domain(domain):
    query = (FormES(
        es_instance_alias=ES_EXPORT_INSTANCE).domain(domain).aggregation(
            TermsAggregation("app_id", "app_id").aggregation(
                TermsAggregation(
                    "xmlns", "xmlns.exact"))).remove_default_filter(
                        "has_xmlns").remove_default_filter("has_user").size(0))
    query_result = query.run()
    form_counts = {}
    for app_id, bucket in six.iteritems(
            query_result.aggregations.app_id.buckets_dict):
        for sub_bucket in bucket.xmlns.buckets_list:
            xmlns = sub_bucket.key
            form_counts[(domain, app_id, xmlns)] = sub_bucket.doc_count
    return form_counts
예제 #6
0
def get_domain_device_breakdown_es(domain_name, monthspan):
    query = FormES(for_export=True).domain(domain_name).submitted(
        gte=monthspan.startdate,
        lt=monthspan.computed_enddate,
    ).aggregation(TermsAggregation('device_id', 'form.meta.deviceID')).size(0)

    return query.run().aggregations.device_id.counts_by_bucket()
예제 #7
0
def get_domain_device_breakdown_es(domain_name, monthspan):
    query = FormES(es_instance_alias=ES_EXPORT_INSTANCE).domain(domain_name).submitted(
        gte=monthspan.startdate,
        lt=monthspan.computed_enddate,
    ).aggregation(TermsAggregation('device_id', 'form.meta.deviceID')).size(0)

    return query.run().aggregations.device_id.counts_by_bucket()
예제 #8
0
def get_last_forms_by_app(user_id):
    """
    gets the last form submission for each app for a given user id
    :param user_id: id of a couch user
    :return: last form submission for every app that user has submitted
    """
    query = (
        FormES()
            .user_id(user_id)
            .aggregation(
            TermsAggregation('app_id', 'app_id').aggregation(
                TopHitsAggregation(
                    'top_hits_last_form_submissions',
                    'received_on',
                    is_ascending=False,
                )
            )
        )
        .size(0)
    )

    aggregations = query.run().aggregations

    buckets_dict = aggregations.app_id.buckets_dict
    result = []
    for app_id, bucket in buckets_dict.items():
        result.append(bucket.top_hits_last_form_submissions.hits[0])

    return result
예제 #9
0
    def _cases_created_per_user_per_month(self, case_type=None):
        query = (CaseES(es_instance_alias=ES_EXPORT_INSTANCE).domain(
            self.domain).opened_range(
                gte=self.date_start, lt=self.date_end).aggregation(
                    TermsAggregation('cases_per_user', 'owner_id',
                                     size=100).aggregation(
                                         DateHistogram('cases_by_date',
                                                       'opened_on',
                                                       interval='month'))))
        if case_type:
            query = query.case_type(case_type)

        results = query.size(0).run()

        stats = defaultdict(list)
        cases_per_user = results.aggregations.cases_per_user
        for bucket in cases_per_user.buckets_list:
            counts_by_date = {
                b['key_as_string']: b['doc_count']
                for b in bucket.cases_by_date.normalized_buckets
            }
            for key, count in counts_by_date.items():
                stats[key].append(count)

        final_stats = []
        for month, case_count_list in sorted(list(stats.items()),
                                             key=lambda r: r[0]):
            final_stats.append(
                (month, sum(case_count_list) // len(case_count_list)))

        suffix = ''
        if case_type:
            suffix = '(case type: %s)' % case_type
        self._print_table(
            ['Month', 'Cases created per user %s' % suffix], final_stats)
예제 #10
0
    def _cases_updated_per_user_per_month(self):
        results = (CaseES(es_instance_alias=ES_EXPORT_INSTANCE).domain(
            self.domain).active_in_range(
                gte=self.date_start, lt=self.date_end).aggregation(
                    TermsAggregation(
                        'cases_per_user', 'owner_id', size=100).aggregation(
                            NestedAggregation(
                                'actions', 'actions').aggregation(
                                    DateHistogram(
                                        'cases_by_date',
                                        'server_date',
                                        interval='month')))).size(0).run())

        stats = defaultdict(list)
        cases_per_user = results.aggregations.cases_per_user
        for bucket in cases_per_user.buckets_list:
            counts_by_date = {
                b['key_as_string']: b['doc_count']
                for b in bucket.actions.cases_by_date.normalized_buckets
            }
            for key, count in counts_by_date.items():
                stats[key].append(count)

        final_stats = []
        for month, case_count_list in sorted(list(stats.items()),
                                             key=lambda r: r[0]):
            final_stats.append(
                (month, sum(case_count_list) // len(case_count_list)))

        self._print_table(['Month', 'Cases updated per user'], final_stats)
예제 #11
0
def get_last_submission_time_for_users(domain,
                                       user_ids,
                                       datespan,
                                       for_export=False):
    def convert_to_date(date):
        return string_to_datetime(date).date() if date else None

    query = (FormES(
        for_export=for_export).domain(domain).user_id(user_ids).submitted(
            gte=datespan.startdate.date(),
            lte=datespan.enddate.date()).aggregation(
                TermsAggregation('user_id', 'form.meta.userID').aggregation(
                    TopHitsAggregation(
                        'top_hits_last_form_submissions',
                        'received_on',
                        is_ascending=False,
                        include='received_on',
                    ))).size(0))

    aggregations = query.run().aggregations
    buckets_dict = aggregations.user_id.buckets_dict
    result = {}
    for user_id, bucket in buckets_dict.items():
        result[user_id] = convert_to_date(
            bucket.top_hits_last_form_submissions.hits[0]['received_on'])
    return result
예제 #12
0
    def test_nesting_aggregations(self):
        json_output = {
            "query": {
                "filtered": {
                    "filter": {
                        "and": [{
                            "match_all": {}
                        }]
                    },
                    "query": {
                        "match_all": {}
                    }
                }
            },
            "aggs": {
                "users": {
                    "terms": {
                        "field": "user_id",
                        "size": SIZE_LIMIT
                    },
                    "aggs": {
                        "closed": {
                            "filter": {
                                "term": {
                                    "closed": True
                                }
                            }
                        }
                    }
                },
                "total_by_status": {
                    "filters": {
                        "filters": {
                            "closed": {
                                "term": {
                                    "closed": True
                                }
                            },
                            "open": {
                                "term": {
                                    "closed": False
                                }
                            }
                        }
                    }
                }
            },
            "size": SIZE_LIMIT
        }

        query = HQESQuery('cases').aggregations([
            TermsAggregation("users", 'user_id').aggregation(
                FilterAggregation('closed', filters.term('closed', True))),
            FiltersAggregation('total_by_status').add_filter(
                'closed',
                filters.term('closed',
                             True)).add_filter('open',
                                               filters.term('closed', False))
        ])
        self.checkQuery(query, json_output)
예제 #13
0
 def test_terms_aggregation_with_order(self):
     json_output = {
         "query": {
             "filtered": {
                 "filter": {
                     "and": [{
                         "match_all": {}
                     }]
                 },
                 "query": {
                     "match_all": {}
                 }
             }
         },
         "aggs": {
             "name": {
                 "terms": {
                     "field": "name",
                     "size": 1000000,
                     "order": [{
                         "sort_field": "asc"
                     }]
                 },
             },
         },
         "size": SIZE_LIMIT
     }
     query = HQESQuery('cases').aggregation(
         TermsAggregation('name', 'name').order('sort_field'))
     self.checkQuery(query, json_output)
예제 #14
0
def get_last_submission_time_for_users(domain,
                                       user_ids,
                                       datespan,
                                       es_instance_alias=ES_DEFAULT_INSTANCE):
    def convert_to_date(date):
        return string_to_datetime(date).date() if date else None

    query = (FormES(es_instance_alias=es_instance_alias).domain(
        domain).user_id(user_ids).completed(
            gte=datespan.startdate.date(),
            lte=datespan.enddate.date()).aggregation(
                TermsAggregation('user_id', 'form.meta.userID').aggregation(
                    TopHitsAggregation(
                        'top_hits_last_form_submissions',
                        'form.meta.timeEnd',
                        is_ascending=False,
                        include='form.meta.timeEnd',
                    ))).size(0))

    aggregations = query.run().aggregations
    buckets_dict = aggregations.user_id.buckets_dict
    result = {}
    for user_id, bucket in buckets_dict.items():
        result[user_id] = convert_to_date(
            bucket.top_hits_last_form_submissions.hits[0]['form']['meta']
            ['timeEnd'])
    return result
예제 #15
0
def get_all_user_ids_submitted(domain, app_ids=None):
    query = (FormES().domain(domain).aggregation(
        TermsAggregation('user_id', 'form.meta.userID')).size(0))

    if app_ids:
        query = query.app(app_ids)

    return list(query.run().aggregations.user_id.buckets_dict)
예제 #16
0
    def _get_aggregated_query(self, start, limit):
        max_size = (start or 0) + (limit or 0)
        query = HQESQuery(self.table_name).size(0)
        for filter in self.filters:
            query = query.filter(filter)

        innermost_agg_col = self.aggregation_columns[-1]
        innermost_agg = TermsAggregation(innermost_agg_col, innermost_agg_col, size=max_size)

        aggregations = []
        for col in self.top_level_columns:
            for agg in col.aggregations(self.config, self.lang):
                innermost_agg.aggregation(agg)

        top_agg = innermost_agg
        # go through aggregations in reverse order so that they are nested properly
        for agg_column in self.aggregation_columns[:-1][::-1]:
            top_agg = TermsAggregation(agg_column, agg_column, size=max_size).aggregation(top_agg)

        if self.order_by:
            col, desc = self.order_by[0]
            valid_columns = (
                self.aggregation_columns[0],
                self.top_level_columns[0].field,
                self.top_level_columns[0].column_id
            )
            if col in valid_columns:
                top_agg = top_agg.order('_term', desc)

        query = query.aggregation(top_agg)

        return query.run()
예제 #17
0
    def _get_aggregated_query(self, start, limit):
        max_size = (start or 0) + (limit or 0)
        query = HQESQuery(self.table_name).size(0)
        for filter in self.filters:
            query = query.filter(filter)

        innermost_agg_col = self.aggregation_columns[-1]
        innermost_agg = TermsAggregation(innermost_agg_col, innermost_agg_col)

        aggregations = []
        for col in self.top_level_columns:
            for agg in col.aggregations(self.config, self.lang):
                innermost_agg.aggregation(agg)

        top_agg = innermost_agg
        # go through aggregations in reverse order so that they are nested properly
        # todo: Refactor NestedTermAggregationsHelper to support this use case
        for agg_column in self.aggregation_columns[:-1][::-1]:
            top_agg = TermsAggregation(agg_column, agg_column).aggregation(top_agg)

        top_agg.size(max_size)

        if self.order_by:
            # todo sort by more than one column
            # todo sort by by something other than the first aggregate column
            col, desc = self.order_by[0]
            if col == self.aggregation_columns[0] or col == self.top_level_columns[0].field:
                top_agg = top_agg.order('_term', desc)

        query = query.aggregation(top_agg)

        return query.run()
예제 #18
0
def get_form_duration_stats_by_user(
        domain,
        app_id,
        xmlns,
        user_ids,
        startdate,
        enddate,
        by_submission_time=True):
    """Gets stats on the duration of a selected form grouped by users"""
    date_filter_fn = submitted_filter if by_submission_time else completed_filter

    missing_users = None in user_ids

    query = (
        FormES()
        .domain(domain)
        .user_ids_handle_unknown(user_ids)
        .remove_default_filter('has_user')
        .xmlns(xmlns)
        .filter(date_filter_fn(gte=startdate, lt=enddate))
        .aggregation(
            TermsAggregation('user_id', 'form.meta.userID').aggregation(
                ExtendedStatsAggregation(
                    'duration_stats',
                    'form.meta.timeStart',
                    script="doc['form.meta.timeEnd'].value - doc['form.meta.timeStart'].value",
                )
            )
        )
        .size(0)
    )

    if app_id:
        query = query.app(app_id)

    if missing_users:
        query = query.aggregation(
            MissingAggregation('missing_user_id', 'form.meta.userID').aggregation(
                ExtendedStatsAggregation(
                    'duration_stats',
                    'form.meta.timeStart',
                    script="doc['form.meta.timeEnd'].value - doc['form.meta.timeStart'].value",
                )
            )
        )

    result = {}
    aggregations = query.run().aggregations

    if missing_users:
        result[MISSING_KEY] = aggregations.missing_user_id.bucket.duration_stats.result

    buckets_dict = aggregations.user_id.buckets_dict
    for user_id, bucket in buckets_dict.iteritems():
        result[user_id] = bucket.duration_stats.result
    return result
예제 #19
0
def get_case_types_from_apps(domain):
    """
    Get the case types of modules in applications in the domain.
    :returns: A set of case_types
    """
    case_types_agg = NestedAggregation('modules', 'modules').aggregation(
        TermsAggregation('case_types', 'modules.case_type.exact'))
    q = (AppES().domain(domain).is_build(False).size(0).aggregation(
        case_types_agg))
    return set(q.run().aggregations.modules.case_types.keys) - {''}
예제 #20
0
def get_forms_for_users(domain, user_ids, start, end):
    query = (FormES().domain(domain).submitted(
        gte=start, lte=end).user_id(user_ids).aggregation(
            TermsAggregation('user_id', 'form.meta.userID').aggregation(
                TopHitsAggregation(name='top_hits_user_submissions',
                                   size=1000000,
                                   include=['form.case',
                                            'form.@xmlns']))).size(0))

    aggregations = query.run().aggregations
    return aggregations.user_id.buckets_dict
예제 #21
0
def get_all_xmlns_app_id_pairs_submitted_to_in_domain(domain):
    """This is used to get (XMLNS, app_id) from submitted forms. The results
    get combined with data from all current app versions which means
    that this is only used to get (XMLNS, app_id) combos from forms submitted
    in the past which no longer have a corresponding form in the app (e.g. form deleted)

    Given that we can cache this for a long period of time under the assumption that
    a user isn't going to submit a form and then delete it from their app immediately.
    """
    query = (FormES().domain(domain).aggregation(
        TermsAggregation("app_id", "app_id").aggregation(
            TermsAggregation("xmlns", "xmlns.exact"))).remove_default_filter(
                "has_xmlns").remove_default_filter("has_user").size(0))
    query_result = query.run()
    form_counts = set()
    for app_id, bucket in query_result.aggregations.app_id.buckets_dict.items(
    ):
        for sub_bucket in bucket.xmlns.buckets_list:
            xmlns = sub_bucket.key
            form_counts.add((xmlns, app_id))
    return form_counts
예제 #22
0
    def _get_aggregated_query(self, start, limit):
        max_size = (start or 0) + (limit or 0)
        query = HQESQuery(self.table_name).size(0)
        for filter in self.filters:
            query = query.filter(filter)

        top_agg = TermsAggregation(self.aggregation_columns[0],
                                   self.aggregation_columns[0],
                                   size=max_size)
        for agg_column in self.aggregation_columns[1:]:
            # todo support multiple aggregations
            pass

        aggregations = []
        for col in self.top_level_columns:
            if col.type == 'expanded':
                for sub_col in get_expanded_column_config(
                        self.config, col, 'en').columns:
                    aggregations.append(sub_col.aggregation)
            elif col.type == 'field':
                if col.aggregation == 'sum':
                    # todo push this to the column
                    aggregations.append(SumAggregation(col.field, col.field))

        for agg in aggregations:
            top_agg = top_agg.aggregation(agg)

        if self.order_by:
            # todo sort by more than one column
            # todo sort by by something other than the first aggregate column
            col, desc = self.order_by[0]
            if col == self.aggregation_columns[
                    0] or col == self.top_level_columns[0].field:
                top_agg = top_agg.order('_count', desc)

        query = query.aggregation(top_agg)

        return query.run()
예제 #23
0
def get_last_form_submissions_by_user(domain, user_ids, app_id=None, xmlns=None):

    missing_users = None in user_ids

    query = (
        FormES()
        .domain(domain)
        .user_ids_handle_unknown(user_ids)
        .remove_default_filter('has_user')
        .aggregation(
            TermsAggregation('user_id', 'form.meta.userID').aggregation(
                TopHitsAggregation(
                    'top_hits_last_form_submissions',
                    'received_on',
                    is_ascending=False,
                )
            )
        )
        .size(0)
    )

    if app_id:
        query = query.app(app_id)

    if xmlns:
        query = query.xmlns(xmlns)

    result = {}
    if missing_users:
        query = query.aggregation(
            MissingAggregation('missing_user_id', 'form.meta.userID').aggregation(
                TopHitsAggregation(
                    'top_hits_last_form_submissions',
                    'received_on',
                    is_ascending=False,
                )
            )
        )

    aggregations = query.run().aggregations

    if missing_users:
        result[MISSING_KEY] = aggregations.missing_user_id.bucket.top_hits_last_form_submissions.hits

    buckets_dict = aggregations.user_id.buckets_dict
    for user_id, bucket in six.iteritems(buckets_dict):
        result[user_id] = bucket.top_hits_last_form_submissions.hits

    return result
예제 #24
0
def get_latest_build_ids(domain, app_id, user_ids):
    query = (FormES(es_instance_alias=ES_EXPORT_INSTANCE).domain(domain).app(
        [app_id]).user_id(user_ids).aggregation(
            TermsAggregation('user_id', 'form.meta.userID').aggregation(
                TopHitsAggregation(
                    'top_hits_last_form_submissions',
                    'received_on',
                    is_ascending=False,
                    include=['build_id'],
                ))).size(0))
    aggregations = query.run().aggregations
    buckets_dict = aggregations.user_id.buckets_dict
    result = {}
    for user_id, bucket in buckets_dict.items():
        result[user_id] = bucket.top_hits_last_form_submissions.hits[0][
            'build_id']
    return result
예제 #25
0
    def _ledgers_per_case(self):
        db_name = get_db_aliases_for_partitioned_query()[
            0]  # just query one shard DB
        results = (LedgerValue.objects.using(db_name).filter(
            domain=self.domain).values('case_id').annotate(
                ledger_count=Count('pk')))[:100]

        case_ids = set()
        ledger_count = 0
        for result in results:
            case_ids.add(result['case_id'])
            ledger_count += result['ledger_count']

        if not case_ids:
            self.stdout.write("Domain has no ledgers")
            return

        avg_ledgers_per_case = ledger_count / len(case_ids)
        case_types_result = CaseES(for_export=True)\
            .domain(self.domain).case_ids(case_ids)\
            .aggregation(TermsAggregation('types', 'type.exact'))\
            .size(0).run()

        case_types = case_types_result.aggregations.types.keys

        self.stdout.write('\nCase Types with Ledgers')
        for type_ in case_types:
            self._print_value(
                'case_type', type_,
                CaseES().domain(self.domain).case_type(type_).count())
            db_name = get_db_aliases_for_partitioned_query()[
                0]  # just query one shard DB
            results = (CommCareCase.objects.using(db_name).filter(
                domain=self.domain, closed=True, type=type_).annotate(
                    lifespan=F('closed_on') - F('opened_on')).annotate(
                        avg_lifespan=Avg('lifespan')).values('avg_lifespan',
                                                             flat=True))
            self._print_value('Average lifespan for "%s" cases' % type_,
                              results[0]['avg_lifespan'])

            self._cases_created_per_user_per_month(type_)

        self._print_value('Average ledgers per case', avg_ledgers_per_case)

        stats = defaultdict(list)
        for db_name, case_ids_p in split_list_by_db_partition(case_ids):
            transactions_per_case_per_month = (
                LedgerTransaction.objects.using(db_name).filter(
                    case_id__in=case_ids).annotate(
                        m=Month('server_date'), y=Year('server_date')).values(
                            'case_id', 'y', 'm').annotate(count=Count('id')))
            for row in transactions_per_case_per_month:
                month = date(row['y'], row['m'], 1)
                stats[month].append(row['count'])

        final_stats = []
        for month, transaction_count_list in sorted(list(stats.items()),
                                                    key=lambda r: r[0]):
            final_stats.append(
                (month.isoformat(),
                 sum(transaction_count_list) // len(transaction_count_list)))

        self.stdout.write('Ledger updates per case')
        self._print_table(['Month', 'Ledgers updated per case'], final_stats)
예제 #26
0
    def _ledgers_per_case(self):
        results = (LedgerES(es_instance_alias=ES_EXPORT_INSTANCE).domain(
            self.domain).aggregation(
                TermsAggregation('by_case', 'case_id',
                                 size=100)).size(0).run())

        ledgers_per_case = results.aggregations.by_case
        case_ids = set()
        ledger_counts = []
        for case_id, ledger_count in ledgers_per_case.counts_by_bucket().items(
        ):
            case_ids.add(case_id)
            ledger_counts.append(ledger_count)

        if not case_ids:
            self.stdout.write("Domain has no ledgers")
            return

        avg_ledgers_per_case = sum(ledger_counts) // len(case_ids)
        case_types_result = CaseES(es_instance_alias=ES_EXPORT_INSTANCE)\
            .domain(self.domain).case_ids(case_ids)\
            .aggregation(TermsAggregation('types', 'type'))\
            .size(0).run()

        case_types = case_types_result.aggregations.types.keys

        self.stdout.write('\nCase Types with Ledgers')
        for type_ in case_types:
            self._print_value(
                'case_type', type_,
                CaseES().domain(self.domain).case_type(type_).count())
            if should_use_sql_backend(self.domain):
                db_name = get_db_aliases_for_partitioned_query()[
                    0]  # just query one shard DB
                results = (CommCareCaseSQL.objects.using(db_name).filter(
                    domain=self.domain, closed=True, type=type_).annotate(
                        lifespan=F('closed_on') - F('opened_on')).annotate(
                            avg_lifespan=Avg('lifespan')).values(
                                'avg_lifespan', flat=True))
                self._print_value('Average lifespan for "%s" cases' % type_,
                                  results[0]['avg_lifespan'])

            self._cases_created_per_user_per_month(type_)

        self._print_value('Average ledgers per case', avg_ledgers_per_case)

        if should_use_sql_backend(self.domain):
            stats = defaultdict(list)
            for db_name, case_ids_p in split_list_by_db_partition(case_ids):
                transactions_per_case_per_month = (
                    LedgerTransaction.objects.using(db_name).filter(
                        case_id__in=case_ids).annotate(
                            m=Month('server_date'),
                            y=Year('server_date')).values(
                                'case_id', 'y',
                                'm').annotate(count=Count('id')))
                for row in transactions_per_case_per_month:
                    month = date(row['y'], row['m'], 1)
                    stats[month].append(row['count'])
        else:
            transactions_per_case_per_month = (StockTransaction.objects.filter(
                case_id__in=case_ids).annotate(
                    m=Month('report__date'), y=Year('report__date')).values(
                        'case_id', 'y', 'm').annotate(count=Count('id')))

            stats = defaultdict(list)
            for row in transactions_per_case_per_month:
                month = date(row['y'], row['m'], 1)
                stats[month].append(row['count'])

        final_stats = []
        for month, transaction_count_list in sorted(list(stats.items()),
                                                    key=lambda r: r[0]):
            final_stats.append(
                (month.isoformat(),
                 sum(transaction_count_list) // len(transaction_count_list)))

        self._print_table(['Month', 'Ledgers updated per case'], final_stats)
예제 #27
0
    def test_result_parsing_complex(self):
        query = HQESQuery('cases').aggregation(
            TermsAggregation("users", 'user_id').aggregation(
                FilterAggregation('closed', filters.term(
                    'closed', True))).aggregation(
                        FilterAggregation('open', filters.term(
                            'closed', False)))).aggregation(
                                RangeAggregation('by_date', 'name', [
                                    AggregationRange(end='c'),
                                    AggregationRange(start='f'),
                                    AggregationRange(start='k', end='p')
                                ]))

        raw_result = {
            "aggregations": {
                "users": {
                    "buckets": [{
                        "closed": {
                            "doc_count": 0
                        },
                        "doc_count": 2,
                        "key": "user1",
                        "open": {
                            "doc_count": 2
                        }
                    }],
                    "doc_count_error_upper_bound":
                    0,
                    "sum_other_doc_count":
                    0
                },
                "by_date": {
                    "buckets": {
                        "*-c": {
                            "to": "c",
                            "doc_count": 3
                        },
                        "f-*": {
                            "from": "f",
                            "doc_count": 8
                        },
                        "k-p": {
                            "from": "k",
                            "to": "p",
                            "doc_count": 6
                        }
                    }
                }
            },
        }
        queryset = ESQuerySet(raw_result, deepcopy(query))
        self.assertEqual(queryset.aggregations.users.buckets.user1.key,
                         'user1')
        self.assertEqual(queryset.aggregations.users.buckets.user1.doc_count,
                         2)
        self.assertEqual(
            queryset.aggregations.users.buckets.user1.closed.doc_count, 0)
        self.assertEqual(
            queryset.aggregations.users.buckets.user1.open.doc_count, 2)
        self.assertEqual(
            queryset.aggregations.users.buckets_dict['user1'].open.doc_count,
            2)
        self.assertEqual(queryset.aggregations.users.counts_by_bucket(),
                         {'user1': 2})
        self.assertEqual(queryset.aggregations.by_date.counts_by_bucket(), {
            '*-c': 3,
            'f-*': 8,
            'k-p': 6,
        })