全文检索 haystack + whoosh + jieba
全文检索不同于特定字段的模糊查询,使用全文检索的效率再高,并且能够对于中文进行分词处理。
- haystack:全文检索框架,支持whoosh、solr、Xaplan、Elasticsearc四种全文检索引擎
- whoosh:纯python编写的全文搜索引擎,虽然 性能比不上sphinx、xapian、elasticsearc等,但是无二进制包,程序不会莫名其妙的崩溃,对于小型的站点,whoosh已经足够使用,
- jieba:中文分词包
安装包:
pip install django-haystack
pip install whoosh
pip install jieba
修改settings文件
INSTALLWS_APPS = [
'haystack', # 全文检索框架
]
全文检索框架的配置
HAYSTACK_CONNECTIONS = {
'default': {
# 使用whoosh搜索引擎
'ENGINE': 'goods.whoosh_cn_backend.WhooshEngine',
# 索引文件的路径
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
},
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 设置每页显示的数目,默认为20,可以自己修改
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 8
在要检索的app下面,创建search_indexes.py文件
# 定义索引类
from haystack import indexes
from .models import Goods
# 索引类名格式:模型类名+Index
class GoodsIndex(indexes.SearchIndex, indexes.Indexable):
"""
"""
# 索引字段:use_template 指定根据表中的哪些字段 建立索引文件
# 把说明放在一个文件中
text = indexes.CharField(document=True, use_template=True)
# 建立检索字段,model_attr模型属性,如果需要多字段的话,在这里添加需要检索的字段
goods_name = indexes.NgramField(model_attr="goods_name")
def get_model(self):
return Goods # 返回的模型类
def index_queryset(self, using=None):
return self.get_model().objects.all()
在templates下面创建如下文件夹 search/indexes/goods,在这下面创建goods_text.txt(goods是需要检索的模型类的小写)
注:名称是固定的,不可随意更改
在goods_test.txt里面写入需要检索的字段
# 指定根据表中的哪些字段建立索引数据
{{object.goods_name}} # 根据商品的名称建立索引
进入到项目所在的目录,创建索引文件:python manage.py rebuild_index
html下搜索框固定设置
<form action="./search" method="get"> <--form的method必须为get-->
{% csrf_token %}
<input type="text" placeholder="搜索品牌 店铺..." name="q"> <--inpu的name必须为q-->
<input type="submit" value="搜索" >
</form>
配置项目下的urls
from django.urls import path, include
urlpatterns = [
path('search/', include('haystack.urls')) # 全文检过框架
]
**搜索出来的结果,haystack会把搜索结果传递给templates/search目录下的search.html,所以需要在templates的search文件夹下创建search.html文件。**传递的上下文包括:
query: 搜索的关键字
page:当前页的page对象
serchResult类的实例对象,对象的属性是object
paginator:分页paginator对象
# 设置每页显示的数目,默认为20,可以自己修改
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 8
配置中文分词器,这里用到的模块为jieba,文件名为:tokenizer.py,把本文件放在与search_indexes.py同目录下,我这里放在了goods文件夹下
from jieba import cut_for_search
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 = cut(value, cut_all=False) # (精确模式)使用结巴分词库进行分词
seglist = cut_for_search(value) # (搜索引擎模式) 使用结巴分词库进行分词
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 # 通过生成器返回每个分词的结果token
def ChineseAnalyzer():
return ChineseTokenizer()
中文搜索引擎配置,文件名:whoosh_cn_backend.py,把本文件放在与search_indexes.py同目录下,我这里放在了goods文件夹下
# ctrl+F搜索 “build_schema”函数
# 导入中文分析器
from goods.tokenizer import ChineseAnalyzer
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True)