Repository: oppia/oppia

Issue:
Clearing search index from admin page raise exception.
<!--
  - Thanks for taking the time to report a bug in the Oppia project.
  - Before filing a new issue, please do a quick search to check that it hasn't
  - already been filed on the [issue tracker](https://github.com/oppia/oppia/issues)._
  -->

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
 1. Go to the Admin page.
 2. Click on the Misc tab.
 3. Click "Clear search index" button.

**Observed behavior**
In terminal:
```
INFO     2019-01-31 17:04:21,215 base.py:475] Traceback (most recent call last):
  File "/home/dubeysandeep/oppia_tools/google_appengine_1.9.67/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/home/dubeysandeep/oppia/core/domain/acl_decorators.py", line 490, in test_super_admin
    return handler(self, **kwargs)
  File "/home/dubeysandeep/oppia/core/controllers/admin.py", line 158, in post
    exp_services.clear_search_index()
AttributeError: 'module' object has no attribute 'clear_search_index'

ERROR    2019-01-31 17:04:21,215 base.py:485] Exception raised: 'module' object has no attribute 'clear_search_index'
```
**Expected behavior**
Should clear search index without any error.
**Screenshots**
If applicable, add screenshots to help explain your problem.
![image](https://user-images.githubusercontent.com/16653571/52071242-8fdefd80-25a8-11e9-9c7b-e078b84b1e4c.png)




Discussion:

Resolving patch:
diff --git a/core/controllers/admin.py b/core/controllers/admin.py
--- a/core/controllers/admin.py
+++ b/core/controllers/admin.py
@@ -31,6 +31,7 @@
 from core.domain import recommendations_services
 from core.domain import rights_manager
 from core.domain import role_services
+from core.domain import search_services
 from core.domain import stats_services
 from core.domain import topic_domain
 from core.domain import topic_services
@@ -155,7 +156,8 @@ def post(self):
                     self._generate_dummy_explorations(
                         num_dummy_exps_to_generate, num_dummy_exps_to_publish)
             elif self.payload.get('action') == 'clear_search_index':
-                exp_services.clear_search_index()
+                search_services.clear_collection_search_index()
+                search_services.clear_exploration_search_index()
             elif self.payload.get('action') == 'save_config_properties':
                 new_config_property_values = self.payload.get(
                     'new_config_property_values')


Test patch:
diff --git a/core/controllers/admin_test.py b/core/controllers/admin_test.py
--- a/core/controllers/admin_test.py
+++ b/core/controllers/admin_test.py
@@ -15,8 +15,10 @@
 """Tests for the admin page."""
 
 from core.controllers import base
+from core.domain import collection_services
 from core.domain import exp_domain
 from core.domain import exp_services
+from core.domain import search_services
 from core.domain import stats_domain
 from core.domain import stats_services
 from core.tests import test_utils
@@ -295,3 +297,31 @@ def test_that_handler_raises_exception(self):
         self.assertEqual(
             response['error'],
             'Exploration \'exp\' does not have \'state name\' state.')
+
+
+class ClearSearchIndexTest(test_utils.GenericTestBase):
+    """Tests that search index gets cleared."""
+
+    def test_clear_search_index(self):
+        exp_services.load_demo('0')
+        result_explorations = search_services.search_explorations(
+            'Welcome', 2)[0]
+        self.assertEqual(result_explorations, ['0'])
+        collection_services.load_demo('0')
+        result_collections = search_services.search_collections('Welcome', 2)[0]
+        self.assertEqual(result_collections, ['0'])
+        self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
+        self.login(self.ADMIN_EMAIL, is_super_admin=True)
+        response = self.get_html_response('/admin')
+        csrf_token = self.get_csrf_token_from_response(response)
+        generated_exps_response = self.post_json(
+            '/adminhandler', {
+                'action': 'clear_search_index'
+            },
+            csrf_token=csrf_token)
+        self.assertEqual(generated_exps_response, {})
+        result_explorations = search_services.search_explorations(
+            'Welcome', 2)[0]
+        self.assertEqual(result_explorations, [])
+        result_collections = search_services.search_collections('Welcome', 2)[0]
+        self.assertEqual(result_collections, [])
diff --git a/core/domain/search_services_test.py b/core/domain/search_services_test.py
--- a/core/domain/search_services_test.py
+++ b/core/domain/search_services_test.py
@@ -298,3 +298,19 @@ def mock_get_rights(unused_exp_id):
             search_services.update_exploration_status_in_search(self.EXP_ID)
 
         self.assertEqual(delete_docs_counter.times_called, 1)
+
+    def test_clear_exploration_search_index(self):
+        exp_services.load_demo('0')
+        result = search_services.search_explorations('Welcome', 2)[0]
+        self.assertEqual(result, ['0'])
+        search_services.clear_exploration_search_index()
+        result = search_services.search_explorations('Welcome', 2)[0]
+        self.assertEqual(result, [])
+
+    def test_clear_collection_search_index(self):
+        collection_services.load_demo('0')
+        result = search_services.search_collections('Welcome', 2)[0]
+        self.assertEqual(result, ['0'])
+        search_services.clear_collection_search_index()
+        result = search_services.search_collections('Welcome', 2)[0]
+        self.assertEqual(result, [])