Django Haystack обновляет индекс быстрее

Я уже некоторое время использую Django Haystack, и это здорово! У меня довольно тяжелый сайт с данными, которые нужно время от времени обновлять (от 15 до 30 минут).

При использовании python manage.py update_index обновление данных занимает много времени. Есть ли способ ускорить это? Или, возможно, обновить только измененные данные, если это возможно.

В настоящее время я использую Django Haystack 1.2.7 с Solr в качестве бэкэнда и Django 1.4.

Спасибо!!!


РЕДАКТИРОВАТЬ:

Да, я пытался прочитать эту часть документации, но мне действительно нужен способ ускорить индексацию. Возможно, обновлять только последние данные, а не обновлять все. Я нашел get_updated_field, но не знаю, как им пользоваться. В документации только упоминается, почему он используется, но не показаны реальные примеры.


РЕДАКТИРОВАТЬ 2:

start = DateTimeField(model_attr='start', null=True, faceted=True, --HERE?--)

РЕДАКТИРОВАТЬ 3:

Хорошо, я применил решение ниже, но когда я попытался перестроить_индекс (с данными 45000), мой компьютер чуть не сломался. После 10 минут ожидания появилась ошибка:

 File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/dist-packages/haystack/management/commands/rebuild_index.py", line 16, in handle
    call_command('update_index', **options)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 150, in call_command
    return klass.execute(*args, **defaults)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/dist-packages/haystack/management/commands/update_index.py", line 193, in handle
    return super(Command, self).handle(*apps, **options)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 304, in handle
    app_output = self.handle_app(app, **options)
  File "/usr/local/lib/python2.7/dist-packages/haystack/management/commands/update_index.py", line 229, in handle_app
    do_update(index, qs, start, end, total, self.verbosity)
  File "/usr/local/lib/python2.7/dist-packages/haystack/management/commands/update_index.py", line 109, in do_update
    index.backend.update(index, current_qs)
  File "/usr/local/lib/python2.7/dist-packages/haystack/backends/solr_backend.py", line 73, in update
    self.conn.add(docs, commit=commit, boost=index.get_field_weights())
  File "/usr/local/lib/python2.7/dist-packages/pysolr.py", line 686, in add
    m = ET.tostring(message, encoding='utf-8')
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1127, in tostring
    ElementTree(element).write(file, encoding, method=method)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 821, in write
    serialize(write, self._root, encoding, qnames, namespaces)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 940, in _serialize_xml
    _serialize_xml(write, e, encoding, qnames, None)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 940, in _serialize_xml
    _serialize_xml(write, e, encoding, qnames, None)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 915, in _serialize_xml
    write("<" + tag)
MemoryError

person prototype    schedule 11.12.2012    source источник
comment
Пробовали ли вы что-то из документа Best Practices? django-haystack.readthedocs.org/en/latest/   -  person Spacedman    schedule 11.12.2012
comment
Я не использовал серверную часть solr, поэтому не могу вам помочь, извините.   -  person Stephen Paulger    schedule 19.12.2012


Ответы (1)


get_updated_field должна возвращать строку, содержащую имя атрибута модели, содержащего дату обновления модели (документы стога сена). DateField с auto_now=True был бы идеальным для этого (Django docs).

Например, в моей модели UserProfile есть поле с именем updated

models.py

class UserProfile(models.Model):
    user = models.ForeignKey(User)
    # lots of other fields snipped
    updated = models.DateTimeField(auto_now=True)

search_indexes.py

class UserProfileIndex(SearchIndex):
    text = CharField(document=True, use_template=True)
    user = CharField(model_attr='user')
    user_fullname = CharField(model_attr='user__get_full_name')

    def get_model(self):
        return UserProfile

    def get_updated_field(self):
        return "updated"

Затем, когда я запускаю ./manage.py update_index --age=10, он индексирует только профили пользователей, обновленные за последние 10 часов.

person Stephen Paulger    schedule 11.12.2012
comment
Где я должен добавить auto_now=True в search_indexes.py? Я сделал пример в своем вопросе выше. Также, где именно я должен реализовать get_updated_field. Спасибо за Ваш ответ!! - person prototype; 12.12.2012
comment
auto_now будет использоваться в Model в models.py, а функция get_updated_field — в классе SearchIndex. - person Stephen Paulger; 17.12.2012
comment
Ваше решение сработает, я в этом не сомневаюсь... но когда я запустил пересборку_индекса, появилась ошибка... - person prototype; 18.12.2012
comment
Я тоже не сомневаюсь, так как у меня это работает :) О чем говорит ваша ошибка? Если вы также передадите -v 2 команде update_index, вы получите более подробный вывод. - person Stephen Paulger; 18.12.2012
comment
Будьте осторожны, если ваша модель поискового индекса содержит ссылки на другие модели, являющиеся частью индекса. Последнее обновление не будет изменено при изменении, а затем не будет индексироваться (представьте модели категорий на основном объекте). - person dalore; 14.08.2013
comment
Проблема Далор решается путем сохранения основного объекта модели одновременно с сохранением связанного объекта модели. - person user2104778; 04.01.2014
comment
К вашему сведению, если вы используете метод Django QuerySet для массовых обновлений .update(), функция auto_now не будет учитываться, поскольку сигнал post_save не срабатывает. Это означает, что опция --age выше не будет работать для обновления только недавно измененных моделей. Чтобы обойти это, вы можете зациклить набор запросов и использовать .save(), или, чтобы продолжить использовать .update(), вам просто нужно вручную обновить время, например. updated=datetime.datetime.now() . - person mynameistechno; 21.06.2015
comment
В дополнение к ответу @mynameistechno, если вы используете .save(update_fields['some_field']), поле updated не будет обновляться (!). Таким образом, используйте либо .save(), либо упомянутый обходной путь datetime. - person nik_m; 03.01.2017