diff --git a/wagtail/wagtailsearch/backends/base.py b/wagtail/wagtailsearch/backends/base.py index 3a2d25dd5..0f3765406 100644 --- a/wagtail/wagtailsearch/backends/base.py +++ b/wagtail/wagtailsearch/backends/base.py @@ -176,6 +176,9 @@ class BaseSearch(object): def __init__(self, params): pass + def get_rebuilder(self): + return None + def reset_index(self): raise NotImplementedError diff --git a/wagtail/wagtailsearch/backends/elasticsearch.py b/wagtail/wagtailsearch/backends/elasticsearch.py index 92c76120f..e9215760a 100644 --- a/wagtail/wagtailsearch/backends/elasticsearch.py +++ b/wagtail/wagtailsearch/backends/elasticsearch.py @@ -352,6 +352,56 @@ class ElasticSearchResults(BaseSearchResults): return max(hit_count, 0) +class ElasticSearchIndexRebuilder(object): + def __init__(self, es, index_name): + self.es = es + self.index_name = index_name + + def start(self): + # Delete old index + try: + self.es.indices.delete(self.index_name) + except NotFoundError: + pass + + # Create new index + self.es.indices.create(self.index_name, INDEX_SETTINGS) + + def add_model(self, model): + # Get mapping + mapping = ElasticSearchMapping(model) + + # Put mapping + self.es.indices.put_mapping(index=self.index_name, doc_type=mapping.get_document_type(), body=mapping.get_mapping()) + + def add_items(self, model, obj_list): + if not class_is_indexed(model): + return + + # Get mapping + mapping = ElasticSearchMapping(model) + doc_type = mapping.get_document_type() + + # Create list of actions + actions = [] + for obj in obj_list: + # Create the action + action = { + '_index': self.index_name, + '_type': doc_type, + '_id': mapping.get_document_id(obj), + } + action.update(mapping.get_document(obj)) + actions.append(action) + + # Run the actions + bulk(self.es, actions) + + def finish(self): + # Refresh index + self.es.indices.refresh(self.index_name) + + class ElasticSearch(BaseSearch): def __init__(self, params): super(ElasticSearch, self).__init__(params) @@ -391,6 +441,9 @@ class ElasticSearch(BaseSearch): timeout=self.es_timeout, **params) + def get_rebuilder(self): + return ElasticSearchIndexRebuilder(self.es, self.es_index) + def reset_index(self): # Delete old index try: diff --git a/wagtail/wagtailsearch/management/commands/update_index.py b/wagtail/wagtailsearch/management/commands/update_index.py index c6c092906..fcc98dabe 100644 --- a/wagtail/wagtailsearch/management/commands/update_index.py +++ b/wagtail/wagtailsearch/management/commands/update_index.py @@ -22,9 +22,16 @@ class Command(BaseCommand): # Get backend backend = get_search_backend(backend_name) - # Reset the index - self.stdout.write(backend_name + ": Reseting index") - backend.reset_index() + # Get rebuilder + rebuilder = backend.get_rebuilder() + + if not rebuilder: + self.stdout.write(backend_name + ": Backend doesn't support rebuild. Skipping") + return + + # Start rebuild + self.stdout.write(backend_name + ": Starting rebuild") + rebuilder.start() for model, queryset in object_list: self.stdout.write(backend_name + ": Indexing model '%s.%s'" % ( @@ -32,15 +39,15 @@ class Command(BaseCommand): model.__name__, )) - # Add type - backend.add_type(model) + # Add model + rebuilder.add_model(model) - # Add objects - backend.add_bulk(model, queryset) + # Add items + rebuilder.add_items(model, queryset) - # Refresh index - self.stdout.write(backend_name + ": Refreshing index") - backend.refresh_index() + # Finish rebuild + self.stdout.write(backend_name + ": Finishing rebuild") + rebuilder.finish() option_list = BaseCommand.option_list + ( make_option('--backend',