Django 如何实现全文检索?

Posted 编程派

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django 如何实现全文检索?相关的知识,希望对你有一定的参考价值。


作者:chenyvehtung

原文:https://chenyvehtung.github.io/2015/09/11/django-haystack-search.html


背景介绍

本人在开发一个Django应用时,其中的一个需求是搜索功能,而Django本身并没有自带搜索模块,所以必须自己实现。显然,最简单粗暴的方法就是,通过暴搜数据库来查找接收到的文字输入,当数据量相对大一点时,这种方法是很不可取的。本文将要介绍的这个方法是使用Django-haystack这个全文检索框架结合Whoosh检索引擎以及Jieba(结巴)中文分词来实现的。

  • Whoosh是一个纯python实现的全文搜索组件。Whoosh不但功能完善,还非常的快。

  • Haystack是一个第三方的app,专门用来为Django增加全文检索功能,让你可以方便地对model里面的内容进行索引,搜索,简化你的工作。并且Django-haystack设计为支持whoosh,solr,Xapian,Elasticsearc四种全文检索引擎后端,属于一种全文检索的框架。

  • Jieba是一个Python中文分词组件,其包含多种功能,本文使用了其中的"ChineseAnalyzer for Whoosh搜索引擎"功能。

安装依赖

 
   
   
 
  1. pip install django-haystack

  2. pip install whoosh

  3. pip install jieba

具体实现

前端建立搜索框(base.html)

 
   
   
 
  1. <form action="/search" method="get" class="navbar-form navbar-left" role="search">

  2. <div class="form-group">

  3.    <input type="text" class="form-control" name="q" placeholder="输入搜索内容" value=""/>

  4. </div>

  5. <button type="submit" class="btn btn-defaul">

  6.    <span class="glyphicon glyphicon-search"></span>

  7. </button>

  8. </form>

添加URL(urls.py)

在 urls.py中,添加如下内容到 urlpatterns

 
   
   
 
  1. url(r'^search/', include('haystack.urls')),

这样,上一步骤中的action将会指向haystack.urls

建立模型(models.py)

我们将对此文章类中的title和text进行搜索

 
   
   
 
  1. class Article(models.Model):

  2.    class Meta:

  3.        verbose_name = u'文章'

  4.        verbose_name_plural = u'文章'

  5.    article_type = (

  6.        (1, u'失恋'),

  7.        (2, u'暗恋'),

  8.        (3, u'异地恋'),

  9.        (4, u'爱恋'),

  10.    )

  11.    author = models.ForeignKey(settings.AUTH_USER_MODEL)

  12.    title = models.CharField(u'文章标题',max_length=200)

  13.    text = models.TextField(u'文章内容')

  14.    choose_type = models.IntegerField(u'板块选择',choices=article_type, default=article_type[0][0])

  15.    created_time = models.DateTimeField(u'发布时间',default=timezone.now, editable=False)

  16.    # article valid or invalid

  17.    status = models.IntegerField(u'状态',default=1)

  18.    image = models.ImageField(u'文章图片',upload_to='images/articleimg', blank=True)

  19.    def __unicode__(self):

  20.        return self.title

选定模型(search_indexes.py)

在models.py所在目录下,新建search_indexes.py,用来确定我们将选定那个class来建立索引。

 
   
   
 
  1. #! /usr/bin/python

  2. # -*- coding: utf-8 -*-

  3. from misslove.models import Article

  4. from haystack import indexes

  5. class ArticleIndex(indexes.SearchIndex, indexes.Indexable):

  6.    text = indexes.CharField(document=True, use_template=True)

  7.    def get_model(self):

  8.        return Article

  9.    def index_queryset(self, using=None):

  10.        return self.get_model().objects.filter(status=1)

确定属性(article_text.txt)

此步骤中,我们需要建立 classname_text.txt,并在其中指明我们需要对选定类中的哪些属性进行索引。该文件所在的路径应该是 templates/search/indexes/appname。如本项目为: /templates/search/indexes/misslove/article_text.txt,并在文件中写入(请去除其中的"",由于模板语言冲突

 
   
   
 
  1. {{ object.title }}

  2. {{ object.text }}

其中的 title和 text就是我们想要建立索引的文章标题和文章内容。

添加搜索引擎到项目中(whooshcnbackend.py)

由于whoosh搜索引擎无法对中文进行搜索,所以我们需要使用jieba分词来作为whoosh的ChineseAnalyzer,这样就必须对原有的代码进行修改。考虑到安全性以及可移植性,我们可以把 whoosh_backend.py拷贝到项目下再进行修改。 
将 whoosh_backend.py拷贝到 models.py所在的目录下,并将其重命名为 whoosh_cn_backend.py,然后,在该文件中添加

 
   
   
 
  1. from jieba.analyse import ChineseAnalyzer

找到

 
   
   
 
  1. schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=field_class.boost, sortable=True)

然后将其修改为

 
   
   
 
  1. schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True)

这样,便成功地为whoosh引擎添加了jieba分词

选定搜索引擎(settings.py)

我们需要在settings.py中添加haystack应用

 
   
   
 
  1. INSTALLED_APPS = (

  2.    'django.contrib.admin',

  3.    'django.contrib.auth',

  4.    'django.contrib.contenttypes',

  5.    'django.contrib.sessions',

  6.    'django.contrib.messages',

  7.    'django.contrib.staticfiles',

  8.    'misslove',

  9.    'haystack',

  10. )

指定haystack的搜索引擎为上一步骤中修改好的,集成了jieba分词的 whoosh_cn_backend.py,在 settings.py的末尾添加如下代码

 
   
   
 
  1. HAYSTACK_CONNECTIONS = {

  2.    'default': {

  3.        'ENGINE': 'misslove.whoosh_cn_backend.WhooshEngine',

  4.        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),

  5.    },

  6. }

到此,整个搜索的配置工作就完成了。

建立索引(终端)

我们将建立索引,在终端中运行

 
   
   
 
  1. python manage.py rebuild_index

成功后,便会在项目根目录下增加一个 whoosh_index的目录

索引自动更新(settings.py)

在 settings.py中加入

 
   
   
 
  1. HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

这样,当我们成功新建一篇Article之后,服务器便会自动更新索引,将该文章的标题和内容加入到索引中。

搜索结果显示(search.html)

在 templates/search/路径下,新建 search.html,作为搜索结果的前端展示页面。

其中的 page.object_list是搜索之后的返回结果list,我们通过 result.object.attr来获取我们所需要的属性。如本例中,我们使用 result.object.title来获得返回的文章的标题。 
至此,我们便成功地实现了基于django-haystack的全文搜索!

Debug相关

对于Haystack

需要对Haystack进行Debug时,可以参考其官方链接: Debugging Haystack

对于Whoosh

如果要查看whoosh_index中是否有正确存入索引, 可以在Django的shell中( python manage.py shell),输入以下语句

 
   
   
 
  1. from whoosh.index import open_dir

  2. ix = open_dir('whoosh_indexes')

  3. from pprint import pprint

  4. pprint(list(ix.searcher().documents()))

成功的话将会打印出已经建立的全部索引。 
参考链接:


题图:pexels,CC0 授权。

点击阅读原文,查看更多 Python 教程和资源。

以上是关于Django 如何实现全文检索?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django Summernote 中显示编程片段的代码块?

Django全文检索实现:基于HayStack + Whoosh引擎 + Jieba中文分词

django-haystack全文检索

Django:如何在 Postgresql 中对日语(多字节字符串)进行全文搜索

markdown 如何在ViewPager中检索当前片段

用于从 cloudkit 检索单列的代码模式/片段