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
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
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
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
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