搜索是一个日益重要的话题。 用户越来越依赖于搜索将信号与噪声分离并快速找到他们正在寻找的东西。 此外,搜索可以深入了解哪些内容受欢迎,哪些内容很难在网站上找到,以及您可以改进网站的方式。
因此,Haystack可以很简单地集成自定义搜索,同时灵活/强大,足以处理更高级的用例。
Haystack是一个可重复使用的应用程序(也就是说,它仅依赖于自己的代码并专注于提供只是搜索),可以很好地与您控制的应用程序以及第三方应用程序(例如django.contrib。*)一起使用,而无需 修改来源。
Haystack是可插拔的后端(很像Django的数据库层)。
1. Django Haystack 简介
django-haystack 是一个专门提供搜索功能的 django 第三方应用,它支持 Solr、Elasticsearch、Whoosh、Xapian 等多种搜索引擎,配合著名的中文自然语言处理库 jieba 分词,就可以为我们的博客提供一个效s果不错的博客文章搜索系统。
2. 安装必要依赖
要使用 django haystack,首先必须安装它,并且安装一些必要的依赖,具体需要安装的依赖有:
Whoosh。Whoosh 是一个由纯 Python 实现的全文搜索引擎,没有二进制文件等,比较小巧,配置简单方便。
jieba 中文分词。由于 Whoosh 自带的是英文分词,对中文的分词支持不是太好,所以使用 jieba 替换Whoosh 的分词组件。
直接使用 pip 安装这些包即可(安装到你使用的虚拟环境下):pip install whoosh django-haystack jieba
3. Haystack配置
与大多数Django应用程序一样,您应该将Haystack添加到设置文件中的INSTALLED_APPS(通常是settings.py)
例如:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', # Added. 'haystack', # Then your usual apps... 'blog',]
修改您的settings.py
由于我们是中国人,引擎使用Whoosh+jieba。
原因
搜索引擎使用Whoosh,这是一个由纯Python实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,当然性能自然略低。
中文分词Jieba,由于Whoosh自带的是英文分词,对中文的分词支持不是太好,故用jieba替换whoosh的分词组件。
在settings.py中,您需要添加一个设置来告诉您的站点配置文件将在何处以及要使用的后端,以及该后端的其他设置。
HAYSTACK_CONNECTIONS是必需的设置,具体格式如下:
import os HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine', 'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'), },} HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10 HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
HAYSTACK_CONNECTIONS 的 ENGINE 指定了 django haystack 使用的搜索引擎,这里我们使用了 haystack.whoosh_cn_backend.WhooshEngine。PATH 指定了索引文件需要存放的位置,我们设置为项目根目录 BASE_DIR 下的 whoosh_index 文件夹(在建立索引是会自动创建)。
HAYSTACK_SEARCH_RESULTS_PER_PAGE 指定如何对搜索结果分页,这里设置为每 10 项结果为一页。
HAYSTACK_SIGNAL_PROCESSOR 指定什么时候更新索引,这里我们使用 haystack.signals.RealtimeSignalProcessor,作用是每当有文章更新时就更新索引。由于博客文章更新不会太频繁,因此实时更新没有问题。
4. Haystack处理数据
创建搜索索引(SearchIndexes)
SearchIndex对象是Haystack确定应该在搜索索引中放置哪些数据并处理数据流的方式。您可以将它们视为类似于Django模型或表单,因为它们是基于字段的操作/存储数据。
您通常需要为索引的每种类型的模型创建唯一的SearchIndex,您需要注意,必须保证字段名称非常标准化,这样可以在不同模型之间重复使用相同的SearchIndex。
要构建SearchIndex,所有必要的是将index.SearchIndex和indexes.Indexable子类化,定义要存储数据的字段并定义get_model方法。
我们将创建以下NoteIndex以对应我们的Note模型。 此代码通常位于其应用的应用程序内的search_indexes.py文件中,但这不是必需的。 这允许Haystack自动拾取它。 NoteIndex应如下所示:
import datetime from haystack import indexes from myapp.models import Note class NoteIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True) author = indexes.CharField(model_attr='user') pub_date = indexes.DateTimeField(model_attr='pub_date') def get_model(self): return Note def index_queryset(self, using=None): """Used when the entire index for model is updated.""" return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())
每个搜索索引(SearchIndexes)都必须有且只能有一个字段为 document=True。这代表 django haystack 和搜索引擎将使用此字段的内容作为索引进行检索(primary field)。
注意:
当您选择document = True字段时,应在所有SearchIndex类中对其进行一致命名,以避免混淆后端。当然名字你也可以随便改,不过必须保证统一性,最后强烈建议不要改这个字段名字,以防出现未知错误不好排除原因。
为什么要创建索引?
索引就像是一本书的目录,可以为读者提供更快速的导航与查找。在这里也是同样的道理,当数据量非常大的时候,若要从这些数据里找出所有的满足搜索条件的几乎是不太可能的,将会给服务器带来极大的负担。所以我们需要为指定的数据添加一个索引(目录),在这里是为 Post 创建一个索引,索引的实现细节是我们不需要关心的,我们只关心为哪些字段创建索引,如何指定。
另外,haystack 提供了use_template=True 在 text 字段中,允许我们使用数据模板去建立搜索引擎索引的文件。
说得通俗点就是索引里面需要存放一些什么东西,例如 Post 的 title 字段,这样我们可以通过 title 内容来检索 Note数据了。举个例子,假如你搜索 Python ,那么就可以检索出 title 中含有 Python 的Note了,怎么样是不是很简单?
数据模板的路径为 templates/search/indexes/myapp/<model_name>_text.txt(例如 search/indexes/myapp/note_text.txt),其内容为:
templates/search/indexes/blog/post_text.txt {{ object.title }} {{ object.user.get_full_name }} {{ object.body }}
这个数据模板的作用是对 Note.title、Note.body 这两个字段建立索引,当检索的时候会对这两个字段做全文检索匹配,然后将匹配的结果排序后作为搜索结果返回。
另外,我们添加了其他几个字段(author和pub_date)。 当您想要提供其他过滤选项时,这些功能非常有用。 Haystack附带了各种SearchField类来处理大多数类型的数据。
一个常见的主题是允许管理员用户添加未来的内容,但在达到未来日期之前不会在网站上显示。 我们指定一个自定义的index_queryset方法来防止将来的项目编入索引。
5. 配置URL
将SearchView添加到您的URLconf
在您的URLconf中,添加以下行:
url(r'^search/', include('haystack.urls')),
这是为Haystack提供默认的URLconf。 它由一个指向SearchView实例的URLconf组成。 您可以通过任何几个关键字参数来更改搜索结果,或者使用您自己的视图完全覆盖它。
创建搜索结果页面
您的搜索模板(默认情况下为search/search.html)可能非常简单。 如:
{% extends 'base.html' %}{% block content %} <h2>Search</h2> <form method="get" action="."> <table> {{ form.as_table }} <tr> <td> </td> <td> <input type="submit" value="Search"> </td> </tr> </table> {% if query %} <h3>Results</h3> {% for result in page.object_list %} <p> <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a> </p> {% empty %} <p>No results found.</p> {% endfor %} {% if page.has_previous or page.has_next %} <div> {% if page.has_previous %}<a href="?q={{ query }}&page={{ page.previous_page_number }}">{% endif %}« Previous{% if page.has_previous %}</a>{% endif %} | {% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}">{% endif %}Next »{% if page.has_next %}</a>{% endif %} </div> {% endif %} {% else %} {# Show some example queries to run, maybe query syntax, something else? #} {% endif %} </form>{% endblock %}
请注意,page.object_list实际上是SearchResult对象的列表,而不是单个模型。 这些对象包含从搜索索引中的该记录返回的所有数据以及得分。 他们还可以通过{{result.object}}直接访问模型以获得结果。 因此{{result.object.title}}使用数据库中的实际Note对象并访问其标题字段。
6. 修改搜索引擎为中文分词
我们使用 Whoosh 作为搜索引擎,但在 django haystack 中为 Whoosh 指定的分词器是英文分词器,可能会使得搜索结果不理想,我们把这个分词器替换成 jieba 中文分词器。从你安装的 haystack 中把 haystack/backends/whoosh_backends.py 文件拷贝到 blog/ 下,重命名为 whoosh_cn_backends.py(之前我们在 settings.py 中 的 HAYSTACK_CONNECTIONS 指定的就是这个文件),然后找到如下一行代码:
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=field_class.boost, sortable=True)
将其中的 analyzer 改为 ChineseAnalyzer,当然为了使用它,你需要在文件顶部引入:from jieba.analyse import ChineseAnalyzer。
from jieba.analyse import ChineseAnalyzer ... #注意先找到这个再修改,而不是直接添加 schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(),field_boost=field_class.boost, sortable=True)
7. 建立索引文件
现在您已完成所有设置,最后一步是将数据从数据库放入搜索索引。 Haystack附带管理命令,以简化此过程。
只需运行python manage.py rebuild_index即可。 您将获得处理并放置在索引中的模型数量的总计。
8. 最后
您现在可以访问您网站的搜索部分,输入搜索查询并接收查询的搜索结果!恭喜!
参考文章:
http://docs.haystacksearch.org/en/master/tutorial.html
https://www.zmrenwu.com/courses/django-blog-tutorial/materials/27/
https://www.cnblogs.com/xuaijun/p/8027606.html