Commit d6b515a1 by Matthew Piatetsky

Add orgs autocomplete to typeahead

ECOM-4738
parent c9c077bc
......@@ -432,3 +432,18 @@ class TypeaheadSearchViewTests(TypeaheadSerializationMixin, LoginMixin, Elastics
self.assertEqual(response.status_code, 200)
response_data = response.json()
self.assertEqual(response_data['course_runs'][0]['title'], title + "2")
def test_typeahead_authoring_organizations_partial_search(self):
""" Test typeahead response with partial organization matching. """
authoring_organizations = OrganizationFactory.create_batch(3)
course_run = CourseRunFactory(authoring_organizations=authoring_organizations)
program = ProgramFactory(authoring_organizations=authoring_organizations)
partial_key = authoring_organizations[0].key[0:5]
response = self.get_typeahead_response(partial_key)
self.assertEqual(response.status_code, 200)
expected = {
'course_runs': [self.serialize_course_run(course_run)],
'programs': [self.serialize_program(program)]
}
self.assertDictEqual(response.data, expected)
......@@ -126,12 +126,24 @@ class TypeaheadSearchView(APIView):
permission_classes = (IsAuthenticated,)
def get_results(self, query):
course_runs = SearchQuerySet().models(CourseRun).filter(SQ(title_autocomplete=query) | SQ(course_key=query))
sqs = SearchQuerySet()
clean_query = sqs.query.clean(query)
course_runs = sqs.models(CourseRun).filter(
SQ(title_autocomplete=clean_query) |
SQ(course_key=clean_query) |
SQ(authoring_organizations_autocomplete=clean_query)
)
course_runs = course_runs.filter(published=True).exclude(hidden=True)
course_runs = course_runs[:self.RESULT_COUNT]
programs = SearchQuerySet().models(Program).filter(SQ(title_autocomplete=query))
programs = sqs.models(Program).filter(
SQ(title_autocomplete=clean_query) |
SQ(authoring_organizations_autocomplete=clean_query)
)
programs = programs.filter(status=ProgramStatus.Active)
programs = programs[:self.RESULT_COUNT]
return course_runs, programs
def get(self, request, *args, **kwargs):
......
......@@ -33,6 +33,9 @@ class OrganizationsMixin:
def prepare_authoring_organizations(self, obj):
return self._prepare_organizations(obj.authoring_organizations.all())
def prepare_authoring_organizations_autocomplete(self, obj):
return self.prepare_authoring_organizations(obj)
class BaseIndex(indexes.SearchIndex):
model = None
......@@ -60,6 +63,7 @@ class BaseCourseIndex(OrganizationsMixin, BaseIndex):
key = indexes.CharField(model_attr='key', stored=True)
title = indexes.CharField(model_attr='title', boost=TITLE_FIELD_BOOST)
title_autocomplete = indexes.NgramField(model_attr='title', boost=TITLE_FIELD_BOOST)
authoring_organizations_autocomplete = indexes.NgramField()
short_description = indexes.CharField(model_attr='short_description', null=True)
full_description = indexes.CharField(model_attr='full_description', null=True)
subjects = indexes.MultiValueField(faceted=True)
......@@ -193,6 +197,7 @@ class ProgramIndex(BaseIndex, indexes.Indexable, OrganizationsMixin):
marketing_url = indexes.CharField(null=True)
organizations = indexes.MultiValueField(faceted=True)
authoring_organizations = indexes.MultiValueField(faceted=True)
authoring_organizations_autocomplete = indexes.NgramField()
authoring_organization_uuids = indexes.MultiValueField()
subject_uuids = indexes.MultiValueField()
staff_uuids = indexes.MultiValueField()
......
......@@ -99,6 +99,8 @@ class ConfigurableElasticBackend(ElasticsearchSearchBackend):
# and all words containing ing would come back in typeahead.
self.specify_analyzers(mapping=mapping, field='title_autocomplete',
index_analyzer='ngram_analyzer', search_analyzer='lowercase')
self.specify_analyzers(mapping=mapping, field='authoring_organizations_autocomplete',
index_analyzer='ngram_analyzer', search_analyzer='lowercase')
return (content_field_name, mapping)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment