Advertisement

Django学习笔记(四十五):haystack全文检索框架+whoosh搜索引擎+jieba分词实现全文检索功能

阅读量:

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

  • haystack:全文检索的框架,支持whoosh、solr、Xapian、Elasticsearc四种全文检索引擎,点击查看官方网站
  • whoosh:纯Python编写的全文搜索引擎,虽然性能比不上sphinx、xapian、Elasticsearc等,但是无二进制包,程序不会莫名其妙的崩溃,对于小型的站点,whoosh已经足够使用,点击查看whoosh文档
  • jieba:一款免费的中文分词包,如果觉得不好用可以使用一些收费产品。

1)在虚拟环境中依次安装需要的包。

复制代码
 pip install django-haystack

    
 pip install whoosh
    
 pip install jieba

2)修改settings.py文件,安装应用haystack。

复制代码
 INSTALLED_APPS = (

    
     ...
    
     'haystack',
    
 )

3)在settings.py文件中配置搜索引擎。

复制代码
 ...

    
 HAYSTACK_CONNECTIONS = {
    
     'default': {
    
     #使用whoosh引擎
    
     'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
    
     #索引文件路径
    
     'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
    
     }
    
 }
    
  
    
 # 当添加、修改、删除数据时,自动生成索引
    
 HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
    
  
    
 # 指定搜索结果每页显示的条数
    
 HAYSTACK_SEARCH_RESULTS_PER_PAGE = 1

4)在相应的app目录中添加搜索的配置,文件名必须为search_indexes.py。

复制代码
 # 定义索引类

    
 from haystack import indexes
    
 # 导入你的模型类
    
 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()

5)在templates目录添加search子目录,search子目录下添加indexes子目录,indexes子目录下添加app同名称的子目录goods,goods子目录下添加所需索引模型名小写goodssku_text.txt,以上名称均为固定格式,在goodssku_text.txt添加需要索引的字段

6)建立索引数据,并在whoosh_index文件中生成索引文件

复制代码
    python manage.py rebuild_index


7)页面中的搜索框的一些固定需求,请求方式为get,搜索的别名为q

复制代码
      <div class="search_con fl">

    
         <form method="get" action="/search">
    
             <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
    
             <input type="submit" class="input_btn fr" name="" value="搜索">
    
         </form>
    
 		</div>

8)在项目的urls.py中添加search的路由配置

复制代码
    url(r'^search', include('haystack.urls')), # 全文检索框架

9)使用搜索功能搜索出的结果数据,haystack会将数据返回到templates下面的sreach目录下的sreach.html中

haystack传递的上下文信息包括:

query:搜索的关键字

page:当前页的page对象,遍历page对象,获得到的是SearchResult类的实例对象,对象的属性obje才是模型类的对象

paginator:分页paginator对象

复制代码
 <body>

    
 query:{{ query }}<br>
    
 page:{{ page }}<br>
    
 {% for item in page %}
    
     {{ item.object }}
    
 {% endfor %}<br>
    
 paginator:{{ paginator }}<br>
    
 </body>

10)按照开发需求新建search.html文件

复制代码
 {% extends 'base_detail_list.html' %}

    
 {% block title %}天天生鲜-商品搜索结果列表{% endblock title %}
    
 {% block main_content %}
    
 	<div class="breadcrumb">
    
 		<a href="#">{{ query }}</a>
    
 		<span>></span>
    
 		<a href="#">搜索结果如下:</a>
    
 	</div>
    
  
    
 	<div class="main_wrap clearfix">
    
     <ul class="goods_type_list clearfix">
    
         {% 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 %}
    
     </ul>
    
     <div class="pagenation">
    
             {% if page.has_previous %}
    
 				<a href="/search?q={{ query }}&page={{ page.previous_page_number }}"><上一页</a>
    
             {% endif %}
    
             {% for pindex in paginator.page_range %}
    
                 {% if pindex == page.number %}
    
 				        <a href="/search?q={{ query }}&page={{ pindex }}" class="active">{{ pindex }}</a>
    
                 {% else %}
    
 				        <a href="/search?q={{ query }}&page={{ pindex }}">{{ pindex }}</a>
    
                 {% endif %}
    
 				{% endfor %}
    
             {% if spage.has_next %}
    
 				<a href="/search?q={{ query }}&page={{ page.next_page_number }}">下一页></a>
    
             {% endif %}
    
 			</div>
    
 	</div>
    
 {% endblock main_content %}

全文检索到现在算完成了大半,现在还有一个问题就是查找出来的数据并不完整,如图可见,盒装草莓并没有被搜索出来,原因是因为whoosh默认的引擎对中文分词的效果不是很好,导致它无法将一些词语进行分词搜索出来。

11)所以我们使用jieba中文分词的包,使他有更好的中文分词效果

12)项目中结合whoosh的使用方法,修改默认的whoosh_backend,找到你下载的haystack文件路径

Python\Python36\Lib\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()

13)在相同目录下创建 whoosh_cn_backend.py文件,内容和whoosh_backend.py基本相同,只是将引用StemmingAnalyzer的地方(有两处)全部改成引用ChineseAnalyzer即可

复制代码
 from .ChineseAnalyzer import ChineseAnalyzer

    
  
    
 schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True)
    
  
    
 if highlight:
    
    sa = ChineseAnalyzer()

14)重新修改setting.py里的haysatck配置

复制代码
 # 全文检索框架的配置

    
 HAYSTACK_CONNECTIONS = {
    
     'default': {
    
     # 使用whoosh引擎
    
     'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
    
  
    
     # 索引文件路径
    
     'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
    
     }
    
 }

15)重新创建索引,可以看到已使用jieba分词进行索引

16)重新搜索关键词看是否达到效果

全部评论 (0)

还没有任何评论哟~