Django全文检索实现:基于HayStack + Whoosh引擎 + Jieba中文分词

Posted 程序设计实验室

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django全文检索实现:基于HayStack + Whoosh引擎 + Jieba中文分词相关的知识,希望对你有一定的参考价值。

涉及到的工具

  • haystack是django的开源搜索框架,该框架支持Solr, Elasticsearch, Whoosh, **Xapian搜索引擎,不用更改代码,直接切换引擎,减少代码量。

  • 搜索引擎使用Whoosh,这是一个由纯Python实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,当然性能自然略低。

  • 中文分词Jieba,由于Whoosh自带的是英文分词,对中文的分词支持不是太好,故用jieba替换whoosh的分词组件。

Model配置

class Post(models.Model):
    """post 文章页面"""
    id = models.AutoField(primary_key=True, max_length=20)
    name = models.CharField(max_length=200, help_text="Post文章的URL链接名称")
    post_category = models.ForeignKey(PostCategory, blank=True, null=True, default=None, on_delete=models.SET_NULL)
    post_author = models.ForeignKey(PostAuthor, blank=True, null=True, default=None, on_delete=models.SET_NULL)
    post_date = models.DateTimeField(default=timezone.now, help_text="创建日期")
    post_modified = models.DateTimeField(default=timezone.now, help_text="修改日期")
    post_content = models.TextField(help_text="html格式的页面内容,仅在page类型才可用")
    post_title = models.CharField(max_length=200)
    post_summary = models.TextField(max_length=300, blank=True)
    post_status = models.CharField(choices=(('publish''已发布'), ('draft''草稿')), default='publish', max_length=20,
                                   help_text="页面状态")

    # post_slug = models.CharField(max_length=200, help_text="URL链接名称")

    def __str__(self):
        return self.post_title

安装Python模块

  • whoosh

  • django-haystack

  • jieba

修改 whoosh 的分析器

将文件whoosh_backend.py(该文件路径为python路径/lib/python版本/site-packages/haystack/backends/whoosh_backend.py)拷贝到app文件夹下面,修改如下
添加from jieba.analyse import ChineseAnalyzer

修改为如下

schema_fields[field_class.index_fieldname] =
    TEXT(stored=True, analyzer=ChineseAnalyzer(),
            field_boost=field_class.boost)

修改settings.py

  • 添加 Haystack 到Django的 INSTALLED_APPS

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE''Core.whoosh_backend.WhooshEngine',
        'PATH': os.path.join(BASE_DIR, 'Resources''index''whoosh'),
    },
}

注:

  • Core 是我的App名称,请根据情况替换成你自己的App文件夹名称

  • PATH为存放Whoosh索引文件的文件夹。

  • 其他引擎的配置请查阅官方文档。

建立索引

在需要搜索功能的App文件夹下建立search_indexes.py文件,用于创建索引。

内容如下:

import datetime
from haystack import indexes
from Core import models


class PostIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)

    post_author = indexes.CharField(model_attr='post_author')
    post_date = indexes.DateTimeField(model_attr='post_date')

    def get_model(self):
        return models.Post

    def index_queryset(self, using=None):
        """Used when the entire index for model is updated."""
        return self.get_model().objects.filter(post_date__lte=datetime.datetime.now())

每个索引里面必须有且只能有一个字段为document=True,这代表haystack 和搜索引擎将使用此字段的内容作为索引进行检索(primary field)。其他的字段只是附属的属性,方便调用,并不作为检索数据。

注意:如果使用一个字段设置了document=True,则一般约定此字段名为text,这是在SearchIndex类里面一贯的命名,以防止后台混乱,当然名字你也可以随便改,不过不建议改。

并且,haystack提供了use_template=True在text字段,这样就允许我们使用数据模板去建立搜索引擎索引的文件,使用方便(官方推荐,当然还有其他复杂的建立索引文件的方式,目前我还不知道),数据模板的路径为yourapp/templates/search/indexes/yourapp/classname_text.txt,例如本例子为Resources/templates/search/indexes/Core/post_text.txt
文件名必须为要索引的类名_text.txt,其内容为:

{{ object.post_title }}
{{ object.post_author }}
{{ object.post_content }}
{{ object.post_summary }}

这个数据模板的作用是对

  • Post.post_title

  • Post.post_author

  • Post.post_content

  • Post.post_summary

这四个字段建立索引,当检索的时候会对这三个字段做全文检索匹配。

配置URL

在链接配置中加入

    path('search/', include('haystack.urls')),

编写search.html

在 templates/search/ 文件夹下添加 search.html 文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>Search</h2>

<form method="get" action=".">
    <table>
        {{ form.as_table }}
        <tr>
            <td> </td>
            <td>
                <input type="submit" value="Search">
            </td>
        </tr>
    </table>

    {% if query %}
        <h3>Results</h3>

        {% for result in page.object_list %}
            <p>
                <a href="{{ result.object.get_absolute_url }}">{{ result.object.post_title }}</a>
            </p>
        {% empty %}
            <p>No results found.</p>
        {% endfor %}

        {% if page.has_previous or page.has_next %}
            <div>
                {% if page.has_previous %}<a href="?q={{ query }}&page={{ page.previous_page_number }}">{% endif %}«
                Previous{% if page.has_previous %}</a>{% endif %}
                |
                {% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}">{% endif %}Next »
                {% if page.has_next %}</a>{% endif %}
            </div>
        {% endif %}
    {% else %}
        {# Show some example queries to run, maybe query syntax, something else? #}
    {% endif %}
</form>
</body>
</html>

建立索引

使用python manage.py rebuild_index或者使用update_index命令。

在 settings.py 里加入以下配置,实现自动刷新索引。

HAYSTACK_SIGNAL_PROCESSOR = "haystack.signals.RealtimeSignalProcessor"

这样就OK啦,可以打开 网站/search 试试看搜索功能了~

SearchQuerySet 初窥

这个 SearchQuerySet 类似于DjangoORM框架里的 QuerySet,熟悉Django的同学应该很快能上手,不过做结果处理的话会比较麻烦。
用到SearchQuerySet一般都是用于Ajax API,我发现之前用于 QuerySet 的序列化器不能用于 SearchQuerySet,要做的话还需要做一些修改。
这个等有时间再继续改。或者我再看看官网文档,研究一下。

用法挺简单的,看一下官方文档就行,已经写得很清楚了~

About



以上是关于Django全文检索实现:基于HayStack + Whoosh引擎 + Jieba中文分词的主要内容,如果未能解决你的问题,请参考以下文章

使用haystack实现Django的全文搜索 -- Elasticsearch搜索引擎

Django使用haystack借助Whoosh实现全文搜索功能

django-haystack全文检索

愚公系列2022年01月 Django商城项目 26-搜索引擎功能实现

Django Haystack 全文检索与关键词高亮

Django Haystack 全文检索与关键词高亮