Django – 使用Haystack+Whoosh配置全文搜索
在此之前我是使用的 ORM的filter来实现的搜索功能。但这个搜索功能实在过于简单,没有多大的实用性。对于一个搜索引擎来说,至少应该能够根据用户的搜索关键词对搜索结果进行排序以及高亮关键字。现在使用 django-haystack 实现这些特性。
Django Haystack 简介
django-haystack 是一个专门提供搜索功能的 django 第三方应用,它还支持 Solr、Elasticsearch、Whoosh、Xapian 等多种搜索引擎,配合著名的中文自然语言处理库 jieba 分词,就可以提供一个效果不错的文字搜索系统。
安装必要依赖
要使用 django haystack,首先必须安装它,并且安装一些必要的依赖,具体需要安装的依赖有:
- Whoosh。Whoosh 是一个由纯 Python 实现的全文搜索引擎,没有二进制文件等,比较小巧,配置简单方便。
- jieba 中文分词。由于 Whoosh 自带的是英文分词,对中文的分词支持不是太好,所以使用 jieba 替换Whoosh 的分词组件。
直接使用 pip 安装这些包即可(安装到你使用的虚拟环境下):pip install django-haystack whoosh jieba
配置 Haystack
安装好 django haystack 后需要在项目的 settings.py 做一些简单的配置。
首先是把 django haystack 加入到 INSTALLED_APPS
选项里:
1 | INSTALLED_APPS = [ |
然后加入如下配置项:
1 | # 配置全文搜索 |
HAYSTACK_CONNECTIONS
的 ENGINE
指定了 django haystack 使用的搜索引擎,这里我们使用了 blog.whoosh_cn_backend.WhooshEngine
,虽然目前这个引擎还不存在,但接下来会创建它。PATH
指定了索引文件需要存放的位置,我们设置为项目根目录 BASE_DIR
下的 whoosh_index 文件夹(在建立索引是会自动创建)。
HAYSTACK_SEARCH_RESULTS_PER_PAGE
指定如何对搜索结果分页,这里设置为每 10 项结果为一页。
HAYSTACK_SIGNAL_PROCESSOR
指定什么时候更新索引,这里我们使用 haystack.signals.RealtimeSignalProcessor
,作用是每当有更新时就更新索引。
处理数据
接下来就要告诉 django haystack 使用那些数据建立索引以及如何存放索引。如果要对 app应用下的数据进行全文检索,做法是在 app应用下建立一个 search_indexes.py 文件,写上如下代码:
1 | from .models import Test |
这是 django haystack 的规定。要相对某个 app 下的数据进行全文检索,就要在该 app 下创建一个 search_indexes.py 文件,然后创建一个 XXIndex 类(XX 为含有被检索数据的模型,如这里的 Test),并且继承 SearchIndex
和 Indexable
。
为什么要创建索引?索引就像是一本书的目录,可以为读者提供更快速的导航与查找。在这里也是同样的道理,当数据量非常大的时候,若要从这些数据里找出所有的满足搜索条件的几乎是不太可能的,将会给服务器带来极大的负担。所以我们需要为指定的数据添加一个索引(目录),在这里是为 Test创建一个索引,索引的实现细节是我们不需要关心的,我们只关心为哪些字段创建索引,如何指定。
每个索引里面必须有且只能有一个字段为 document=True
,这代表 django haystack 和搜索引擎将使用此字段的内容作为索引进行检索(primary field)。注意,如果使用一个字段设置了document=True
,则一般约定此字段名为text
,这是在 SearchIndex
类里面一贯的命名,以防止后台混乱,当然名字你也可以随便改,不过不建议改。
并且,haystack 提供了use_template=True 在 text 字段中,这样就允许我们使用数据模板去建立搜索引擎索引的文件,说得通俗点就是索引里面需要存放一些什么东西,例如 Test的 title 字段,这样我们可以通过 title 内容来检索 Test数据了。举个例子,假如你搜索 Python ,那么就可以检索出 title 中含有 Python 的Test了,怎么样是不是很简单?数据模板的路径为 templates/search/indexes/youapp/\<model_name>_text.txt(例如 templates/search/indexes/app/test_text.txt),其内容为:
1 | {{ object.title }} |
这个数据模板的作用是对 Test.title、Test.content这两个字段建立索引,当检索的时候会对这两个字段做全文检索匹配,然后将匹配的结果排序后作为搜索结果返回。
配置 URL
接下来就是配置 URL,搜索的视图函数和 URL 模式 django haystack 都已经帮我们写好了,只需要项目的 urls.py 中包含它:
1 | urlpatterns = [ |
修改搜索表单
修改一下搜索表单,让它提交数据到 django haystack 搜索视图对应的 URL:
1 | <form role="search" method="get" id="searchform" action="{% url 'haystack_search' %}"> |
主要是把表单的 action 属性改为自己写的视图路径。
创建搜索结果页面
haystack_search
视图函数会将搜索结果传递给模板 search/search.html,因此创建这个模板文件,对搜索结果进行简单渲染:
1 | {% load highlight %} |
高亮关键词
注意到百度的搜索结果页面,含有用户搜索的关键词的地方都是被标红的,在 django haystack 中实现这个效果也非常简单,只需要使用 highlight 模板标签即可,其用法如下:
1 | # 使用默认值 |
在搜索的结果页面也是用高亮语法:
1 | # 就是说在 content 内容中的关键字使用名为 ‘keyword’ 的css样式包裹 |
修改搜索引擎为中文分词
使用 Whoosh 作为搜索引擎,但在 django haystack 中为 Whoosh 指定的分词器是英文分词器,可能会使得搜索结果不理想,我们把这个分词器替换成 jieba 中文分词器。这里需要在项目环境下的Lib\site-packages\haystack\backends的目录中新建一个文件 ChineseAnalyzer.py,其中代码如下:
1 | import jieba |
再把 haystack/backends/whoosh_backends.py 文件复制一份到当前目录下,重命名为 whoosh_cn_backends.py(之前我们在 settings.py 中 的 HAYSTACK_CONNECTIONS
指定的就是这个文件),然后修改whoosh_cn_backends.py中的代码:
1 | # 顶部引入刚才添加的中文分词 |
找到如下一行代码:
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) |
建立索引文件
最后一步就是建立索引文件了,运行命令 python manage.py rebuild_index
就可以建立索引文件了。
效果如下: