如何使用elasticsearch-dsl-py保持Elasticsearch索引最新?

时间:2018-01-04 21:19:33

标签: elasticsearch-dsl elasticsearch-dsl-py

我开发了一个小型的个人信息目录,我的客户端通过Django管理界面访问和更新。该信息需要可搜索,因此我设置了我的Django站点以将该数据保存在搜索索引中。我最初使用Haystack和Whoosh作为搜索索引,但最近我不得不放弃这些工具,转而使用Elasticsearch 5.

以前,只要目录中的任何内容更新,代码就会清除整个搜索索引并从头开始重建。此目录中只有几百个条目,因此不具有严重的性能。不幸的是,尝试在Elasticsearch中做同样的事情是非常不可靠的,因为我认为在我的代码中某种竞争条件。

这里是我编写的使用elasticsearch-py和elasticsearch-dsl-py的代码:

import elasticsearch
import time
from django.apps import apps
from django.conf import settings
from elasticsearch.helpers import bulk
from elasticsearch_dsl.connections import connections
from elasticsearch_dsl import DocType, Text, Search

# Create the default Elasticsearch connection using the host specified in settings.py.
elasticsearch_host = "{0}:{1}".format(
    settings.ELASTICSEARCH_HOST['HOST'], settings.ELASTICSEARCH_HOST['PORT']
)
elasticsearch_connection = connections.create_connection(hosts=[elasticsearch_host])


class DepartmentIndex(DocType):
    url = Text()
    name = Text()
    text = Text(analyzer='english')
    content_type = Text()

    class Meta:
        index = 'departmental_directory'


def refresh_index():
    # Erase the existing index.
    try:
        elasticsearch_connection.indices.delete(index=DepartmentIndex().meta.index)
    except elasticsearch.exceptions.NotFoundError:
        # If it doesn't exist, the job's already done.
        pass

    # Wait a few seconds to give enough time for Elasticsearch to accept that the 
    # DepartmentIndex is gone before we try to recreate it.
    time.sleep(3)

    # Rebuild the index from scratch.
    DepartmentIndex.init()
    Department = apps.get_model('departmental_directory', 'Department')
    bulk(
        client=elasticsearch_connection, 
        actions=(b.indexing() for b in Department.objects.all().iterator())
    )

每当refresh_index()被保存时,我设置了Django信号来调用Department。但由于此错误,refresh_index()经常崩溃:

elasticsearch.exceptions.RequestError: TransportError(400, u'index_already_exists_exception', u'index [departmental_directory/uOQdBukEQBWvMZk83eByug] already exists')

这就是我添加time.sleep(3)电话的原因。我假设在调用DepartmentIndex.init()时,索引尚未完全删除,这导致了错误。

我的猜测是,我只是以完全错误的方式解决这个问题。必须有一个更好的方法来保持弹性搜索索引达到 - 使用elasticsearch-dsl-py的日期,但我不知道它是什么,我还没有能够通过他们的文档弄明白。

从头开始搜索"重建弹性搜索索引"在谷歌上提供了大量的结果,如何重新索引你的弹性搜索数据",但这不是我想要的。我需要使用来自应用数据库的新的,更新的数据替换数据。

1 个答案:

答案 0 :(得分:2)

也许这会有所帮助:https://github.com/HonzaKral/es-django-example/blob/master/qa/models.py#L137-L146

无论哪种方式,您都希望拥有2种方法:将所有数据批量加载到新索引(https://github.com/HonzaKral/es-django-example/blob/master/qa/management/commands/index_data.py)中,并且可选地使用上述方法/信号进行同步。