diff --git a/cms/djangoapps/contentstore/courseware_index.py b/cms/djangoapps/contentstore/courseware_index.py index bcf26f3572..2a05caf64c 100644 --- a/cms/djangoapps/contentstore/courseware_index.py +++ b/cms/djangoapps/contentstore/courseware_index.py @@ -640,3 +640,22 @@ class CourseAboutSearchIndexer(object): "Successfully added %s course to the course discovery index", course_id ) + + @classmethod + def _get_location_info(cls, normalized_structure_key): + """ Builds location info dictionary """ + return {"course": unicode(normalized_structure_key), "org": normalized_structure_key.org} + + @classmethod + def remove_deleted_items(cls, structure_key): + """ Remove item from Course About Search_index """ + searcher = SearchEngine.get_search_engine(cls.INDEX_NAME) + if not searcher: + return + + response = searcher.search( + doc_type=cls.DISCOVERY_DOCUMENT_TYPE, + field_dictionary=cls._get_location_info(structure_key) + ) + result_ids = [result["data"]["id"] for result in response["results"]] + searcher.remove(cls.DISCOVERY_DOCUMENT_TYPE, result_ids) diff --git a/cms/djangoapps/contentstore/tests/test_courseware_index.py b/cms/djangoapps/contentstore/tests/test_courseware_index.py index e146cb914c..1b290a29d6 100644 --- a/cms/djangoapps/contentstore/tests/test_courseware_index.py +++ b/cms/djangoapps/contentstore/tests/test_courseware_index.py @@ -17,7 +17,7 @@ from django.conf import settings from course_modes.models import CourseMode from xmodule.library_tools import normalize_key_for_search from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.django import SignalHandler +from xmodule.modulestore.django import SignalHandler, modulestore from xmodule.modulestore.edit_info import EditInfoMixin from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.inheritance import InheritanceMixin @@ -335,6 +335,25 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): response = self.search() self.assertEqual(response["total"], 5) + def _test_delete_course_from_search_index_after_course_deletion(self, store): # pylint: disable=invalid-name + """ + Test that course will also be delete from search_index after course deletion. + """ + self.DOCUMENT_TYPE = 'course_info' # pylint: disable=invalid-name + response = self.search() + self.assertEqual(response["total"], 0) + + # index the course in search_index + self.reindex_course(store) + response = self.search() + self.assertEqual(response["total"], 1) + + # delete the course and look course in search_index + modulestore().delete_course(self.course.id, self.user_id) + self.assertIsNone(modulestore().get_course(self.course.id)) + response = self.search() + self.assertEqual(response["total"], 0) + def _test_deleting_item(self, store): """ test deleting an item """ # Publish the vertical to start with @@ -604,6 +623,11 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): def test_course_location_null(self, store_type): self._perform_test_using_store(store_type, self._test_course_location_null) + @ddt.data(*WORKS_WITH_STORES) + def test_delete_course_from_search_index_after_course_deletion(self, store_type): + """ Test for removing course from CourseAboutSearchIndexer """ + self._perform_test_using_store(store_type, self._test_delete_course_from_search_index_after_course_deletion) + @patch('django.conf.settings.SEARCH_ENGINE', 'search.tests.utils.ForceRefreshElasticSearchEngine') @ddt.ddt diff --git a/openedx/core/djangoapps/content/course_overviews/signals.py b/openedx/core/djangoapps/content/course_overviews/signals.py index 26dcca6490..951ebbd65f 100644 --- a/openedx/core/djangoapps/content/course_overviews/signals.py +++ b/openedx/core/djangoapps/content/course_overviews/signals.py @@ -24,3 +24,7 @@ def _listen_for_course_delete(sender, course_key, **kwargs): # pylint: disable= invalidates the corresponding CourseOverview cache entry if one exists. """ CourseOverview.objects.filter(id=course_key).delete() + # import CourseAboutSearchIndexer inline due to cyclic import + from cms.djangoapps.contentstore.courseware_index import CourseAboutSearchIndexer + # Delete course entry from Course About Search_index + CourseAboutSearchIndexer.remove_deleted_items(course_key)