全文检索
Haystack 为 Django 提供了模块化的搜索,它支持的搜索引擎有 Solr 、 Elasticsearch 、 Whoosh 以及 Xapian 。其中 Elasticsearch 是广受欢迎的开源搜索解决方案。
安装 Haystack
使用 pip 安装 haystack:
pip install django-haystack
使用 pip 安装 elasticsearch:
pip install elasticsearch==5
目前 Haystack 支持 Elasticsearch 1.x 、2.x 以及 5.x 。elasticsearch 会调用 Elasticsearch 服务的 HTTP API。还需要安装并运行 Elasticsearch 服务。有关 Elasticsearch 的安装,可以参考 下载Elasticsearch 。
如果你使用 Docker,也可以使用下面的命令先拉取镜像:
docker pull elasticsearch:5.0
然后创建自定义网络:
docker network create somenetwork
最后运行 Elasticsearch 服务:
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:5.0
配置 Haystack
与许多 Django 应用一样,你需要把 Haystack 加入到配置文件(通常是settings.py
)中的INSTALLED_APPS
中:
INSTALLED_APPS = [
'search.apps.SearchConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'haystack',
]
在settings.py
中,还需要指定使用的搜索引擎并进行相应的配置,以 Elasitcsearch 5.x 为例:
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine',
'URL': 'http://localhost:9200/',
'INDEX_NAME': 'haystack',
},
}
处理数据
定义索引
Haystack 通过SearchIndex
对象决定哪些数据应该被放到搜索引擎的索引中,并使用它们处理输入的数据流。你可以认为它们与 Django 的Models
或者Forms
类似,因为它们都基于域变量(Field),且用于操纵和存储数据。
为了创建SearchIndex
,你需要继承indexes.SearchIndex
和indexes.Indexable
并定义你想要用于存储数据的域(Field)以及一个get_model
方法。
下面在search
应用的目录下创建文件search_indexes.py
,为演出模型(Show)模型创建下面的ShowIndex
:
from datetime import datetime
from haystack import indexes
from search.models import Show
class ShowIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
time = indexes.DateTimeField(model_attr="time")
def get_model(self):
return Show
def index_queryset(self, using=None):
"""
Used when the entire index for model is updated.
"""
return self.get_model().objects.filter(time__gte=datetime.now())
每一个SearchIndex
都需要(且只能)指定一个域(Field)为document=True
,这个域是 Haystack 和搜索引擎在搜索中的首要的域(Field)。通常这个域的名称是text
,如果你想使用其他的名字,则需要在settings.py
中配置HAYSTACK_DOCUMENT_FIELD
为你使用的其他名字。
除此之外,我们还指定text
域为use_template=True
。这允许我们使用一个数据模板来建立搜索引擎需要索引的文档。在 template 目录下创建一个新的模板search/indexes/search/show_text.txt
:
{{ object.title }}
{{ object.venue }}
{{ object.artist }}
我们还添加了一个名为time
的域,我们用这个域在index_queryset
中过滤掉过时的演出。
编写视图
配置 URLconf
在findshow/urls.py
的urlpatterns
中添加 Haystack 的视图:
path('search/', include('haystack.urls')),
搜索模板
在templates/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
对象的列表而不是独立的模型。这些对象包括从记录中按照搜索引擎的索引和排序返回的所有数据。可以通过访问模型得到结果。所以
使用数据库中实际的Show
对象并访问它的title
域。
重建索引
执行下面的命令为数据库中的数据建立索引:
python manage.py rebuild_index
使用标准的SearchIndex
,索引只会在你使用python manage.py rebuild_index
重建索引或使用python manage.py update_index
更新索引时才会发生变化。可以通过 cron 定时任务定期更新索引,有关定时任务的内容可以参考 使用 cron 调度任务 。
当然,如果你的业务流量不大或者你的搜索引擎足够强大。你也可以考虑使用RealtimeSignalProcessor
自动处理数据的更新和删除并即时更新索引。
完成
现在你可以访问你网站的搜索页面,输入一个查询并查看相应的搜索结果。