商品搜索
P66 商品搜索-全文检索概念
搜索时如果是原生SQL语句:
模糊查询:select * from df_goods_sku where name like '%草莓%' or desc like '%草莓%'
开发时不用like,它的查效率很低
百度:维护着关键字对应的信息
搜索引擎:
1:可以对表中的某些字段进行关键词分析,建立关键词对应的索引数据
对某些字段内容进行关键词分析,将其分解成对应的关键词,并建立关键词对应的索引数据
很
好吃
的
草莓:sku_id1 sku_id2 sku_id5
字典
全文检索框架:
可以帮助用户使用搜索引擎
配合全文检索框架使用whoosh引擎,帮助用户搜索数据
P67 商品搜索-全文检索框架和引擎的安装和配置
全文检索框架:haystack
搜索引擎:whoosh
pip3 install django-haystack
pip3 install whoosh
在settings.py中的INSTALLED_APPS:注册全文检索框架haystack
配置haystack和whoosh:
# 全文检索框架的配置
HAYSTACK_CONNECTIONS = {
'default': {
# 使用whoosh引擎
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
# 索引文件路径
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
}
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
配置实际上在django-haystack包中
cd xxxx/venv/lib/python3.x/site-packages/
cd haystack/
cd backends/
其中的ChineseAnalyzer.py和whoosh_cn_backend.py原始安装完是没有的
原始配置应该是:
haystack.backends.whoosh_backend.WhooshEngine
P68 商品搜索-生成索引文件
最终是要根据GoodsSKU类对应表中的数据生成索引数据
1. 新建一个GoodsSKU类对应的索引类,在apps.goods下方,即模型类所在的应用新建文件search_indexes.py
2. 在文件search_indexes.py中定义索引类
# 定义索引类
from haystack import indexs
# 导入你的模型类
from goods.models import GoodsSKU
# 指定对于某个类的某些数据建立索引
# 索引类名格式: 模型类名+Index
class GoodsSKUIndex(indexes.SearchIndex, indexes.Indexable):
# 索引字段
# document=True说明text为索引字段
# 建立GoodsSKU类对应的表中的数据的索引信息 use_template指定根据表中的哪些字段建立索引文件,把说明放在一个文件中
text = indexes.CharField(document=True, use_template=True)
def get_model(self):
# 返回你的模型类
return GoodsSKU
# 建立索引的数据
# 该方法最终返回哪些内容,就会对哪些内容建立索引
# self.get_model()返回的是GoodsSKU,self.get_model().objects.all()则表示查询该表中的所有数据,因此对该表中的所有数据建立索引
def index_queryset(self, using=None)
return self.get_model().objects.all()
总结三点
1.导入模型类
2.索引类名格式:模型类名+Index
3.get_model中返回你的模型类
use_template指定根据表中的哪些字段建立索引文件,把说明放在一个文件中
文件格式:
在templates中创建search/indexes/你的模型类所在app/模型类名小写_text.txt
templates/search/indexes/goods/goodssku_text.txt
# 在该文件中指定根据表中的哪些字段建立索引数据
{{ object.模型类的属性 }}
{{ }}
{{ object.name }} # 根据商品的名称建立索引
{{ object.desc }} # 根据商品的简介建立索引
# 根据商品的详情建立索引
{{ object.goods.detail }} # 根据商品的详情建立索引
接下来生成索引数据:
进入自己的项目,通过manage.py生成索引数据
python3 manage.py rebuild_index
P69 商品搜索-全文检索的使用
有了索引文件之后可以借助全文检索引擎帮助我们搜索数据
找到base.html中的搜索部分,将其放入一个表单中,其中的method="get"和name="q"固定,其余不固定
<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>
此时点击之后会访问该地址/search,该地址对应的处理, 我们的目的是借助搜索引擎,因此我们需要去配置该地址,将其匹配完之后对应的处理应该交给搜索引擎去做
配置地址:
path('search/', include('haystack.urls')) # 全文检索框架
我们点击搜索之后访问/search地址,最终匹配之后的处理过程就不用管了,此时请求已经交给haystack。
全文检索结果:
搜索出结果后,haystack会把搜索出的结果传递给template/search目录下的search.html,传递的上下文包括:
query: 搜索关键字
page: 当前页的page对象---》遍历page对象,获取到的是SearchResult类的实例对象,对象的属性object才是模型类的对象。
paginator:分页paginator对象
通过HAYSTACK_SEARCH_RESULTS_PER_PAGE 可以控制每页显示数量
在templates/search目录下创建一个search.html
query: 搜索关键字
page: 当前页的page对象---在搜索完之后,它在传递数据时会对搜索的结果进行分页,然后会把当前页的page对象传过来,这里的page对象和之前的page对象是一样的,所以可以遍历page对象获取里面的数据。
遍历page对象,获取到的是SearchResult类的实例对象,在这个对象中包含了商品的数据,如何获取到实例对象中包含的数据?该实例对象中有个属性为object,这个object就是模型类所包含的对象
对象的属性object才是模型类的对象。
search_test.html
<body>
搜索的关键字:{{ query }}<br/>
当前页的Page对象:{{ page }}<br/>
<ul>
{% for item in page %}
<li>{{ item.object }}</li> # SearchResult对象
<li>{{ item.object }}</li> # GoodsSKU 对象,通过遍历出的item.object可以获取到搜索到的商品的信息
{% endfor %}
</ul>
</body>
获取到item中的商品信息
接下来要获取页码page的列表,此时paginator对象已经传给模板
paginator.page_range<---分页之后页码的列表
搜索页:/search?q=搜索关键字&page=第多少页的内容,不加页码默认显示第一页
上一页:依旧需要搜索,访问搜索地址,搜索谁,跟在?后面,访问第几页的内容,页码也需要传过来-----》/search?q={{ query }}&page={{ page.previous_page_number }}
下一页:/search?q={{ query }}&page={{ page.next_page_number }}
当前页:/search?q={{ query }}&page={{ pindex }}
P70 商品搜索-更改分词方式
默认whoosh引擎在进行关键词分析的时候,使用的是默认的引擎,有些汉字分析的并不准确,这里会更改掉whoosh引擎中词语分析的类,使用中文分词包jieba分词
pip3 install jieba
import jieba
str = '很不错的草莓'
# cut_all=True 只要能分析出来的词语都给分析出来
res = jieba.cut(str, cut_all=True)
res是个生成器,直接遍历获取到分词之后的结果
for val in res:
print(val)
如何更改whoosh的默认词语分析类?
1.找到/haystack/backends/目录
2.创建一个ChineseAnalyzer.py文件
import jieba
from whoosh.analysis import Tokenizer, Token
# __call__有call说明是可调用的
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()
创建好之后,更改/haystack/backends/目录下的whoosh_backend.py中的词语的分析类
注:不要在源文件上改,copy一份进行修改
cp whoosh_backend.py whoosh_cn_backend.py
此时修改copy版本的词语分析类
# 导入ChineseAnalyzer函数
from ChineseAnalyzer import ChineseAnalyzer
# 导入之后用此函数去替换默认的词语分析类
查找StemmingAnalyzer
将
analyzer = StemmingAnalyzer()
改为
analyzer = ChineseAnalyzer()
此时分词使用的是jieba分词
记得去setting.py中修改whoosh的配置,
将
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
改为
'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
重新生成索引文件
回到项目下方
python3 manage.py rebuild_index
用‘不错’进行测试
P71 商品搜索-小结
安装和配置
索引文件生成
全文检索的使用
改变分词的方式
安装:
pip3 install django-haystack
pip3 install whoosh
配置
注册haystack
在项目文件中加一个对应的配置项,配置你要使用的引擎是whoosh
以及HAYSTACK_SIGNAL_PROCESSOR当你的表中发生改变的时候会自动地重新帮你生成索引文件
生成对应的索引文件
要搜索的是哪一个表中的数据需要在模型类所在的应用下方新建一个文件,文件名固定为search_indexes.py
在文件中定义一个商品索引类
导入你的模型类
将索引类名格式改为:模型类名+Index
在get_model中返回你的模型类
搜索引擎在建立索引的时候需要告诉他是根据哪些字段去建立索引
use_template=True说明你指定的字段要把它放在一个文件里面templates/search/indexes/你的模型类所在的app/你的模型类名的小写_text.txt
然后在该文件中指定根据哪些字段建立索引数据
全文检索的使用
配置URL
表单搜索时提交方式为get,关键词名字name为q,提交的地址action可以自定义,但是在提交完之后需要haystack框架进行处理,所以在URL中配置的时候两者要保持一致
进行全文搜索出结果之后,haystack会把搜索出的结果传递给templates/search目录下的search.html,传递的上下文包括三个内容:搜索关键字query, 当前页的page对象page,分页的paginator对象paginator。
注:遍历page对象,获取到的是SearchResult类的实例对象,对象的属性object才是模型类的对象
它默认在搜索完数据之后,会对数据进行分页,分页的话默认的是一页20条,如果想要自己指定,有个配置项为HAYSTACK_SEARCH_RESULTS_PER_PAGE
通过该项配置可以控制每页显示的条数
最后改变分词方式