django-haystack+jieba+whoosh实现全文检索

写在前面

电商网站,免不了用户搜索商品,根据一般的思路是mysql的模糊匹配或者正则匹配,但是这种方法不仅效率低下,而且对于某些分词处理也很难处理,本文讲解简单的实现全文检索,利用django-haystack+jieba+whoosh,话不多说,进入正题。

全文检索

全文检索不同于特定字段的模糊查询,使用全文检索的效率更高,并且能够对于中文进行分词处理

  • haystack:全文检索的框架,支持whoosh、solr、Xapian、Elasticsearc四种全文检索引擎

  • whoosh: 纯python写的全文搜索引擎,虽然性能比不上sphinx、xapian、Elasticsearc等,但是无二进制包,程序不会莫名其妙崩溃,对于小型的站点,whoosh已经足够使用

  • jieba:一款免费的中文分词包,如果觉得不好用可以使用一些收费产品

1、安装包

  • 在虚拟环境中一次安装需要的包
pip install django-haystack
pip install whoosh
pip install jieba

2、修改配置

  • 1、修改 Yourproject/settin.py 文件,安装应用haystack
INSTALLED_APPS = [
    ...
    'haystack', #全文检索
]
  • 2、全文检索框架配置
HAYSTACK_CONNECTIONS = {
    'default': {
        # 使用whoosh引擎
        'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
        # 索引文件路径
        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
        # 这个文件夹也不需要自己建立,会自动生成
    }
}

# 指定如何对搜索结果分页,这里设置为每 10 项结果为一页。
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10

# 指定什么时候更新索引,这里我们使用 haystack.signals.RealtimeSignalProcessor,作用是每当有商品更新时就更新索引。由于商品更新不会太频繁,因此实时更新没有问题。
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
  • 3、改变分词方式步骤1:建立ChineseAnalyzer.py文件

保存在haystack的安装文件夹下,路径如下

cd path_to_virtualenv/lib/python3.6/site_packages/haystack/backends
# ChineseAnalyzer.py文件内容
import jieba
from whoosh.analysis import Tokenizer, Token


class ChineseTokenizer(Tokenizer):
    def __call__(self, value, positions=False, chars=False,
                 keeporiginal=False, removestops=True,
                 start_pos=0, start_char=0, mode='', **kwargs):
        t = Token(positions, chars, removestops=removestops, mode=mode,
                  **kwargs)
        seglist = jieba.cut(value, cut_all=True)
        for w in seglist:
            t.original = t.text = w
            t.boost = 1.0
            if positions:
                t.pos = start_pos + value.find(w)
            if chars:
                t.startchar = start_char + value.find(w)
                t.endchar = start_char + value.find(w) + len(w)
            yield t


def ChineseAnalyzer():
    return ChineseTokenizer()
  • 4、改变分词方式步骤2:复制whoosh_backend.py文件,改名为whoosh_cn_backend.py
# 刚才的路径下

cp whoosh_backend.py whoosh_cn_backend.py

在whoosh_cn_backend.py文件中添加:

#添加
from haystack.backends.ChineseAnalyzer  import ChineseAnalyzer

并修改:
最好将原来的注释掉,再复制一行改成自己的。

# 将文件中的
analyzer=StemmingAnalyzer()
改为
analyzer=ChineseAnalyzer()

3、索引文件的生成

  • 在应用目录(即要设为检索关键字的应用目录下)下新建一个search_indexes.py文件(名字是固定的不能改),我这里是goods目录下面的。
from haystack import indexes
#引入你项目下的model(也就是你要将其作为检索关键词的models)
from goods.models import GoodsSKU


# 指定对于摸个类的某些数据建立索引
# 索引类名格式:模型类型+Index
class GoodsSkuIndex(indexes.SearchIndex, indexes.Indexable):
    # 索引字段
    # use_template=True:指定根据表中的哪些字段建立索引文件,把说明放在一个文件中
    text = indexes.CharField(document=True, use_template=True)

    def get_model(self):
        # 返回你的模型类
        return GoodsSKU

    # 建立索引的数据
    def index_queryset(self, using=None):
        return self.get_model().objects.all()

4、创建“模型类名称_text.txt”文件

  • 在目录”templates/search/indexes/应用名称/”下创建”模型类名称小写_text.txt”文件(我建立的是goodssku_text.txt),这个模板的作用是让text字段包含的内容,在后面的模板中可能会有用。
# 指定根据表中的哪些字段建立索引数据
{{ object.name }} # 根据商品的名称建立索引
{{ object.desc }} # 根据商品的简介简历索引
{{ object.goods.detail }} # 根据商品的详情简历索引

5、配置路由

  • 在本项目(不是某个应用)的urls.py中配置检索结果返回的地址
from django.urls import path, include

urlpatterns = [
    # 其它path设置

    path(r'search/', include('haystack.urls')),
    # django小于 2.0版本的用以下的url
    # url(r'^search/', include('haystack.urls')),
]

6、创建search.html

  • haystack 会把搜索出来的结果传递给 templates/search.html,传递的上下文包括:

    • query: 搜索关键字

    • page: 当前页的page对象 --> 遍历page对象,获取到的是 SearchResult: # 对象的属性object才模型类的对象

    • paginator: 分页paginator对象

  • 在目录”templates/search/”下建立search.html作为检索结果返回的页面(可自己进行定制)

{%extends 'base_detail_list.html'%}
{% block title %}天天生鲜-商品搜索结果列表{% endblock title %}

{% block main_content %}
     


    
    {% for item in page %}
  • {{ item.object.name }}

    ¥{{ item.object.price }} {{ item.object.unite }} {% if request.session.user_name|default:'' != '' %} {% else %} {% endif %}
  • {%endfor%}
{% if page.has_previous %} <上一页 {% endif %} {%for pindex in paginator.page_range%} {%if pindex == page.number%} {{pindex}} {%else%} {{pindex}} {%endif%} {%endfor%} {% if page.has_next %} 下一页> {% endif %}
{% endblock main_content %} {% block bottom_files %} {% endblock bottom_files %}

7、生成索引

  • 在Terminal窗口中输入
python manage.py rebuild_index
  • 出现以下字段说明索引已经建立成功
All documents removed
Indexting 2 goods
...
  • 以后可以通过以下命令来更新索引。
python manage.py update_index

(ps:如果在settings.py中添加了

HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

就不用手动更新索引,系统会自动更新。)

  • 生成成功后在根目录下会生成一个whoosh_index的文件夹。

你可能感兴趣的:(django-haystack+jieba+whoosh实现全文检索)