diff --git a/docs/topics/search/backends.rst b/docs/topics/search/backends.rst index 24d19ab0c..c19da48b5 100644 --- a/docs/topics/search/backends.rst +++ b/docs/topics/search/backends.rst @@ -7,13 +7,45 @@ Backends Wagtailsearch has support for multiple backends giving you the choice between using the database for search or an external service such as Elasticsearch. -You can configure which backend to use with the ``WAGTAILSEARCH_BACKENDS`` setting. +You can configure which backend to use with the ``WAGTAILSEARCH_BACKENDS`` setting: +.. code-block:: python + + WAGTAILSEARCH_BACKENDS = { + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch', + } + } + + +``AUTO_UPDATE`` +=============== + +By default, Wagtail will automatically keep all indexes up to date. This could impact performance when editing content, especially if your index is hosted on an external service. + +The ``AUTO_UPDATE`` setting allows you to disable this on a per-index basis: + +.. code-block:: python + + WAGTAILSEARCH_BACKENDS = { + 'default': { + 'BACKEND': ..., + 'AUTO_UPDATE': False, + } + } + +If you have disabled auto update, you must run the :ref:`update_index` command on a regular basis to keep the index in sync with the database. + + +``BACKEND`` +=========== + +Here's a list of backends that Wagtail supports out of the box. .. _wagtailsearch_backends_database: Database Backend (default) -========================== +-------------------------- ``wagtail.wagtailsearch.backends.db.DBSearch`` @@ -29,7 +61,7 @@ If any of these features are important to you, we recommend using Elasticsearch Elasticsearch Backend -===================== +--------------------- ``wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch`` @@ -71,6 +103,6 @@ If you prefer not to run an Elasticsearch server in development or production, t Rolling Your Own -================ +---------------- Wagtail search backends implement the interface defined in ``wagtail/wagtail/wagtailsearch/backends/base.py``. At a minimum, the backend's ``search()`` method must return a collection of objects or ``model.objects.none()``. For a fully-featured search backend, examine the Elasticsearch backend code in ``elasticsearch.py``. diff --git a/wagtail/tests/settings.py b/wagtail/tests/settings.py index c5e06592a..88f7eb235 100644 --- a/wagtail/tests/settings.py +++ b/wagtail/tests/settings.py @@ -150,6 +150,7 @@ try: 'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch', 'TIMEOUT': 10, 'max_retries': 1, + 'AUTO_UPDATE': False, } if 'ELASTICSEARCH_URL' in os.environ: diff --git a/wagtail/wagtailsearch/backends/__init__.py b/wagtail/wagtailsearch/backends/__init__.py index fa6fcf017..3877677ad 100644 --- a/wagtail/wagtailsearch/backends/__init__.py +++ b/wagtail/wagtailsearch/backends/__init__.py @@ -51,9 +51,12 @@ def get_search_backend(backend='default', **kwargs): return backend_cls(params) -def get_search_backends(): +def get_search_backends(with_auto_update=False): if hasattr(settings, 'WAGTAILSEARCH_BACKENDS'): - for backend in settings.WAGTAILSEARCH_BACKENDS.keys(): + for backend, params in settings.WAGTAILSEARCH_BACKENDS.items(): + if with_auto_update and params.get('AUTO_UPDATE', True) is False: + continue + yield get_search_backend(backend) else: yield get_search_backend('default') diff --git a/wagtail/wagtailsearch/signal_handlers.py b/wagtail/wagtailsearch/signal_handlers.py index 6f701af31..395e59967 100644 --- a/wagtail/wagtailsearch/signal_handlers.py +++ b/wagtail/wagtailsearch/signal_handlers.py @@ -20,7 +20,7 @@ def post_save_signal_handler(instance, **kwargs): indexed_instance = get_indexed_instance(instance) if indexed_instance: - for backend in get_search_backends(): + for backend in get_search_backends(with_auto_update=True): backend.add(indexed_instance) @@ -28,7 +28,7 @@ def post_delete_signal_handler(instance, **kwargs): indexed_instance = get_indexed_instance(instance) if indexed_instance: - for backend in get_search_backends(): + for backend in get_search_backends(with_auto_update=True): backend.delete(indexed_instance) diff --git a/wagtail/wagtailsearch/tests/test_backends.py b/wagtail/wagtailsearch/tests/test_backends.py index ef22ae3c0..9a50d9c42 100644 --- a/wagtail/wagtailsearch/tests/test_backends.py +++ b/wagtail/wagtailsearch/tests/test_backends.py @@ -9,7 +9,7 @@ from django.core import management from wagtail.tests.utils import WagtailTestUtils from wagtail.tests.search import models -from wagtail.wagtailsearch.backends import get_search_backend, InvalidSearchBackendError +from wagtail.wagtailsearch.backends import get_search_backend, get_search_backends, InvalidSearchBackendError from wagtail.wagtailsearch.backends.db import DBSearch @@ -132,9 +132,11 @@ class BackendTests(WagtailTestUtils): self.assertEqual(set(results), {self.testa, self.testb, self.testc.searchtest_ptr, self.testd.searchtest_ptr}) -@override_settings(WAGTAILSEARCH_BACKENDS={ - 'default': {'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch'} -}) +@override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': {'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch'} + } +) class TestBackendLoader(TestCase): def test_import_by_name(self): db = get_search_backend(backend='default') @@ -149,3 +151,56 @@ class TestBackendLoader(TestCase): def test_invalid_backend_import(self): self.assertRaises(InvalidSearchBackendError, get_search_backend, backend="I'm not a backend!") + + def test_get_search_backends(self): + backends = list(get_search_backends()) + + self.assertEqual(len(backends), 1) + self.assertIsInstance(backends[0], DBSearch) + + @override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch' + }, + 'another-backend': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch' + }, + } + ) + def test_get_search_backends_multiple(self): + backends = list(get_search_backends()) + + self.assertEqual(len(backends), 2) + + def test_get_search_backends_with_auto_update(self): + backends = list(get_search_backends(with_auto_update=True)) + + # Auto update is the default + self.assertEqual(len(backends), 1) + + @override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch', + 'AUTO_UPDATE': False, + }, + } + ) + def test_get_search_backends_with_auto_update_disabled(self): + backends = list(get_search_backends(with_auto_update=True)) + + self.assertEqual(len(backends), 0) + + @override_settings( + WAGTAILSEARCH_BACKENDS={ + 'default': { + 'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch', + 'AUTO_UPDATE': False, + }, + } + ) + def test_get_search_backends_without_auto_update_disabled(self): + backends = list(get_search_backends()) + + self.assertEqual(len(backends), 1)