def test_words(self): # search strings with single words self.assertEqual([(None, 'word')], parse_search_terms('word')) self.assertEqual([(None, 'multiple'), (None, 'words')], parse_search_terms('multiple words')) self.assertEqual([(None, 'extraneous'), (None, 'whitespace')], parse_search_terms(' extraneous whitespace '))
def test_fields(self): self.assertEqual([('title', 'willows')], parse_search_terms('title:willows')) self.assertEqual([('title', 'willows'), ('title', 'wind')], parse_search_terms('title:willows title:wind')) self.assertEqual([(None, 'frog'), (None, 'toad'), ('title', 'willows'), ('title', 'wind')], parse_search_terms('frog toad title:willows title:wind'))
def test_fields(self): self.assertEqual([('title', 'willows')], parse_search_terms('title:willows')) self.assertEqual([('title', 'willows'), ('title', 'wind')], parse_search_terms('title:willows title:wind')) self.assertEqual( [(None, 'frog'), (None, 'toad'), ('title', 'willows'), ('title', 'wind')], parse_search_terms('frog toad title:willows title:wind'))
def to_python(self, value): if not value: return [] else: try: return parse_search_terms(value) except Exception: raise forms.ValidationError('There was an error parsing your search: %s' \ % value)
def test_phrases(self): # quoted phrases self.assertEqual([(None, 'exact phrase')], parse_search_terms('"exact phrase"'))
def keyword_search_suggest(request): '''Suggest helper for keyword search. If the search string ends with a recognized field name with an optional value, e.g. ``user:`` or ``user:A``, looks up existing values using Solr facets. Returns a JSON response with the 15 most common matching terms in the requested field with the search term prefix, if any. If the search string is empty or ends with a space, suggests available search fields with an explanation. .. Note:: Due to the current implementation and the limitations of facet querying in Solr, the search term is case-sensitive and only matches at the beginning of the string. Return format is suitable for use with `JQuery UI Autocomplete`_ widget. .. _JQuery UI Autocomplete: http://jqueryui.com/demos/autocomplete/ :param request: the http request passed to the original view method (used to retrieve the search term) ''' term = request.GET.get('term', '') suggestions = [] # if term is empty or ends in a space, suggest available search fields if term == '' or term[-1] == ' ': suggestions = [ {'label': field, 'value': '%s%s' % (term, field), 'category': 'Search Fields', 'desc': desc} for field, desc in KeywordSearch.field_descriptions.iteritems() ] # otherwise, check if there is a field to look up values for else: term_prefix, sep, term_suffix = term.rpartition(' ') value_prefix = term_prefix + sep # parse the last search term try: # parse could error in some cases parsed_terms = parse_search_terms(term_suffix) field, prefix = parsed_terms[-1] except Exception: field, prefix = None, '' if prefix is None: prefix = '' # if field can be faceted, suggest terms if field in KeywordSearch.facet_fields.keys(): facet_field = KeywordSearch.facet_fields[field] # date created is a special case if field == 'created': sort = 'index' category = 'Date Added' # if less than 4 characters, suggest year if len(prefix) < 4: facet_field = 'created_year' result_fmt = '%s' # between 4 and 7, suggest year-month elif len(prefix) < 7: facet_field = 'created_month' result_fmt = '%s' # suggest full dates else: result_fmt = '%s ' elif field in ['added_by', 'user']: # added_by or user sort = 'count' category = 'Users' result_fmt = '"%s" ' # collection label if field == 'coll': sort = 'count' category = 'Collection' result_fmt = '%s ' # if the term is numeric facet by source_id if prefix and prefix.isdigit(): facet_field = 'collection_source_id' solr = solr_interface() facetq = solr.query().paginate(rows=0) # filter by current user permssions # facetq = filter_by_perms(facetq, request.user) # return the 15 most common terms in the requested facet field # with a specified prefix facetq = facetq.facet_by(facet_field, prefix=prefix, sort=sort, limit=15) facets = facetq.execute().facet_counts.facet_fields # generate a dictionary to return via json with label (facet value # + count), and actual value to use suggestions = [{'label': '%s (%d)' % (facet, count), 'value': '%s%s:' % (value_prefix, field) + \ result_fmt % facet, 'category': category} for facet, count in facets[facet_field] ] return HttpResponse(json_serializer.encode(suggestions), content_type='application/json')