【问题标题】:How does one keep an Elasticsearch index up-to-date using elasticsearch-dsl-py?如何使用 elasticsearch-dsl-py 使 Elasticsearch 索引保持最新?
【发布时间】:2018-01-04 21:19:33
【问题描述】:

我开发了一个小型个人信息目录,我的客户可以通过 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())
    )

我已经设置了 Django 信号,以便在 Department 被保存时调用 refresh_index()。但是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- 使 elasticsearch 索引保持最新py,但我只是不知道它是什么,而且我无法通过他们的文档弄清楚。

在 google 上搜索“从头开始重建 elasticsearch 索引”会给出“如何重新索引您的 elasticsearch 数据”的大量结果,但这不是我想要的。我需要将数据替换为我的应用数据库中更新的新数据。

【问题讨论】:

  • 要保持索引是最新的,不需要一次又一次地创建索引
  • 我知道这不是一个好方法。您想提出更好的方法吗?
  • 首先,删除那些索引然后重新创建它们... Elasticsearch将标记旧索引中的记录要删除并为您创建一个新索引,因为es创建的索引具有唯一的uid ..那里不会有问题的..
  • “首先,删除那些索引,然后重新创建它们……”这不正是我正在做的吗??

标签: elasticsearch-dsl elasticsearch-dsl-py


【解决方案1】:

也许这会有所帮助: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) 中,以及(可选)使用上述方法/或信号进行同步。

【讨论】:

  • 该项目非常有用,可以作为更新我的代码的基础!谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-08-29
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 2020-03-10
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
相关资源
最近更新 更多