前言
最近在学习天天生鲜项目,记录一下在django中如何使用全文搜索
我们在面对商品搜索时可以通过使用sql语句进行查询,但是这样效率很低,推荐使用全文搜索框架进行检索。
haystack及whoosh介绍
- haystack 是django的开源搜索框架,该框架支持Solr、Elasticsearch、Whoosh、Xapian搜索引擎,不用直接更改代码,直接切换引擎,减少代码量
- Whoosh是一个纯python实现的全文搜索引擎,没有二进制文件,比较小巧,配置比较简单,性能略低,但是稳定。
安装和配置
1、 安装python包
pip install django-haystack
pip install whoosh
2、在settings.py
文件中注册应用 haystack,在INSTALLED_APPS
中插入haystack
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tinymce', # 富文本编辑器
'haystack', # 全文检索框架
'apps.user',
'apps.cart',
'apps.goods',
'apps.order',
]
添加全文检索框架配置
# 全文检索框架的配置
HAYSTACK_CONNECTIONS = {
'default': {
# 使用whoosh引擎
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
#'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine', # 更换分词方式为结巴分词
# 索引文件路径
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
}
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
索引文件的生成
1、在 goods(你需要建立索引的应用) 应用的目录下信新建一个 search_indexes.py(文件名固定)
文件,在其中定义一个商品的索引类
# 定义索引类
from haystack import indexes
# 导入你的模型类
from apps.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()
2、在 templates 下面新建目录 search/indexes/goods
,其中search
和indexes
文件名固定,goods为创建索引的应用名
3、在此目录下新建一个文件goodssku_text.txt
文件(其中goodssku
为需要创建索引的模型类名的小写),并编辑需要建立索引的字段
# 指定根据表中的哪些字段建立索引数据
{{ object.name }} # 根据商品的名称建立索引
{{ object.desc }} # 根据商品的简介建立索引
{{ object.goods.detail }} # 根据商品的详情建立索引
4、使用命令生成索引文件
python manage.py rebuild_index
会在项目根目录下生成一个whoosh_index
的文件夹,文件名是上面在settings.py
中配置的
使用全文索引
1、配置url
在项目url下,添加全文索引的url
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tinymce/', include('tinymce.urls')), # 富文本编辑器
url(r'^search/', include('haystack.urls')), # 全文检索框架
url(r'^user/', include('apps.user.urls', namespace='user')), # 用户模块
url(r'^', include('apps.goods.urls', namespace='goods')), # 商品模块
url(r'^cart/', include('apps.cart.urls', namespace='cart')), # 购物车模块
url(r'^order/', include('apps.order.urls', namespace='order')) # 订单模块
]
2、模板下表单搜索时设置表单内容如下:
<div class="search_con fl">
<form action="/search" method="get">
<input type="text" class="input_text fl" name="q" placeholder="搜索商品">
<input type="submit" class="input_btn fr" name="" value="搜索">
</form>
</div>
进行搜索提交时,会通过haystack 搜索数据
3、全文索引结果处理
搜索出结果后,haystack 会把搜索出的结果传递给 templates/search/search.html
,文件名和文件夹名固定。
传递的上下文包括:
query:搜索关键字
page:当前页的page对象 -》 遍历 page 对象,获取到的是 SearchResult 类的实例,对象的属性 object 才是模型类的对象
paginator:分页 paginator对象
通过 HAYSTACK_SEARCH_PLER_PAGE可以控制每页显示数量,在settings.py
中添加
# 显示指定搜索结果每页显示的条数
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5
{% for item in page %}
<li>
<a href="{% url 'goods:detail' item.object.id %}"><img src="{{ item.object.image.url }}"></a>
<h4><a href="{% url 'goods:detail' item.object.id %}">{{ item.object.name }}</a></h4>
<div class="operate">
<span class="prize">¥{{ item.object.price }}</span>
<span class="unit">{{ item.object.price }}/{{ item.object.unite }}</span>
<a href="#" class="add_goods" title="加入购物车"></a>
</div>
</li>
{% endfor %}
改变分词方式
全文搜索框架自带的分词方式对部分中文支持不是很好,我们需要替换为结巴分词
1、安装jeiba分词模块
pip install jieba
2、在虚拟环境中找到hytrack的目录下的backends目录
3、在上面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、复制 whoosh_backend.py
文件,改名为whoosh_cn_backend.py
5、打开复制的新文件,引入上面定义的中文解析类,采用jeiba分词,
from .ChineseAnalyzer import ChineseAnalyzer
6、更改词语分析类
查找:
analyzer = StemmingAnalyzer()
改为:
analyzer = ChineseAnalyzer()
7、在 settings.py 文件中配置,将之前定义的whoosh_backend
改为whoosh_cn_backend
# 全文检索框架的配置
HAYSTACK_CONNECTIONS = {
'default': {
# 使用whoosh引擎
# 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine', # 更换分词方式为结巴分词
# 索引文件路径
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
}
}
8、重新创建索引
python manage.py rebuild_index