使用 Django 和 Elasticsearch 索引新对象

Posted

技术标签:

【中文标题】使用 Django 和 Elasticsearch 索引新对象【英文标题】:Indexing new object with Django & Elasticsearch 【发布时间】:2017-06-28 07:22:24 【问题描述】:

我无法让 django 自动索引新创建的对象。

我使用groupby 创建了一些自定义数据。

每次创建新模型时,都应为其编制索引。

确实索引了“title”值,但“tag”值不存在。

所以,我创建了一个手动函数“manual_index”。当我运行它时,“标签”值 确实 被添加到索引中。但是这个过程必须手动触发。

如何在每次创建新对象时获取要保存的“标记”值?

我正在使用 elasticsearch_dsl

搜索.py

class TaskIndex(DocType):
    title = String()
    class Meta:
        index = 'task-index'

def manual_index():
    TaskIndex.init()
    es = Elasticsearch()
    bulk(client=es, actions=(b.indexing() for b in models.Task.objects.all().iterator()))

模型.py

from itertools import groupby

class Tag(models.Model):
    name = models.CharField("Name", max_length=5000, blank=True)
    taglevel = models.IntegerField("Tag level", null=True, blank=True)

class Item(models.Model):
    title = models.CharField("Title", max_length=10000, blank=True)
    tag = models.ManyToManyField('Tag', blank=True)

    def get_grouped_tags(self):
        tag = self.tag.order_by('taglevel')
        grouped_tags = 
            tag_level: [
                 'name': tag_of_level.name, 'taglevel': tag_of_level.taglevel, 
                for tag_of_level in tags_of_level
            ] for tag_level, tags_of_level
            in groupby(tag, lambda tag: tag.taglevel)
        
        return grouped_tags

    def indexing(self):
        obj = TaskIndex(
            meta='id': self.id,
            title=self.title,
            tag=self.get_grouped_tags()
        obj.save()
        return obj.to_dict(include_meta=True)

【问题讨论】:

【参考方案1】:

这里有几个问题,首先你要保存所有内容两次 - 一次在 indexing 中(通过调用 .save()),然后在 manual_index 中。

manual_index 中的代码效率更高,绝对应该用于重新索引整个数据集。对于单独的模型创建,您几乎可以按原样使用indexing 方法并使用django 的signal 框架。只需修改indexing 方法以返回TaskIndex 对象(无需在其上调用.save()!)并将以下等效代码添加到您的models.py 中: https://github.com/HonzaKral/es-django-example/blob/master/qa/models.py#L128-L137

在您的代码中,您将只使用indexing 而不是我的to_search

希望这会有所帮助, 洪萨

【讨论】:

哦,抱歉,我忽略了您对 tag 对象的评论。存在的问题是,在 Django 方面,indexing 在保存多对多数据之前被触发。有几种解决方法,最安全的是也使用m2m_changed 信号 - docs.djangoproject.com/en/1.10/ref/signals/#m2m-changed

以上是关于使用 Django 和 Elasticsearch 索引新对象的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch:如何在 Django 中使用 Elasticsearch

Elasticsearch:如何在 Django 中使用 Elasticsearch

Django + ElasticSearch + Docker - 无论我使用啥主机名,连接超时

第15篇-使用Django进行ElasticSearch的简单方法

django使用haystack来调用Elasticsearch搜索引擎

Django + Elasticsearch——搜索精彩的TED演讲