Example #1
0
def get_resource_filter_options(resource):
    """Return the available filter options for the given resource

    @type resource: dict
    @param resource: Dictionary representing a resource
    @rtype: dict
    @return: A dictionary associating each option's name to a dict
            defining:
                - label: The label to display to users;
                - checked: True if the option is currently applied.
    """
    options = resource_filter_options(resource)
    filter_list = toolkit.request.params.get('filters', '').split('|')
    filters = {}
    for filter_def in filter_list:
        try:
            (key, value) = filter_def.split(':', 1)
        except ValueError:
            continue
        if key not in filters:
            filters[key] = [value]
        else:
            filters[key].append(value)
    result = {}
    for o in options:
        if options[o].get('hide', False):
            continue
        result[o] = options[o]
        result[o]['checked'] = o in filters and 'true' in filters[o]
    return result
Example #2
0
    def datastore_validate(self, context, data_dict, all_field_ids):
        if 'filters' in data_dict:
            resource_show = p.toolkit.get_action('resource_show')
            resource = resource_show(context, {'id': data_dict['resource_id']})
            # Remove both filter options and field groups from filters
            # These will be handled separately
            options = chain(resource_filter_options(resource).keys(), [FIELD_DISPLAY_FILTER])

            for o in options:
                if o in data_dict['filters']:
                    del data_dict['filters'][o]

        return data_dict
Example #3
0
    def datasolr_search(self, context, data_dict, field_types, query_dict):
        # Add our custom filters
        if 'filters' in data_dict:

            resource_show = p.toolkit.get_action('resource_show')
            resource = resource_show(context, {'id': data_dict['resource_id']})
            options = resource_filter_options(resource)
            for o in options:
                if o in data_dict['filters'] and 'true' in data_dict['filters'][o]:
                    if 'solr' in options[o]:
                        query_dict['q'][0].append(options[o]['solr'])
                elif 'solr_false' in options[o]:
                    query_dict['q'][0].append(options[o]['solr_false'])
        self.enforce_max_limit(query_dict, 'rows')
        return query_dict
Example #4
0
    def datastore_search(self, context, data_dict, all_field_ids, query_dict):
        # Add our options filters
        if 'filters' in data_dict:
            resource_show = p.toolkit.get_action('resource_show')
            resource = resource_show(context, {'id': data_dict['resource_id']})
            options = resource_filter_options(resource)
            for o in options:
                if o in data_dict['filters'] and 'true' in data_dict['filters'][o]:
                    if 'sql' in options[o]:
                        query_dict['where'].append(options[o]['sql'])
                elif 'sql_false' in options[o]:
                    query_dict['where'].append(options[o]['sql_false'])

        # Enhance the full text search, by adding support for double quoted expressions. We leave the
        # full text search query intact (so we benefit from the full text index) and add an additional
        # LIKE statement for each quoted group.
        if 'q' in data_dict and not isinstance(data_dict['q'], dict):
            for match in re.findall('"[^"]+"', data_dict['q']):
                query_dict['where'].append((
                    '"{}"::text LIKE %s'.format(resource['id']),
                    '%' + match[1:-1] + '%'
                ))

        self.enforce_max_limit(query_dict)

        # CKAN's field auto-completion uses full text search on individual fields. This causes
        # problems because of stemming issues, and is quite slow on our data set (even with an
        # appropriate index). We detect this type of queries and replace them with a LIKE query.
        # We also cancel the count query which is not needed for this query and slows things down.
        if 'q' in data_dict and isinstance(data_dict['q'], dict) and len(data_dict['q']) == 1:
            field_name = data_dict['q'].keys()[0]
            if data_dict['fields'] == field_name and data_dict['q'][field_name].endswith(':*'):
                escaped_field_name = '"' + field_name.replace('"', '') + '"'
                value = '%' + data_dict['q'][field_name].replace(':*', '%')

                query_dict = {
                    'distinct': True,
                    'limit': query_dict['limit'],
                    'offset': query_dict['offset'],
                    'sort': [escaped_field_name],
                    'where': [(escaped_field_name + '::citext LIKE %s', value)],
                    'select': [escaped_field_name],
                    'ts_query': '',
                    'count': False
                }
        return query_dict
Example #5
0
def get_resource_filter_pills(resource):
    """
    Get filter pills
    We don't want the field group pills - these are handled separately in get_resource_field_groups
    @param resource:
    @return:
    """

    filter_dict = parse_request_filters()

    def get_pill_filters(exclude_field, exclude_value):
        """
        Build filter, using filters which aren't exclude_field=exclude_value
        @param exclude_field:
        @param exclude_value:
        @return:
        """

        filters = []
        for field, values in filter_dict.items():
            for value in values:
                if not (field == exclude_field and value == exclude_value):
                    filters.append('%s:%s' % (field, value))

        return '|'.join(filters)

    pills = {}

    options = resource_filter_options(resource)

    field_labels = {}

    field_groups = resource_view_get_field_groups(resource)

    if field_groups:
        for fields in field_groups.values():
            for field_name, label in fields.items():
                field_labels[field_name] = label

    for field, values in filter_dict.items():
        for value in values:
            filters = get_pill_filters(field, value)

            # If this is the _tmgeom field, we don't want to output the whole value as it's in the format:
            # POLYGON ((-100.45898437499999 41.902277040963696, -100.45898437499999 47.54687159892238, -92.6806640625 47.54687159892238, -92.6806640625 41.902277040963696, -100.45898437499999 41.902277040963696))
            if field == '_tmgeom':
                pills['geometry'] = {'Polygon': filters}
            elif field in options:
                label = options[field]['label']
                try:
                    pills['Options'][label] = filters
                except KeyError:
                    pills['Options'] = {label: filters}
            else:

                try:
                    label = field_labels[field]
                except KeyError:
                    label = field

                try:
                    pills[label][value] = filters
                except KeyError:
                    pills[label] = {value: filters}

    # Remove the field group key, if it exists
    pills.pop(FIELD_DISPLAY_FILTER, None)
    return pills